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