Only add the default dlldir to the search path if that's where ntdll
[wine] / libs / wine / 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 <ctype.h>
29
30 #include "wine/debug.h"
31 #include "wine/library.h"
32 #include "wine/unicode.h"
33
34 struct dll
35 {
36     struct dll   *next;        /* linked list of dlls */
37     struct dll   *prev;
38     char * const *channels;    /* array of channels */
39     int           nb_channels; /* number of channels in array */
40 };
41
42 static struct dll *first_dll;
43
44 struct debug_option
45 {
46     struct debug_option *next;       /* next option in list */
47     unsigned char        set;        /* bits to set */
48     unsigned char        clear;      /* bits to clear */
49     char                 name[14];   /* channel name, or empty for "all" */
50 };
51
52 static struct debug_option *first_option;
53 static struct debug_option *last_option;
54
55 static const char * const debug_classes[] = { "fixme", "err", "warn", "trace" };
56
57 static int cmp_name( const void *p1, const void *p2 )
58 {
59     const char *name = p1;
60     const char * const *chan = p2;
61     return strcmp( name, *chan + 1 );
62 }
63
64 /* apply a debug option to the channels of a given dll */
65 static void apply_option( struct dll *dll, const struct debug_option *opt )
66 {
67     if (opt->name[0])
68     {
69         char **dbch = bsearch( opt->name, dll->channels, dll->nb_channels,
70                                sizeof(*dll->channels), cmp_name );
71         if (dbch) **dbch = (**dbch & ~opt->clear) | opt->set;
72     }
73     else /* all */
74     {
75         int i;
76         for (i = 0; i < dll->nb_channels; i++)
77             dll->channels[i][0] = (dll->channels[i][0] & ~opt->clear) | opt->set;
78     }
79 }
80
81 /* register a new set of channels for a dll */
82 void *__wine_dbg_register( char * const *channels, int nb )
83 {
84     struct debug_option *opt = first_option;
85     struct dll *dll = malloc( sizeof(*dll) );
86     if (dll)
87     {
88         dll->channels = channels;
89         dll->nb_channels = nb;
90         dll->prev = NULL;
91         if ((dll->next = first_dll)) dll->next->prev = dll;
92         first_dll = dll;
93
94         /* apply existing options to this dll */
95         while (opt)
96         {
97             apply_option( dll, opt );
98             opt = opt->next;
99         }
100     }
101     return dll;
102 }
103
104
105 /* unregister a set of channels; must pass the pointer obtained from wine_dbg_register */
106 void __wine_dbg_unregister( void *channel )
107 {
108     struct dll *dll = channel;
109     if (dll)
110     {
111         if (dll->next) dll->next->prev = dll->prev;
112         if (dll->prev) dll->prev->next = dll->next;
113         else first_dll = dll->next;
114         free( dll );
115     }
116 }
117
118
119 /* add a new debug option at the end of the option list */
120 void wine_dbg_add_option( const char *name, unsigned char set, unsigned char clear )
121 {
122     struct dll *dll = first_dll;
123     struct debug_option *opt;
124     size_t len = strlen(name);
125
126     if (!(opt = malloc( sizeof(*opt) ))) return;
127     opt->next  = NULL;
128     opt->set   = set;
129     opt->clear = clear;
130     if (len >= sizeof(opt->name)) len = sizeof(opt->name) - 1;
131     memcpy( opt->name, name, len );
132     opt->name[len] = 0;
133     if (last_option) last_option->next = opt;
134     else first_option = opt;
135     last_option = opt;
136
137     /* apply option to all existing dlls */
138     while (dll)
139     {
140         apply_option( dll, opt );
141         dll = dll->next;
142     }
143 }
144
145 /* parse a set of debugging option specifications and add them to the option list */
146 int wine_dbg_parse_options( const char *str )
147 {
148     char *opt, *next, *options;
149     unsigned int i;
150     int errors = 0;
151
152     if (!(options = strdup(str))) return -1;
153     for (opt = options; opt; opt = next)
154     {
155         const char *p;
156         unsigned char set = 0, clear = 0;
157
158         if ((next = strchr( opt, ',' ))) *next++ = 0;
159
160         p = opt + strcspn( opt, "+-" );
161         if (!p[0]) p = opt;  /* assume it's a debug channel name */
162
163         if (p > opt)
164         {
165             for (i = 0; i < sizeof(debug_classes)/sizeof(debug_classes[0]); i++)
166             {
167                 int len = strlen(debug_classes[i]);
168                 if (len != (p - opt)) continue;
169                 if (!memcmp( opt, debug_classes[i], len ))  /* found it */
170                 {
171                     if (*p == '+') set |= 1 << i;
172                     else clear |= 1 << i;
173                     break;
174                 }
175             }
176             if (i == sizeof(debug_classes)/sizeof(debug_classes[0])) /* bad class name, skip it */
177             {
178                 errors++;
179                 continue;
180             }
181         }
182         else
183         {
184             if (*p == '-') clear = ~0;
185             else set = ~0;
186         }
187         if (*p == '+' || *p == '-') p++;
188         if (!p[0])
189         {
190             errors++;
191             continue;
192         }
193         if (!strcmp( p, "all" )) p = "";  /* empty string means all */
194         wine_dbg_add_option( p, set, clear );
195     }
196     free( options );
197     return errors;
198 }
199
200 /* varargs wrapper for __wine_dbg_vprintf */
201 int wine_dbg_printf( const char *format, ... )
202 {
203     int ret;
204     va_list valist;
205
206     va_start(valist, format);
207     ret = __wine_dbg_vprintf( format, valist );
208     va_end(valist);
209     return ret;
210 }
211
212
213 /* varargs wrapper for __wine_dbg_vsprintf */
214 const char *wine_dbg_sprintf( const char *format, ... )
215 {
216     const char *ret;
217     va_list valist;
218
219     va_start(valist, format);
220     ret = __wine_dbg_vsprintf( format, valist );
221     va_end(valist);
222     return ret;
223 }
224
225
226 /* varargs wrapper for __wine_dbg_vlog */
227 int wine_dbg_log( unsigned int cls, const char *channel, const char *func, const char *format, ... )
228 {
229     int ret;
230     va_list valist;
231
232     va_start(valist, format);
233     ret = __wine_dbg_vlog( cls, channel, func, format, valist );
234     va_end(valist);
235     return ret;
236 }
237
238
239 /* allocate some tmp string space */
240 /* FIXME: this is not 100% thread-safe */
241 static char *get_tmp_space( int size )
242 {
243     static char *list[32];
244     static long pos;
245     char *ret;
246     int idx;
247
248     idx = interlocked_xchg_add( &pos, 1 ) % (sizeof(list)/sizeof(list[0]));
249     if ((ret = realloc( list[idx], size ))) list[idx] = ret;
250     return ret;
251 }
252
253
254 /* default implementation of wine_dbgstr_an */
255 static const char *default_dbgstr_an( const char *str, int n )
256 {
257     char *dst, *res;
258
259     if (!HIWORD(str))
260     {
261         if (!str) return "(null)";
262         res = get_tmp_space( 6 );
263         sprintf( res, "#%04x", LOWORD(str) );
264         return res;
265     }
266     if (n == -1) n = strlen(str);
267     if (n < 0) n = 0;
268     else if (n > 200) n = 200;
269     dst = res = get_tmp_space( n * 4 + 6 );
270     *dst++ = '"';
271     while (n-- > 0)
272     {
273         unsigned char c = *str++;
274         switch (c)
275         {
276         case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
277         case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
278         case '\t': *dst++ = '\\'; *dst++ = 't'; break;
279         case '"':  *dst++ = '\\'; *dst++ = '"'; break;
280         case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
281         default:
282             if (c >= ' ' && c <= 126)
283                 *dst++ = c;
284             else
285             {
286                 *dst++ = '\\';
287                 *dst++ = '0' + ((c >> 6) & 7);
288                 *dst++ = '0' + ((c >> 3) & 7);
289                 *dst++ = '0' + ((c >> 0) & 7);
290             }
291         }
292     }
293     *dst++ = '"';
294     if (*str)
295     {
296         *dst++ = '.';
297         *dst++ = '.';
298         *dst++ = '.';
299     }
300     *dst = 0;
301     return res;
302 }
303
304
305 /* default implementation of wine_dbgstr_wn */
306 static const char *default_dbgstr_wn( const WCHAR *str, int n )
307 {
308     char *dst, *res;
309
310     if (!HIWORD(str))
311     {
312         if (!str) return "(null)";
313         res = get_tmp_space( 6 );
314         sprintf( res, "#%04x", LOWORD(str) );
315         return res;
316     }
317     if (n == -1) n = strlenW(str);
318     if (n < 0) n = 0;
319     else if (n > 200) n = 200;
320     dst = res = get_tmp_space( n * 5 + 7 );
321     *dst++ = 'L';
322     *dst++ = '"';
323     while (n-- > 0)
324     {
325         WCHAR c = *str++;
326         switch (c)
327         {
328         case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
329         case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
330         case '\t': *dst++ = '\\'; *dst++ = 't'; break;
331         case '"':  *dst++ = '\\'; *dst++ = '"'; break;
332         case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
333         default:
334             if (c >= ' ' && c <= 126)
335                 *dst++ = c;
336             else
337             {
338                 *dst++ = '\\';
339                 sprintf(dst,"%04x",c);
340                 dst+=4;
341             }
342         }
343     }
344     *dst++ = '"';
345     if (*str)
346     {
347         *dst++ = '.';
348         *dst++ = '.';
349         *dst++ = '.';
350     }
351     *dst = 0;
352     return res;
353 }
354
355
356 /* default implementation of wine_dbg_vsprintf */
357 static const char *default_dbg_vsprintf( const char *format, va_list args )
358 {
359     static const int max_size = 200;
360
361     char *res = get_tmp_space( max_size );
362     int len = vsnprintf( res, max_size, format, args );
363     if (len == -1 || len >= max_size) res[max_size-1] = 0;
364     return res;
365 }
366
367 /* default implementation of wine_dbg_vprintf */
368 static int default_dbg_vprintf( const char *format, va_list args )
369 {
370     return vfprintf( stderr, format, args );
371 }
372
373
374 /* default implementation of wine_dbg_vlog */
375 static int default_dbg_vlog( unsigned int cls, const char *channel, const char *func,
376                              const char *format, va_list args )
377 {
378     int ret = 0;
379
380     if (cls < sizeof(debug_classes)/sizeof(debug_classes[0]))
381         ret += wine_dbg_printf( "%s:%s:%s ", debug_classes[cls], channel + 1, func );
382     if (format)
383         ret += __wine_dbg_vprintf( format, args );
384     return ret;
385 }
386
387
388 /* exported function pointers so that debugging functions can be redirected at run-time */
389
390 const char * (*__wine_dbgstr_an)( const char * s, int n ) = default_dbgstr_an;
391 const char * (*__wine_dbgstr_wn)( const WCHAR *s, int n ) = default_dbgstr_wn;
392 const char * (*__wine_dbg_vsprintf)( const char *format, va_list args ) = default_dbg_vsprintf;
393 int (*__wine_dbg_vprintf)( const char *format, va_list args ) = default_dbg_vprintf;
394 int (*__wine_dbg_vlog)( unsigned int cls, const char *channel, const char *function,
395                         const char *format, va_list args ) = default_dbg_vlog;
396
397 /* wrappers to use the function pointers */
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 }