Module: wine Branch: master Commit: b0ecbe0baed6910fae291f0ae506dd90506e5315 URL: https://source.winehq.org/git/wine.git/?a=commit;h=b0ecbe0baed6910fae291f0ae...
Author: Alexandre Julliard julliard@winehq.org Date: Wed Apr 3 19:25:39 2019 +0200
winecrt0: Add a fallback implementation of __wine_dbg_get_channel_flags().
Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/winecrt0/debug.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+)
diff --git a/dlls/winecrt0/debug.c b/dlls/winecrt0/debug.c index 4ae086c..8003e03 100644 --- a/dlls/winecrt0/debug.c +++ b/dlls/winecrt0/debug.c @@ -27,9 +27,18 @@ #include "windef.h" #include "winbase.h" #include "wine/debug.h" +#include "wine/heap.h"
static const char * (__cdecl *p__wine_dbg_strdup)( const char *str ); static int (__cdecl *p__wine_dbg_output)( const char *str ); +static unsigned char (__cdecl *p__wine_dbg_get_channel_flags)( struct __wine_debug_channel *channel ); + +static const char * const debug_classes[] = { "fixme", "err", "warn", "trace" }; + +static unsigned char default_flags = (1 << __WINE_DBCL_ERR) | (1 << __WINE_DBCL_FIXME); +static int nb_debug_options = -1; +static int options_size; +static struct __wine_debug_channel *debug_options;
static void load_func( void **func, const char *name, void *def ) { @@ -42,6 +51,103 @@ static void load_func( void **func, const char *name, void *def ) } #define LOAD_FUNC(name) load_func( (void **)&p ## name, #name, fallback ## name )
+ +/* add a new debug option at the end of the option list */ +static void add_option( const char *name, unsigned char set, unsigned char clear ) +{ + int min = 0, max = nb_debug_options - 1, pos, res; + + if (!name[0]) /* "all" option */ + { + default_flags = (default_flags & ~clear) | set; + return; + } + if (strlen(name) >= sizeof(debug_options[0].name)) return; + + while (min <= max) + { + pos = (min + max) / 2; + res = strcmp( name, debug_options[pos].name ); + if (!res) + { + debug_options[pos].flags = (debug_options[pos].flags & ~clear) | set; + return; + } + if (res < 0) max = pos - 1; + else min = pos + 1; + } + if (nb_debug_options >= options_size) + { + options_size = max( options_size * 2, 16 ); + debug_options = heap_realloc( debug_options, options_size * sizeof(debug_options[0]) ); + } + + pos = min; + if (pos < nb_debug_options) memmove( &debug_options[pos + 1], &debug_options[pos], + (nb_debug_options - pos) * sizeof(debug_options[0]) ); + strcpy( debug_options[pos].name, name ); + debug_options[pos].flags = (default_flags & ~clear) | set; + nb_debug_options++; +} + +/* parse a set of debugging option specifications and add them to the option list */ +static void parse_options( const char *str ) +{ + char *opt, *next, *options; + unsigned int i; + + if (!(options = _strdup(str))) return; + for (opt = options; opt; opt = next) + { + const char *p; + unsigned char set = 0, clear = 0; + + if ((next = strchr( opt, ',' ))) *next++ = 0; + + p = opt + strcspn( opt, "+-" ); + if (!p[0]) p = opt; /* assume it's a debug channel name */ + + if (p > opt) + { + for (i = 0; i < ARRAY_SIZE(debug_classes); i++) + { + int len = strlen(debug_classes[i]); + if (len != (p - opt)) continue; + if (!memcmp( opt, debug_classes[i], len )) /* found it */ + { + if (*p == '+') set |= 1 << i; + else clear |= 1 << i; + break; + } + } + if (i == ARRAY_SIZE(debug_classes)) /* bad class name, skip it */ + continue; + } + else + { + if (*p == '-') clear = ~0; + else set = ~0; + } + if (*p == '+' || *p == '-') p++; + if (!p[0]) continue; + + if (!strcmp( p, "all" )) + default_flags = (default_flags & ~clear) | set; + else + add_option( p, set, clear ); + } + free( options ); +} + +/* initialize all options at startup */ +static void init_options(void) +{ + char *wine_debug = getenv("WINEDEBUG"); + + nb_debug_options = 0; + if (wine_debug) parse_options( wine_debug ); +} + /* FIXME: this is not 100% thread-safe */ static const char * __cdecl fallback__wine_dbg_strdup( const char *str ) { @@ -60,6 +166,27 @@ static int __cdecl fallback__wine_dbg_output( const char *str ) return fwrite( str, 1, strlen(str), stderr ); }
+static unsigned char __cdecl fallback__wine_dbg_get_channel_flags( struct __wine_debug_channel *channel ) +{ + int min, max, pos, res; + + if (nb_debug_options == -1) init_options(); + + min = 0; + max = nb_debug_options - 1; + while (min <= max) + { + pos = (min + max) / 2; + res = strcmp( channel->name, debug_options[pos].name ); + if (!res) return debug_options[pos].flags; + if (res < 0) max = pos - 1; + else min = pos + 1; + } + /* no option for this channel */ + if (channel->flags & (1 << __WINE_DBCL_INIT)) channel->flags = default_flags; + return default_flags; +} + const char * __cdecl __wine_dbg_strdup( const char *str ) { LOAD_FUNC( __wine_dbg_strdup ); @@ -72,4 +199,10 @@ int __cdecl __wine_dbg_output( const char *str ) return p__wine_dbg_output( str ); }
+unsigned char __cdecl __wine_dbg_get_channel_flags( struct __wine_debug_channel *channel ) +{ + LOAD_FUNC( __wine_dbg_get_channel_flags ); + return p__wine_dbg_get_channel_flags( channel ); +} + #endif /* _WIN32 */