No longer directly accessing debuggee memory.
[wine] / misc / debugstr.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <ctype.h>
6
7 #include "debugtools.h"
8 #include "wtypes.h"
9 #include "thread.h"
10
11 /* ---------------------------------------------------------------------- */
12
13 struct debug_info
14 {
15     char *str_pos;       /* current position in strings buffer */
16     char *out_pos;       /* current position in output buffer */
17     char  strings[500];  /* buffer for temporary strings */
18     char  output[500];   /* current output line */
19 };
20
21 static struct debug_info tmp;
22
23 static inline struct debug_info *get_info(void)
24 {
25     struct debug_info *info = NtCurrentTeb()->debug_info;
26     if (!info)
27     {
28         /* setup the temp structure in case HeapAlloc wants to print something */
29         NtCurrentTeb()->debug_info = &tmp;
30         tmp.str_pos = tmp.strings;
31         tmp.out_pos = tmp.output;
32         info = HeapAlloc( GetProcessHeap(), 0, sizeof(*info) );
33         info->str_pos = info->strings;
34         info->out_pos = info->output;
35         NtCurrentTeb()->debug_info = info;
36     }
37     return info;
38 }
39
40 /* ---------------------------------------------------------------------- */
41
42 static void *
43 gimme1 (int n)
44 {
45     struct debug_info *info = get_info();
46     char *res = info->str_pos;
47
48     if (res + n >= &info->strings[sizeof(info->strings)]) res = info->strings;
49     info->str_pos = res + n;
50     return res;
51 }
52
53 /* ---------------------------------------------------------------------- */
54
55 /* release extra space that we requested in gimme1() */
56 static inline void release( void *ptr )
57 {
58     struct debug_info *info = NtCurrentTeb()->debug_info;
59     info->str_pos = ptr;
60 }
61
62 /* ---------------------------------------------------------------------- */
63
64 LPCSTR debugstr_an (LPCSTR src, int n)
65 {
66   LPSTR dst, res;
67
68   if (!src) return "(null)";
69   if (n < 0) n = 0;
70   dst = res = gimme1 (n * 4 + 6);
71   *dst++ = '"';
72   while (n-- > 0 && *src)
73     {
74       BYTE c = *src++;
75       switch (c)
76         {
77         case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
78         case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
79         case '\t': *dst++ = '\\'; *dst++ = 't'; break;
80         case '"': *dst++ = '\\'; *dst++ = '"'; break;
81         case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
82         default:
83           if (c >= ' ' && c <= 126)
84             *dst++ = c;
85           else
86             {
87               *dst++ = '\\';
88               *dst++ = '0' + ((c >> 6) & 7);
89               *dst++ = '0' + ((c >> 3) & 7);
90               *dst++ = '0' + ((c >> 0) & 7);
91             }
92         }
93     }
94   *dst++ = '"';
95   if (*src)
96     {
97       *dst++ = '.';
98       *dst++ = '.';
99       *dst++ = '.';
100     }
101   *dst++ = '\0';
102   release( dst );
103   return res;
104 }
105
106 /* ---------------------------------------------------------------------- */
107
108 LPCSTR debugstr_wn (LPCWSTR src, int n)
109 {
110   LPSTR dst, res;
111
112   if (!src) return "(null)";
113   if (n < 0) n = 0;
114   dst = res = gimme1 (n * 5 + 7);
115   *dst++ = 'L';
116   *dst++ = '"';
117   while (n-- > 0 && *src)
118     {
119       WORD c = *src++;
120       switch (c)
121         {
122         case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
123         case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
124         case '\t': *dst++ = '\\'; *dst++ = 't'; break;
125         case '"': *dst++ = '\\'; *dst++ = '"'; break;
126         case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
127         default:
128           if (c >= ' ' && c <= 126)
129             *dst++ = c;
130           else 
131             {
132               *dst++ = '\\';
133               sprintf(dst,"%04x",c);
134               dst+=4;
135             }
136         }
137     }
138   *dst++ = '"';
139   if (*src)
140     {
141       *dst++ = '.';
142       *dst++ = '.';
143       *dst++ = '.';
144     }
145   *dst++ = '\0';
146   release( dst );
147   return res;
148 }
149
150 /* ---------------------------------------------------------------------- */
151 /* This routine returns a nicely formated name of the resource res
152    If the resource name is a string, it will return '<res-name>'
153    If it is a number, it will return #<4-digit-hex-number> */
154 LPCSTR debugres_a( LPCSTR res )
155 {
156     char *resname;
157     if (HIWORD(res)) return debugstr_a(res);
158     resname = gimme1(6);
159     sprintf(resname, "#%04x", LOWORD(res) );
160     return resname;
161 }
162
163 LPCSTR debugres_w( LPCWSTR res )
164 {
165     char *resname;
166     if (HIWORD(res)) return debugstr_w(res);
167     resname = gimme1(6);
168     sprintf( resname, "#%04x", LOWORD(res) );
169     return resname;
170 }
171
172 /* ---------------------------------------------------------------------- */
173
174 LPCSTR debugstr_guid( const GUID *id )
175 {
176     LPSTR str;
177
178     if (!id) return "(null)";
179     if (!HIWORD(id))
180     {
181         str = gimme1(12);
182         sprintf( str, "<guid-0x%04x>", LOWORD(id) );
183     }
184     else
185     {
186         str = gimme1(40);
187         sprintf( str, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
188                  id->Data1, id->Data2, id->Data3,
189                  id->Data4[0], id->Data4[1], id->Data4[2], id->Data4[3],
190                  id->Data4[4], id->Data4[5], id->Data4[6], id->Data4[7] );
191     }
192     return str;
193 }
194
195 /* ---------------------------------------------------------------------- */
196
197 int dbg_vprintf( const char *format, va_list args )
198 {
199     struct debug_info *info = get_info();
200
201     int ret = vsprintf( info->out_pos, format, args );
202     char *p = strrchr( info->out_pos, '\n' );
203     if (!p) info->out_pos += ret;
204     else
205     {
206         char *pos = info->output;
207         p++;
208         write( 2, pos, p - pos );
209         /* move beginning of next line to start of buffer */
210         while ((*pos = *p++)) pos++;
211         info->out_pos = pos;
212     }
213     return ret;
214 }
215
216 /* ---------------------------------------------------------------------- */
217
218 int dbg_printf(const char *format, ...)
219 {
220     int ret;
221     va_list valist;
222
223     va_start(valist, format);
224     ret = dbg_vprintf( format, valist);
225     va_end(valist);
226     return ret;
227 }
228
229
230 /*--< Function >---------------------------------------------------------
231 **  
232 **              debugstr_hex_dump
233 **              
234 **  Description:
235 **      This function creates a hex dump, with a readable ascii
236 **  section, for displaying memory.
237 **  
238 **  Parameters:
239 **      1.  ptr             Pointer to memory
240 **      2.  len             How much to dump.
241 **
242 **  Returns:
243 **    Temporarily allocated buffer, with the hex dump in it.
244 **  Don't rely on this pointer being around for very long, just
245 **  long enough to use it in a TRACE statement; e.g.:
246 **  TRACE("struct dump is \n%s", debugstr_hex_dump(&x, sizeof(x)));
247 **          
248 **-------------------------------------------------------------------------*/
249 LPCSTR debugstr_hex_dump (const void *ptr, int len)
250 {
251     /* Locals */
252     char          dumpbuf[59];
253     char          charbuf[20];
254     char          tempbuf[8];
255     const char    *p;
256     int           i;
257     unsigned int  nosign;
258     LPSTR         dst;
259     LPSTR         outptr;
260
261 /* Begin function dbg_hex_dump */
262
263     /*-----------------------------------------------------------------------
264     **  Allocate an output buffer
265     **      A reasonable value is one line overhand (80 chars), and
266     **      then one line (80) for every 16 bytes.
267     **---------------------------------------------------------------------*/
268     outptr = dst = gimme1 ((len * (80 / 16)) + 80);
269
270     /*-----------------------------------------------------------------------
271     **  Loop throught the input buffer, one character at a time
272     **---------------------------------------------------------------------*/
273     for (i = 0, p = ptr; (i < len); i++, p++)
274     {
275
276         /*-------------------------------------------------------------------
277         **  If we're just starting a line, 
278         **      we need to possibly flush the old line, and then
279         **      intialize the line buffer.
280         **-----------------------------------------------------------------*/
281         if ((i % 16) == 0)
282         {
283             if (i)
284             {
285                 sprintf(outptr, "  %-43.43s   %-16.16s\n", dumpbuf, charbuf);
286                 outptr += strlen(outptr);
287             }
288             sprintf (dumpbuf, "%04x: ", i);
289             strcpy (charbuf, "");
290         }
291
292         /*-------------------------------------------------------------------
293         **  Add the current data byte to the dump section.
294         **-----------------------------------------------------------------*/
295         nosign = (unsigned char) *p;
296         sprintf (tempbuf, "%02X", nosign);
297
298         /*-------------------------------------------------------------------
299         **  If we're two DWORDS through, add a hyphen for readability,
300         **      if it's a DWORD boundary, add a space for more
301         **      readability.
302         **-----------------------------------------------------------------*/
303         if ((i % 16) == 7)
304             strcat(tempbuf, " - ");
305         else if ( (i % 4) == 3)
306             strcat(tempbuf, " ");
307         strcat (dumpbuf, tempbuf);
308
309         /*-------------------------------------------------------------------
310         **  Add the current byte to the character display part of the
311         **      hex dump
312         **-----------------------------------------------------------------*/
313         sprintf (tempbuf, "%c", isprint(*p) ? *p : '.');
314         strcat (charbuf, tempbuf);
315     }
316
317     /*-----------------------------------------------------------------------
318     **  Flush the last line, if any
319     **---------------------------------------------------------------------*/
320     if (i > 0)
321     {
322         sprintf(outptr, "  %-43.43s   %-16.16s\n", dumpbuf, charbuf);
323         outptr += strlen(outptr);
324     }
325
326     return(dst);
327 } /* End function dbg_hex_dump */
328
329
330