7 #include "debugtools.h"
11 /* ---------------------------------------------------------------------- */
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
;
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
;
40 /* ---------------------------------------------------------------------- */
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
;
53 /* ---------------------------------------------------------------------- */
56 debugstr_an (LPCSTR src
, int n
)
60 if (!src
) return "(null)";
62 dst
= res
= gimme1 (n
* 4 + 6);
64 while (n
-- > 0 && *src
)
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;
75 if (c
>= ' ' && c
<= 126)
80 *dst
++ = '0' + ((c
>> 6) & 7);
81 *dst
++ = '0' + ((c
>> 3) & 7);
82 *dst
++ = '0' + ((c
>> 0) & 7);
97 /* ---------------------------------------------------------------------- */
100 debugstr_a (LPCSTR s
)
102 return debugstr_an (s
, 80);
105 /* ---------------------------------------------------------------------- */
108 debugstr_wn (LPCWSTR src
, int n
)
112 if (!src
) return "(null)";
114 dst
= res
= gimme1 (n
* 5 + 7);
117 while (n
-- > 0 && *src
)
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;
128 if (c
>= ' ' && c
<= 126)
133 sprintf(dst
,"%04x",c
);
149 /* ---------------------------------------------------------------------- */
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
)
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
)
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
)
183 if (!id
) return "(null)";
187 sprintf( str
, "<guid-0x%04x>", LOWORD(id
) );
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] );
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
;
211 char *pos
= info
->output
;
213 write( 2, pos
, p
- pos
);
214 /* move beginning of next line to start of buffer */
215 while ((*pos
= *p
++)) pos
++;
221 /* ---------------------------------------------------------------------- */
223 int dbg_printf(const char *format
, ...)
228 va_start(valist
, format
);
229 ret
= dbg_vprintf( format
, valist
);
236 /*--< Function >---------------------------------------------------------
241 ** This function creates a hex dump, with a readable ascii
242 ** section, for displaying memory.
245 ** 1. ptr Pointer to memory
246 ** 2. len How much to dump.
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 **-------------------------------------------------------------------------*/
256 debugstr_hex_dump (const void *ptr
, int len
)
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 **-----------------------------------------------------------------*/
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
309 **-----------------------------------------------------------------*/
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
319 **-----------------------------------------------------------------*/
320 sprintf (tempbuf
, "%c", isprint(*p
) ? *p
: '.');
321 strcat (charbuf
, tempbuf
);
324 /*-----------------------------------------------------------------------
325 ** Flush the last line, if any
326 **---------------------------------------------------------------------*/
329 sprintf(outptr
, " %-43.43s %-16.16s\n", dumpbuf
, charbuf
);
330 outptr
+= strlen(outptr
);
334 } /* End function dbg_hex_dump */