Moved specification of relay and snoop include/exclude functions to
[wine] / library / debug.c
1 /*
2  * Management of the debugging channels
3  *
4  * Copyright 2000 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <stdarg.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <ctype.h>
30
31 #include "wine/debug.h"
32 #include "wine/library.h"
33 #include "wine/unicode.h"
34
35 struct dll
36 {
37     struct dll   *next;        /* linked list of dlls */
38     struct dll   *prev;
39     char * const *channels;    /* array of channels */
40     int           nb_channels; /* number of channels in array */
41 };
42
43 static struct dll *first_dll;
44
45 struct debug_option
46 {
47     struct debug_option *next;       /* next option in list */
48     unsigned char        set;        /* bits to set */
49     unsigned char        clear;      /* bits to clear */
50     char                 name[14];   /* channel name, or empty for "all" */
51 };
52
53 static struct debug_option *first_option;
54 static struct debug_option *last_option;
55
56 static const char * const debug_classes[] = { "fixme", "err", "warn", "trace" };
57
58 static int cmp_name( const void *p1, const void *p2 )
59 {
60     const char *name = p1;
61     const char * const *chan = p2;
62     return strcmp( name, *chan + 1 );
63 }
64
65 /* apply a debug option to the channels of a given dll */
66 static void apply_option( struct dll *dll, const struct debug_option *opt )
67 {
68     if (opt->name[0])
69     {
70         char **dbch = bsearch( opt->name, dll->channels, dll->nb_channels,
71                                sizeof(*dll->channels), cmp_name );
72         if (dbch) **dbch = (**dbch & ~opt->clear) | opt->set;
73     }
74     else /* all */
75     {
76         int i;
77         for (i = 0; i < dll->nb_channels; i++)
78             dll->channels[i][0] = (dll->channels[i][0] & ~opt->clear) | opt->set;
79     }
80 }
81
82 /* register a new set of channels for a dll */
83 void *__wine_dbg_register( char * const *channels, int nb )
84 {
85     struct debug_option *opt = first_option;
86     struct dll *dll = malloc( sizeof(*dll) );
87     if (dll)
88     {
89         dll->channels = channels;
90         dll->nb_channels = nb;
91         dll->prev = NULL;
92         if ((dll->next = first_dll)) dll->next->prev = dll;
93         first_dll = dll;
94
95         /* apply existing options to this dll */
96         while (opt)
97         {
98             apply_option( dll, opt );
99             opt = opt->next;
100         }
101     }
102     return dll;
103 }
104
105
106 /* unregister a set of channels; must pass the pointer obtained from wine_dbg_register */
107 void __wine_dbg_unregister( void *channel )
108 {
109     struct dll *dll = channel;
110     if (dll)
111     {
112         if (dll->next) dll->next->prev = dll->prev;
113         if (dll->prev) dll->prev->next = dll->next;
114         else first_dll = dll->next;
115         free( dll );
116     }
117 }
118
119
120 /* add a new debug option at the end of the option list */
121 void wine_dbg_add_option( const char *name, unsigned char set, unsigned char clear )
122 {
123     struct dll *dll = first_dll;
124     struct debug_option *opt;
125
126     if (!(opt = malloc( sizeof(*opt) ))) return;
127     opt->next  = NULL;
128     opt->set   = set;
129     opt->clear = clear;
130     strncpy( opt->name, name, sizeof(opt->name) );
131     opt->name[sizeof(opt->name)-1] = 0;
132     if (last_option) last_option->next = opt;
133     else first_option = opt;
134     last_option = opt;
135
136     /* apply option to all existing dlls */
137     while (dll)
138     {
139         apply_option( dll, opt );
140         dll = dll->next;
141     }
142 }
143
144 /* parse a set of debugging option specifications and add them to the option list */
145 int wine_dbg_parse_options( const char *str )
146 {
147     char *p, *opt, *next, *options;
148     int i, errors = 0;
149
150     if (!(options = strdup(str))) return -1;
151     for (opt = options; opt; opt = next)
152     {
153         unsigned char set = 0, clear = 0;
154
155         if ((next = strchr( opt, ',' ))) *next++ = 0;
156
157         p = opt + strcspn( opt, "+-" );
158         if (!p[0] || !p[1])  /* bad option, skip it */
159         {
160             errors++;
161             continue;
162         }
163
164         if (p > opt)
165         {
166             for (i = 0; i < sizeof(debug_classes)/sizeof(debug_classes[0]); i++)
167             {
168                 int len = strlen(debug_classes[i]);
169                 if (len != (p - opt)) continue;
170                 if (!memcmp( opt, debug_classes[i], len ))  /* found it */
171                 {
172                     if (*p == '+') set |= 1 << i;
173                     else clear |= 1 << i;
174                     break;
175                 }
176             }
177             if (i == sizeof(debug_classes)/sizeof(debug_classes[0])) /* bad class name, skip it */
178             {
179                 errors++;
180                 continue;
181             }
182         }
183         else
184         {
185             if (*p == '+') set = ~0;
186             else clear = ~0;
187         }
188         p++;
189         if (!strcmp( p, "all" )) p = "";  /* empty string means all */
190         wine_dbg_add_option( p, set, clear );
191     }
192     free( options );
193     return errors;
194 }
195
196 /* varargs wrapper for __wine_dbg_vprintf */
197 int wine_dbg_printf( const char *format, ... )
198 {
199     int ret;
200     va_list valist;
201
202     va_start(valist, format);
203     ret = __wine_dbg_vprintf( format, valist );
204     va_end(valist);
205     return ret;
206 }
207
208
209 /* varargs wrapper for __wine_dbg_vlog */
210 int wine_dbg_log( int cls, const char *channel, const char *func, const char *format, ... )
211 {
212     int ret;
213     va_list valist;
214
215     va_start(valist, format);
216     ret = __wine_dbg_vlog( cls, channel, func, format, valist );
217     va_end(valist);
218     return ret;
219 }
220
221
222 /* allocate some tmp string space */
223 /* FIXME: this is not 100% thread-safe */
224 static char *get_tmp_space( int size )
225 {
226     static char *list[32];
227     static long pos;
228     char *ret;
229     int idx;
230
231     idx = interlocked_xchg_add( &pos, 1 ) % (sizeof(list)/sizeof(list[0]));
232     if ((ret = realloc( list[idx], size ))) list[idx] = ret;
233     return ret;
234 }
235
236
237 /* default implementation of wine_dbgstr_an */
238 static const char *default_dbgstr_an( const char *str, int n )
239 {
240     char *dst, *res;
241
242     if (!HIWORD(str))
243     {
244         if (!str) return "(null)";
245         res = get_tmp_space( 6 );
246         sprintf( res, "#%04x", LOWORD(str) );
247         return res;
248     }
249     if (n == -1) n = strlen(str);
250     if (n < 0) n = 0;
251     else if (n > 200) n = 200;
252     dst = res = get_tmp_space( n * 4 + 6 );
253     *dst++ = '"';
254     while (n-- > 0)
255     {
256         unsigned char c = *str++;
257         switch (c)
258         {
259         case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
260         case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
261         case '\t': *dst++ = '\\'; *dst++ = 't'; break;
262         case '"':  *dst++ = '\\'; *dst++ = '"'; break;
263         case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
264         default:
265             if (c >= ' ' && c <= 126)
266                 *dst++ = c;
267             else
268             {
269                 *dst++ = '\\';
270                 *dst++ = '0' + ((c >> 6) & 7);
271                 *dst++ = '0' + ((c >> 3) & 7);
272                 *dst++ = '0' + ((c >> 0) & 7);
273             }
274         }
275     }
276     *dst++ = '"';
277     if (*str)
278     {
279         *dst++ = '.';
280         *dst++ = '.';
281         *dst++ = '.';
282     }
283     *dst = 0;
284     return res;
285 }
286
287
288 /* default implementation of wine_dbgstr_wn */
289 static const char *default_dbgstr_wn( const WCHAR *str, int n )
290 {
291     char *dst, *res;
292
293     if (!HIWORD(str))
294     {
295         if (!str) return "(null)";
296         res = get_tmp_space( 6 );
297         sprintf( res, "#%04x", LOWORD(str) );
298         return res;
299     }
300     if (n == -1) n = strlenW(str);
301     if (n < 0) n = 0;
302     else if (n > 200) n = 200;
303     dst = res = get_tmp_space( n * 5 + 7 );
304     *dst++ = 'L';
305     *dst++ = '"';
306     while (n-- > 0)
307     {
308         WCHAR c = *str++;
309         switch (c)
310         {
311         case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
312         case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
313         case '\t': *dst++ = '\\'; *dst++ = 't'; break;
314         case '"':  *dst++ = '\\'; *dst++ = '"'; break;
315         case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
316         default:
317             if (c >= ' ' && c <= 126)
318                 *dst++ = c;
319             else
320             {
321                 *dst++ = '\\';
322                 sprintf(dst,"%04x",c);
323                 dst+=4;
324             }
325         }
326     }
327     *dst++ = '"';
328     if (*str)
329     {
330         *dst++ = '.';
331         *dst++ = '.';
332         *dst++ = '.';
333     }
334     *dst = 0;
335     return res;
336 }
337
338
339 /* default implementation of wine_dbgstr_guid */
340 static const char *default_dbgstr_guid( const struct _GUID *id )
341 {
342     char *str;
343
344     if (!id) return "(null)";
345     if (!((int)id >> 16))
346     {
347         str = get_tmp_space( 12 );
348         sprintf( str, "<guid-0x%04x>", (int)id & 0xffff );
349     }
350     else
351     {
352         str = get_tmp_space( 40 );
353         sprintf( str, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
354                  id->Data1, id->Data2, id->Data3,
355                  id->Data4[0], id->Data4[1], id->Data4[2], id->Data4[3],
356                  id->Data4[4], id->Data4[5], id->Data4[6], id->Data4[7] );
357     }
358     return str;
359 }
360
361
362 /* default implementation of wine_dbg_vprintf */
363 static int default_dbg_vprintf( const char *format, va_list args )
364 {
365     return vfprintf( stderr, format, args );
366 }
367
368
369 /* default implementation of wine_dbg_vlog */
370 static int default_dbg_vlog( int cls, const char *channel, const char *func,
371                              const char *format, va_list args )
372 {
373     int ret = 0;
374
375     if (cls < sizeof(debug_classes)/sizeof(debug_classes[0]))
376         ret += wine_dbg_printf( "%s:%s:%s ", debug_classes[cls], channel + 1, func );
377     if (format)
378         ret += __wine_dbg_vprintf( format, args );
379     return ret;
380 }
381
382
383 /* exported function pointers so that debugging functions can be redirected at run-time */
384
385 const char * (*__wine_dbgstr_an)( const char * s, int n ) = default_dbgstr_an;
386 const char * (*__wine_dbgstr_wn)( const WCHAR *s, int n ) = default_dbgstr_wn;
387 const char * (*__wine_dbgstr_guid)( const struct _GUID *id ) = default_dbgstr_guid;
388 int (*__wine_dbg_vprintf)( const char *format, va_list args ) = default_dbg_vprintf;
389 int (*__wine_dbg_vlog)( int cls, const char *channel, const char *function,
390                         const char *format, va_list args ) = default_dbg_vlog;
391
392 /* wrappers to use the function pointers */
393
394 const char *wine_dbgstr_guid( const struct _GUID *id )
395 {
396     return __wine_dbgstr_guid(id);
397 }
398
399 const char *wine_dbgstr_an( const char * s, int n )
400 {
401     return __wine_dbgstr_an(s, n);
402 }
403
404 const char *wine_dbgstr_wn( const WCHAR *s, int n )
405 {
406     return __wine_dbgstr_wn(s, n);
407 }
408
409 const char *wine_dbgstr_a( const char *s )
410 {
411     return __wine_dbgstr_an( s, -1 );
412 }
413
414 const char *wine_dbgstr_w( const WCHAR *s )
415 {
416     return __wine_dbgstr_wn( s, -1 );
417 }