2 * Management of the debugging channels
4 * Copyright 2000 Alexandre Julliard
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.
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.
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
22 #include "wine/port.h"
31 #include "wine/debug.h"
32 #include "wine/library.h"
33 #include "wine/unicode.h"
37 struct dll
*next
; /* linked list of dlls */
39 char * const *channels
; /* array of channels */
40 int nb_channels
; /* number of channels in array */
43 static struct dll
*first_dll
;
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" */
53 static struct debug_option
*first_option
;
54 static struct debug_option
*last_option
;
57 static int cmp_name( const void *p1
, const void *p2
)
59 const char *name
= p1
;
60 const char * const *chan
= p2
;
61 return strcmp( name
, *chan
+ 1 );
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
)
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
;
76 for (i
= 0; i
< dll
->nb_channels
; i
++)
77 dll
->channels
[i
][0] = (dll
->channels
[i
][0] & ~opt
->clear
) | opt
->set
;
81 /* register a new set of channels for a dll */
82 void *__wine_dbg_register( char * const *channels
, int nb
)
84 struct debug_option
*opt
= first_option
;
85 struct dll
*dll
= malloc( sizeof(*dll
) );
88 dll
->channels
= channels
;
89 dll
->nb_channels
= nb
;
91 if ((dll
->next
= first_dll
)) dll
->next
->prev
= dll
;
94 /* apply existing options to this dll */
97 apply_option( dll
, opt
);
105 /* unregister a set of channels; must pass the pointer obtained from wine_dbg_register */
106 void __wine_dbg_unregister( void *channel
)
108 struct dll
*dll
= channel
;
111 if (dll
->next
) dll
->next
->prev
= dll
->prev
;
112 if (dll
->prev
) dll
->prev
->next
= dll
->next
;
113 else first_dll
= dll
->next
;
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
)
122 struct dll
*dll
= first_dll
;
123 struct debug_option
*opt
;
125 if (!(opt
= malloc( sizeof(*opt
) ))) return;
129 strncpy( opt
->name
, name
, sizeof(opt
->name
) );
130 opt
->name
[sizeof(opt
->name
)-1] = 0;
131 if (last_option
) last_option
->next
= opt
;
132 else first_option
= opt
;
135 /* apply option to all existing dlls */
138 apply_option( dll
, opt
);
144 /* varargs wrapper for __wine_dbg_vprintf */
145 int wine_dbg_printf( const char *format
, ... )
150 va_start(valist
, format
);
151 ret
= __wine_dbg_vprintf( format
, valist
);
157 /* varargs wrapper for __wine_dbg_vlog */
158 int wine_dbg_log( int cls
, const char *channel
, const char *func
, const char *format
, ... )
163 va_start(valist
, format
);
164 ret
= __wine_dbg_vlog( cls
, channel
, func
, format
, valist
);
170 /* allocate some tmp string space */
171 /* FIXME: this is not 100% thread-safe */
172 static char *get_tmp_space( int size
)
174 static char *list
[32];
179 idx
= interlocked_xchg_add( &pos
, 1 ) % (sizeof(list
)/sizeof(list
[0]));
180 if ((ret
= realloc( list
[idx
], size
))) list
[idx
] = ret
;
185 /* default implementation of wine_dbgstr_an */
186 static const char *default_dbgstr_an( const char *str
, int n
)
192 if (!str
) return "(null)";
193 res
= get_tmp_space( 6 );
194 sprintf( res
, "#%04x", LOWORD(str
) );
197 if (n
== -1) n
= strlen(str
);
199 else if (n
> 200) n
= 200;
200 dst
= res
= get_tmp_space( n
* 4 + 6 );
204 unsigned char c
= *str
++;
207 case '\n': *dst
++ = '\\'; *dst
++ = 'n'; break;
208 case '\r': *dst
++ = '\\'; *dst
++ = 'r'; break;
209 case '\t': *dst
++ = '\\'; *dst
++ = 't'; break;
210 case '"': *dst
++ = '\\'; *dst
++ = '"'; break;
211 case '\\': *dst
++ = '\\'; *dst
++ = '\\'; break;
213 if (c
>= ' ' && c
<= 126)
218 *dst
++ = '0' + ((c
>> 6) & 7);
219 *dst
++ = '0' + ((c
>> 3) & 7);
220 *dst
++ = '0' + ((c
>> 0) & 7);
236 /* default implementation of wine_dbgstr_wn */
237 static const char *default_dbgstr_wn( const WCHAR
*str
, int n
)
243 if (!str
) return "(null)";
244 res
= get_tmp_space( 6 );
245 sprintf( res
, "#%04x", LOWORD(str
) );
248 if (n
== -1) n
= strlenW(str
);
250 else if (n
> 200) n
= 200;
251 dst
= res
= get_tmp_space( n
* 5 + 7 );
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;
265 if (c
>= ' ' && c
<= 126)
270 sprintf(dst
,"%04x",c
);
287 /* default implementation of wine_dbgstr_guid */
288 static const char *default_dbgstr_guid( const struct _GUID
*id
)
292 if (!id
) return "(null)";
293 if (!((int)id
>> 16))
295 str
= get_tmp_space( 12 );
296 sprintf( str
, "<guid-0x%04x>", (int)id
& 0xffff );
300 str
= get_tmp_space( 40 );
301 sprintf( str
, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
302 id
->Data1
, id
->Data2
, id
->Data3
,
303 id
->Data4
[0], id
->Data4
[1], id
->Data4
[2], id
->Data4
[3],
304 id
->Data4
[4], id
->Data4
[5], id
->Data4
[6], id
->Data4
[7] );
310 /* default implementation of wine_dbg_vprintf */
311 static int default_dbg_vprintf( const char *format
, va_list args
)
313 return vfprintf( stderr
, format
, args
);
317 /* default implementation of wine_dbg_vlog */
318 static int default_dbg_vlog( int cls
, const char *channel
, const char *func
,
319 const char *format
, va_list args
)
321 static const char * const classes
[] = { "fixme", "err", "warn", "trace" };
324 if (cls
< sizeof(classes
)/sizeof(classes
[0]))
325 ret
+= wine_dbg_printf( "%s:%s:%s ", classes
[cls
], channel
+ 1, func
);
327 ret
+= __wine_dbg_vprintf( format
, args
);
332 /* exported function pointers so that debugging functions can be redirected at run-time */
334 const char * (*__wine_dbgstr_an
)( const char * s
, int n
) = default_dbgstr_an
;
335 const char * (*__wine_dbgstr_wn
)( const WCHAR
*s
, int n
) = default_dbgstr_wn
;
336 const char * (*__wine_dbgstr_guid
)( const struct _GUID
*id
) = default_dbgstr_guid
;
337 int (*__wine_dbg_vprintf
)( const char *format
, va_list args
) = default_dbg_vprintf
;
338 int (*__wine_dbg_vlog
)( int cls
, const char *channel
, const char *function
,
339 const char *format
, va_list args
) = default_dbg_vlog
;
341 /* wrappers to use the function pointers */
343 const char *wine_dbgstr_guid( const struct _GUID
*id
)
345 return __wine_dbgstr_guid(id
);
348 const char *wine_dbgstr_an( const char * s
, int n
)
350 return __wine_dbgstr_an(s
, n
);
353 const char *wine_dbgstr_wn( const WCHAR
*s
, int n
)
355 return __wine_dbgstr_wn(s
, n
);
358 const char *wine_dbgstr_a( const char *s
)
360 return __wine_dbgstr_an( s
, -1 );
363 const char *wine_dbgstr_w( const WCHAR
*s
)
365 return __wine_dbgstr_wn( s
, -1 );