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