Fixed memory overwrite bug.
[wine/testsucceed.git] / misc / debugstr.c
blobeb17938ae44983c51ef5986f6d98cd6c07ec14d5
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <ctype.h>
7 #include "debugtools.h"
8 #include "wtypes.h"
9 #include "thread.h"
11 /* ---------------------------------------------------------------------- */
13 struct debug_info
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 */
21 static struct debug_info tmp;
23 static inline struct debug_info *get_info(void)
25 struct debug_info *info = NtCurrentTeb()->debug_info;
26 if (!info)
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;
37 return info;
40 /* ---------------------------------------------------------------------- */
42 static void *
43 gimme1 (int n)
45 struct debug_info *info = get_info();
46 char *res = info->str_pos;
48 if (res + n >= &info->strings[sizeof(info->strings)]) res = info->strings;
49 info->str_pos = res + n;
50 return res;
53 /* ---------------------------------------------------------------------- */
55 LPSTR
56 debugstr_an (LPCSTR src, int n)
58 LPSTR dst, res;
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)
66 BYTE c = *src++;
67 switch (c)
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
79 *dst++ = '\\';
80 *dst++ = '0' + ((c >> 6) & 7);
81 *dst++ = '0' + ((c >> 3) & 7);
82 *dst++ = '0' + ((c >> 0) & 7);
86 *dst++ = '"';
87 if (*src)
89 *dst++ = '.';
90 *dst++ = '.';
91 *dst++ = '.';
93 *dst = '\0';
94 return res;
97 /* ---------------------------------------------------------------------- */
99 LPSTR
100 debugstr_a (LPCSTR s)
102 return debugstr_an (s, 80);
105 /* ---------------------------------------------------------------------- */
107 LPSTR
108 debugstr_wn (LPCWSTR src, int n)
110 LPSTR dst, res;
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)
119 WORD c = *src++;
120 switch (c)
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
132 *dst++ = '\\';
133 sprintf(dst,"%04x",c);
134 dst+=4;
138 *dst++ = '"';
139 if (*src)
141 *dst++ = '.';
142 *dst++ = '.';
143 *dst++ = '.';
145 *dst = '\0';
146 return res;
149 /* ---------------------------------------------------------------------- */
151 LPSTR
152 debugstr_w (LPCWSTR s)
154 return debugstr_wn (s, 80);
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 )
163 char resname[10];
164 if (HIWORD(res)) return debugstr_a(res);
165 sprintf(resname, "#%04x", LOWORD(res));
166 return debugstr_a (resname);
169 LPSTR debugres_w( LPCWSTR res )
171 char resname[10];
172 if (HIWORD(res)) return debugstr_w(res);
173 sprintf(resname, "#%04x", LOWORD(res));
174 return debugstr_a (resname);
177 /* ---------------------------------------------------------------------- */
179 LPSTR debugstr_guid( const GUID *id )
181 LPSTR str;
183 if (!id) return "(null)";
184 if (!HIWORD(id))
186 str = gimme1(12);
187 sprintf( str, "<guid-0x%04x>", LOWORD(id) );
189 else
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] );
197 return str;
200 /* ---------------------------------------------------------------------- */
202 int dbg_vprintf( const char *format, va_list args )
204 struct debug_info *info = get_info();
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
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;
218 return ret;
221 /* ---------------------------------------------------------------------- */
223 int dbg_printf(const char *format, ...)
225 int ret;
226 va_list valist;
228 va_start(valist, format);
229 ret = dbg_vprintf( format, valist);
230 va_end(valist);
231 return ret;
236 /*--< Function >---------------------------------------------------------
238 ** debugstr_hex_dump
240 ** Description:
241 ** This function creates a hex dump, with a readable ascii
242 ** section, for displaying memory.
244 ** Parameters:
245 ** 1. ptr Pointer to memory
246 ** 2. len How much to dump.
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)));
254 **-------------------------------------------------------------------------*/
255 LPSTR
256 debugstr_hex_dump (const void *ptr, int len)
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;
268 /* Begin function dbg_hex_dump */
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);
277 /*-----------------------------------------------------------------------
278 ** Loop throught the input buffer, one character at a time
279 **---------------------------------------------------------------------*/
280 for (i = 0, p = ptr; (i < len); i++, p++)
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)
290 if (i)
292 sprintf(outptr, " %-43.43s %-16.16s\n", dumpbuf, charbuf);
293 outptr += strlen(outptr);
295 sprintf (dumpbuf, "%04x: ", i);
296 strcpy (charbuf, "");
299 /*-------------------------------------------------------------------
300 ** Add the current data byte to the dump section.
301 **-----------------------------------------------------------------*/
302 nosign = (unsigned char) *p;
303 sprintf (tempbuf, "%02X", nosign);
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);
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);
324 /*-----------------------------------------------------------------------
325 ** Flush the last line, if any
326 **---------------------------------------------------------------------*/
327 if (i > 0)
329 sprintf(outptr, " %-43.43s %-16.16s\n", dumpbuf, charbuf);
330 outptr += strlen(outptr);
333 return(dst);
334 } /* End function dbg_hex_dump */