- fixes, loading of settings per user
[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 LPSTR
56 debugstr_an (LPCSTR src, int n)
57 {
58   LPSTR dst, res;
59
60   if (!src) return "(null)";
61   if (n < 0) n = 0;
62   dst = res = gimme1 (n * 4 + 6);
63   *dst++ = '"';
64   while (n-- > 0 && *src)
65     {
66       BYTE c = *src++;
67       switch (c)
68         {
69         case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
70         case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
71         case '\t': *dst++ = '\\'; *dst++ = 't'; break;
72         case '"': *dst++ = '\\'; *dst++ = '"'; break;
73         case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
74         default:
75           if (c >= ' ' && c <= 126)
76             *dst++ = c;
77           else
78             {
79               *dst++ = '\\';
80               *dst++ = '0' + ((c >> 6) & 7);
81               *dst++ = '0' + ((c >> 3) & 7);
82               *dst++ = '0' + ((c >> 0) & 7);
83             }
84         }
85     }
86   *dst++ = '"';
87   if (*src)
88     {
89       *dst++ = '.';
90       *dst++ = '.';
91       *dst++ = '.';
92     }
93   *dst = '\0';
94   return res;
95 }
96
97 /* ---------------------------------------------------------------------- */
98
99 LPSTR
100 debugstr_a (LPCSTR s)
101 {
102   return debugstr_an (s, 80);
103 }
104
105 /* ---------------------------------------------------------------------- */
106
107 LPSTR
108 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   return res;
147 }
148
149 /* ---------------------------------------------------------------------- */
150
151 LPSTR
152 debugstr_w (LPCWSTR s)
153 {
154   return debugstr_wn (s, 80);
155 }
156
157 /* ---------------------------------------------------------------------- */
158 /* This routine returns a nicely formated name of the resource res
159    If the resource name is a string, it will return '<res-name>'
160    If it is a number, it will return #<4-digit-hex-number> */
161 LPSTR debugres_a( LPCSTR res )
162 {
163     char resname[10];
164     if (HIWORD(res)) return debugstr_a(res);
165     sprintf(resname, "#%04x", LOWORD(res));
166     return debugstr_a (resname);
167 }
168
169 LPSTR debugres_w( LPCWSTR res )
170 {
171     char resname[10];
172     if (HIWORD(res)) return debugstr_w(res);
173     sprintf(resname, "#%04x", LOWORD(res));
174     return debugstr_a (resname);
175 }
176
177 /* ---------------------------------------------------------------------- */
178
179 LPSTR debugstr_guid( const GUID *id )
180 {
181     LPSTR str;
182
183     if (!id) return "(null)";
184     if (!HIWORD(id))
185     {
186         str = gimme1(12);
187         sprintf( str, "<guid-0x%04x>", LOWORD(id) );
188     }
189     else
190     {
191         str = gimme1(40);
192         sprintf( str, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
193                  id->Data1, id->Data2, id->Data3,
194                  id->Data4[0], id->Data4[1], id->Data4[2], id->Data4[3],
195                  id->Data4[4], id->Data4[5], id->Data4[6], id->Data4[7] );
196     }
197     return str;
198 }
199
200 /* ---------------------------------------------------------------------- */
201
202 int dbg_vprintf( const char *format, va_list args )
203 {
204     struct debug_info *info = get_info();
205
206     int ret = vsprintf( info->out_pos, format, args );
207     char *p = strrchr( info->out_pos, '\n' );
208     if (!p) info->out_pos += ret;
209     else
210     {
211         char *pos = info->output;
212         p++;
213         write( 2, pos, p - pos );
214         /* move beginning of next line to start of buffer */
215         while ((*pos = *p++)) pos++;
216         info->out_pos = pos;
217     }
218     return ret;
219 }
220
221 /* ---------------------------------------------------------------------- */
222
223 int dbg_printf(const char *format, ...)
224 {
225     int ret;
226     va_list valist;
227
228     va_start(valist, format);
229     ret = dbg_vprintf( format, valist);
230     va_end(valist);
231     return ret;
232 }
233
234
235
236 /*--< Function >---------------------------------------------------------
237 **  
238 **              debugstr_hex_dump
239 **              
240 **  Description:
241 **      This function creates a hex dump, with a readable ascii
242 **  section, for displaying memory.
243 **  
244 **  Parameters:
245 **      1.  ptr             Pointer to memory
246 **      2.  len             How much to dump.
247 **
248 **  Returns:
249 **    Temporarily allocated buffer, with the hex dump in it.
250 **  Don't rely on this pointer being around for very long, just
251 **  long enough to use it in a TRACE statement; e.g.:
252 **  TRACE("struct dump is \n%s", debugstr_hex_dump(&x, sizeof(x)));
253 **          
254 **-------------------------------------------------------------------------*/
255 LPSTR 
256 debugstr_hex_dump (const void *ptr, int len)
257 {
258     /* Locals */
259     char          dumpbuf[59];
260     char          charbuf[20];
261     char          tempbuf[8];
262     const char    *p;
263     int           i;
264     unsigned int  nosign;
265     LPSTR         dst;
266     LPSTR         outptr;
267
268 /* Begin function dbg_hex_dump */
269
270     /*-----------------------------------------------------------------------
271     **  Allocate an output buffer
272     **      A reasonable value is one line overhand (80 chars), and
273     **      then one line (80) for every 16 bytes.
274     **---------------------------------------------------------------------*/
275     outptr = dst = gimme1 ((len * (80 / 16)) + 80);
276
277     /*-----------------------------------------------------------------------
278     **  Loop throught the input buffer, one character at a time
279     **---------------------------------------------------------------------*/
280     for (i = 0, p = ptr; (i < len); i++, p++)
281     {
282
283         /*-------------------------------------------------------------------
284         **  If we're just starting a line, 
285         **      we need to possibly flush the old line, and then
286         **      intialize the line buffer.
287         **-----------------------------------------------------------------*/
288         if ((i % 16) == 0)
289         {
290             if (i)
291             {
292                 sprintf(outptr, "  %-43.43s   %-16.16s\n", dumpbuf, charbuf);
293                 outptr += strlen(outptr);
294             }
295             sprintf (dumpbuf, "%04x: ", i);
296             strcpy (charbuf, "");
297         }
298
299         /*-------------------------------------------------------------------
300         **  Add the current data byte to the dump section.
301         **-----------------------------------------------------------------*/
302         nosign = (unsigned char) *p;
303         sprintf (tempbuf, "%02X", nosign);
304
305         /*-------------------------------------------------------------------
306         **  If we're two DWORDS through, add a hyphen for readability,
307         **      if it's a DWORD boundary, add a space for more
308         **      readability.
309         **-----------------------------------------------------------------*/
310         if ((i % 16) == 7)
311             strcat(tempbuf, " - ");
312         else if ( (i % 4) == 3)
313             strcat(tempbuf, " ");
314         strcat (dumpbuf, tempbuf);
315
316         /*-------------------------------------------------------------------
317         **  Add the current byte to the character display part of the
318         **      hex dump
319         **-----------------------------------------------------------------*/
320         sprintf (tempbuf, "%c", isprint(*p) ? *p : '.');
321         strcat (charbuf, tempbuf);
322     }
323
324     /*-----------------------------------------------------------------------
325     **  Flush the last line, if any
326     **---------------------------------------------------------------------*/
327     if (i > 0)
328     {
329         sprintf(outptr, "  %-43.43s   %-16.16s\n", dumpbuf, charbuf);
330         outptr += strlen(outptr);
331     }
332
333     return(dst);
334 } /* End function dbg_hex_dump */
335
336
337