Fixed first/last playable frame referencing.
[wine.git] / misc / debugstr.c
blob6ffdf31fa1aecf697f7841268d9321d178b17444
1 #include <stdarg.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <ctype.h>
7 #include "debugstr.h"
8 #include "debugtools.h"
9 #include "xmalloc.h"
11 /* ---------------------------------------------------------------------- */
13 #define SAVE_STRING_COUNT 50
14 static void *strings[SAVE_STRING_COUNT];
15 static int nextstring;
17 /* ---------------------------------------------------------------------- */
19 static void *
20 gimme1 (int n)
22 void *res;
23 if (strings[nextstring]) free (strings[nextstring]);
24 res = strings[nextstring] = xmalloc (n);
25 if (++nextstring == SAVE_STRING_COUNT) nextstring = 0;
26 return res;
29 /* ---------------------------------------------------------------------- */
31 LPSTR
32 debugstr_an (LPCSTR src, int n)
34 LPSTR dst, res;
36 if (!src) return "(null)";
37 if (n < 0) n = 0;
38 dst = res = gimme1 (n * 4 + 10);
39 *dst++ = '"';
40 while (n-- > 0 && *src)
42 BYTE c = *src++;
43 switch (c)
45 case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
46 case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
47 case '\t': *dst++ = '\\'; *dst++ = 't'; break;
48 case '"': *dst++ = '\\'; *dst++ = '"'; break;
49 case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
50 default:
51 if (c >= ' ' && c <= 126)
52 *dst++ = c;
53 else
55 *dst++ = '\\';
56 *dst++ = '0' + ((c >> 6) & 7);
57 *dst++ = '0' + ((c >> 3) & 7);
58 *dst++ = '0' + ((c >> 0) & 7);
62 if (*src)
64 *dst++ = '.';
65 *dst++ = '.';
66 *dst++ = '.';
68 *dst++ = '"';
69 *dst = 0;
70 return res;
73 /* ---------------------------------------------------------------------- */
75 LPSTR
76 debugstr_a (LPCSTR s)
78 return debugstr_an (s, 80);
81 /* ---------------------------------------------------------------------- */
83 LPSTR
84 debugstr_wn (LPCWSTR src, int n)
86 LPSTR dst, res;
88 if (!src) return "(null)";
89 if (n < 0) n = 0;
90 dst = res = gimme1 (n * 4 + 10);
91 *dst++ = '"';
92 while (n-- > 0 && *src)
94 WORD c = *src++;
95 switch (c)
97 case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
98 case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
99 case '\t': *dst++ = '\\'; *dst++ = 't'; break;
100 case '"': *dst++ = '\\'; *dst++ = '"'; break;
101 case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
102 default:
103 if (c >= ' ' && c <= 126)
104 *dst++ = c;
105 else
107 *dst++ = '\\';
108 *dst++ = '0' + ((c >> 6) & 7);
109 *dst++ = '0' + ((c >> 3) & 7);
110 *dst++ = '0' + ((c >> 0) & 7);
114 if (*src)
116 *dst++ = '.';
117 *dst++ = '.';
118 *dst++ = '.';
120 *dst++ = '"';
121 *dst = 0;
122 return res;
125 /* ---------------------------------------------------------------------- */
127 LPSTR
128 debugstr_w (LPCWSTR s)
130 return debugstr_wn (s, 80);
133 /* ---------------------------------------------------------------------- */
134 /* This routine returns a nicely formated name of the resource res
135 If the resource name is a string, it will return '<res-name>'
136 If it is a number, it will return #<4-digit-hex-number> */
137 LPSTR debugres_a( LPCSTR res )
139 char resname[10];
140 if (HIWORD(res)) return debugstr_a(res);
141 sprintf(resname, "#%04x", LOWORD(res));
142 return debugstr_a (resname);
145 LPSTR debugres_w( LPCWSTR res )
147 char resname[10];
148 if (HIWORD(res)) return debugstr_w(res);
149 sprintf(resname, "#%04x", LOWORD(res));
150 return debugstr_a (resname);
153 /* ---------------------------------------------------------------------- */
155 void debug_dumpstr (LPCSTR s)
157 fputc ('"', stderr);
158 while (*s)
160 switch (*s)
162 case '\\':
163 case '"':
164 fputc ('\\', stderr);
165 fputc (*s, stderr);
166 break;
167 case '\n':
168 fputc ('\\', stderr);
169 fputc ('n', stderr);
170 break;
171 case '\r':
172 fputc ('\\', stderr);
173 fputc ('r', stderr);
174 break;
175 case '\t':
176 fputc ('\\', stderr);
177 fputc ('t', stderr);
178 break;
179 default:
180 if (*s<' ')
181 fprintf (stderr, "\\0x%02x", *s);
182 else
183 fputc (*s, stderr);
185 s++;
187 fputc ('"', stderr);
190 /* ---------------------------------------------------------------------- */
192 int dbg_printf(const char *format, ...)
194 int ret;
195 va_list valist;
197 va_start(valist, format);
198 ret = vfprintf(stderr, format, valist);
199 va_end(valist);
200 return ret;
205 /*--< Function >---------------------------------------------------------
207 ** debugstr_hex_dump
209 ** Description:
210 ** This function creates a hex dump, with a readable ascii
211 ** section, for displaying memory.
213 ** Parameters:
214 ** 1. ptr Pointer to memory
215 ** 2. len How much to dump.
217 ** Returns:
218 ** Temporarily allocated buffer, with the hex dump in it.
219 ** Don't rely on this pointer being around for very long, just
220 ** long enough to use it in a TRACE statement; e.g.:
221 ** TRACE("struct dump is \n%s", debugstr_hex_dump(&x, sizeof(x)));
223 **-------------------------------------------------------------------------*/
224 LPSTR
225 debugstr_hex_dump (const void *ptr, int len)
227 /* Locals */
228 char dumpbuf[59];
229 char charbuf[20];
230 char tempbuf[8];
231 const char *p;
232 int i;
233 unsigned int nosign;
234 LPSTR dst;
235 LPSTR outptr;
237 /* Begin function dbg_hex_dump */
239 /*-----------------------------------------------------------------------
240 ** Allocate an output buffer
241 ** A reasonable value is one line overhand (80 chars), and
242 ** then one line (80) for every 16 bytes.
243 **---------------------------------------------------------------------*/
244 outptr = dst = gimme1 ((len * (80 / 16)) + 80);
246 /*-----------------------------------------------------------------------
247 ** Loop throught the input buffer, one character at a time
248 **---------------------------------------------------------------------*/
249 for (i = 0, p = ptr; (i < len); i++, p++)
252 /*-------------------------------------------------------------------
253 ** If we're just starting a line,
254 ** we need to possibly flush the old line, and then
255 ** intialize the line buffer.
256 **-----------------------------------------------------------------*/
257 if ((i % 16) == 0)
259 if (i)
261 sprintf(outptr, " %-43.43s %-16.16s\n", dumpbuf, charbuf);
262 outptr += strlen(outptr);
264 sprintf (dumpbuf, "%04x: ", i);
265 strcpy (charbuf, "");
268 /*-------------------------------------------------------------------
269 ** Add the current data byte to the dump section.
270 **-----------------------------------------------------------------*/
271 nosign = (unsigned char) *p;
272 sprintf (tempbuf, "%02X", nosign);
274 /*-------------------------------------------------------------------
275 ** If we're two DWORDS through, add a hyphen for readability,
276 ** if it's a DWORD boundary, add a space for more
277 ** readability.
278 **-----------------------------------------------------------------*/
279 if ((i % 16) == 7)
280 strcat(tempbuf, " - ");
281 else if ( (i % 4) == 3)
282 strcat(tempbuf, " ");
283 strcat (dumpbuf, tempbuf);
285 /*-------------------------------------------------------------------
286 ** Add the current byte to the character display part of the
287 ** hex dump
288 **-----------------------------------------------------------------*/
289 sprintf (tempbuf, "%c", isprint(*p) ? *p : '.');
290 strcat (charbuf, tempbuf);
293 /*-----------------------------------------------------------------------
294 ** Flush the last line, if any
295 **---------------------------------------------------------------------*/
296 if (i > 0)
298 sprintf(outptr, " %-43.43s %-16.16s\n", dumpbuf, charbuf);
299 outptr += strlen(outptr);
302 return(dst);
303 } /* End function dbg_hex_dump */