From 94613ab03eaa9f062370b8770f84080b0a38f05f Mon Sep 17 00:00:00 2001
From: Alexandre Julliard <julliard@winehq.org>
Date: Sun, 5 Nov 2000 04:51:34 +0000
Subject: [PATCH] New debug channel mechanism allowing decentralized channel
 declarations.

---
 dlls/ntdll/Makefile.in    |   1 +
 dlls/ntdll/debugtools.c   | 238 +++++++++++++++++++++++++
 dlls/ntdll/ntdll.spec     |  20 +++
 include/debugdefs.h       | 365 --------------------------------------
 include/debugtools.h      |  69 +++----
 include/main.h            |   1 -
 library/Makefile.in       |   1 +
 library/debug.c           | 118 ++++++++++++
 misc/Makefile.in          |   1 -
 misc/debugstr.c           | 332 ----------------------------------
 misc/main.c               |   5 +-
 misc/options.c            |  59 +++++-
 relay32/builtin32.c       |   2 +-
 tools/find_debug_channels |  47 -----
 tools/make_debug          |  98 +++++-----
 15 files changed, 523 insertions(+), 834 deletions(-)
 create mode 100644 dlls/ntdll/debugtools.c
 delete mode 100644 include/debugdefs.h
 create mode 100644 library/debug.c
 delete mode 100644 misc/debugstr.c
 delete mode 100755 tools/find_debug_channels

diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in
index 9dfbccf1b19..1d7450fd7b9 100644
--- a/dlls/ntdll/Makefile.in
+++ b/dlls/ntdll/Makefile.in
@@ -7,6 +7,7 @@ SOVERSION = 1.0
 
 C_SRCS = \
 	critsection.c \
+	debugtools.c \
 	exception.c \
 	error.c \
 	file.c \
diff --git a/dlls/ntdll/debugtools.c b/dlls/ntdll/debugtools.c
new file mode 100644
index 00000000000..22ceb34c15c
--- /dev/null
+++ b/dlls/ntdll/debugtools.c
@@ -0,0 +1,238 @@
+/*
+ * Debugging functions
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#include "debugtools.h"
+#include "thread.h"
+#include "winbase.h"
+#include "winnt.h"
+#include "wtypes.h"
+
+/* ---------------------------------------------------------------------- */
+
+struct debug_info
+{
+    char *str_pos;       /* current position in strings buffer */
+    char *out_pos;       /* current position in output buffer */
+    char  strings[504];  /* buffer for temporary strings */
+    char  output[504];   /* current output line */
+};
+
+static struct debug_info tmp;
+
+/* get the debug info pointer for the current thread */
+static inline struct debug_info *get_info(void)
+{
+    struct debug_info *info = NtCurrentTeb()->debug_info;
+    if (!info)
+    {
+        /* setup the temp structure in case HeapAlloc wants to print something */
+        NtCurrentTeb()->debug_info = &tmp;
+        tmp.str_pos = tmp.strings;
+        tmp.out_pos = tmp.output;
+        info = HeapAlloc( GetProcessHeap(), 0, sizeof(*info) );
+        info->str_pos = info->strings;
+        info->out_pos = info->output;
+        NtCurrentTeb()->debug_info = info;
+    }
+    return info;
+}
+
+/* allocate some tmp space for a string */
+static void *gimme1(int n)
+{
+    struct debug_info *info = get_info();
+    char *res = info->str_pos;
+
+    if (res + n >= &info->strings[sizeof(info->strings)]) res = info->strings;
+    info->str_pos = res + n;
+    return res;
+}
+
+/* release extra space that we requested in gimme1() */
+static inline void release( void *ptr )
+{
+    struct debug_info *info = NtCurrentTeb()->debug_info;
+    info->str_pos = ptr;
+}
+
+/* ---------------------------------------------------------------------- */
+
+const char *debugstr_an( const char *src, int n )
+{
+    char *dst, *res;
+
+    if (!HIWORD(src))
+    {
+        if (!src) return "(null)";
+        res = gimme1(6);
+        sprintf(res, "#%04x", LOWORD(src) );
+        return res;
+    }
+    if (n < 0) n = 0;
+    dst = res = gimme1 (n * 4 + 6);
+    *dst++ = '"';
+    while (n-- > 0 && *src)
+    {
+        unsigned char c = *src++;
+        switch (c)
+        {
+        case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
+        case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
+        case '\t': *dst++ = '\\'; *dst++ = 't'; break;
+        case '"': *dst++ = '\\'; *dst++ = '"'; break;
+        case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
+        default:
+            if (c >= ' ' && c <= 126)
+                *dst++ = c;
+            else
+            {
+                *dst++ = '\\';
+                *dst++ = '0' + ((c >> 6) & 7);
+                *dst++ = '0' + ((c >> 3) & 7);
+                *dst++ = '0' + ((c >> 0) & 7);
+            }
+        }
+    }
+    *dst++ = '"';
+    if (*src)
+    {
+        *dst++ = '.';
+        *dst++ = '.';
+        *dst++ = '.';
+    }
+    *dst++ = '\0';
+    release( dst );
+    return res;
+}
+
+/* ---------------------------------------------------------------------- */
+
+const char *debugstr_wn( const WCHAR *src, int n )
+{
+    char *dst, *res;
+
+    if (!HIWORD(src))
+    {
+        if (!src) return "(null)";
+        res = gimme1(6);
+        sprintf(res, "#%04x", LOWORD(src) );
+        return res;
+    }
+    if (n < 0) n = 0;
+    dst = res = gimme1 (n * 5 + 7);
+    *dst++ = 'L';
+    *dst++ = '"';
+    while (n-- > 0 && *src)
+    {
+        WCHAR c = *src++;
+        switch (c)
+        {
+        case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
+        case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
+        case '\t': *dst++ = '\\'; *dst++ = 't'; break;
+        case '"': *dst++ = '\\'; *dst++ = '"'; break;
+        case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
+        default:
+            if (c >= ' ' && c <= 126)
+                *dst++ = c;
+            else
+            {
+                *dst++ = '\\';
+                sprintf(dst,"%04x",c);
+                dst+=4;
+            }
+        }
+    }
+    *dst++ = '"';
+    if (*src)
+    {
+        *dst++ = '.';
+        *dst++ = '.';
+        *dst++ = '.';
+    }
+    *dst++ = '\0';
+    release( dst );
+    return res;
+}
+
+/* ---------------------------------------------------------------------- */
+
+const char *debugstr_guid( const GUID *id )
+{
+    char *str;
+
+    if (!id) return "(null)";
+    if (!HIWORD(id))
+    {
+        str = gimme1(12);
+        sprintf( str, "<guid-0x%04x>", LOWORD(id) );
+    }
+    else
+    {
+        str = gimme1(40);
+        sprintf( str, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
+                 id->Data1, id->Data2, id->Data3,
+                 id->Data4[0], id->Data4[1], id->Data4[2], id->Data4[3],
+                 id->Data4[4], id->Data4[5], id->Data4[6], id->Data4[7] );
+    }
+    return str;
+}
+
+/* ---------------------------------------------------------------------- */
+
+int wine_dbg_vprintf( const char *format, va_list args )
+{
+    struct debug_info *info = get_info();
+
+    int ret = vsprintf( info->out_pos, format, args );
+    char *p = strrchr( info->out_pos, '\n' );
+    if (!p) info->out_pos += ret;
+    else
+    {
+        char *pos = info->output;
+        p++;
+        write( 2, pos, p - pos );
+        /* move beginning of next line to start of buffer */
+        while ((*pos = *p++)) pos++;
+        info->out_pos = pos;
+    }
+    return ret;
+}
+
+int wine_dbg_printf(const char *format, ...)
+{
+    int ret;
+    va_list valist;
+
+    va_start(valist, format);
+    ret = wine_dbg_vprintf( format, valist);
+    va_end(valist);
+    return ret;
+}
+
+int __wine_dbg_header_err( const char *dbg_channel, const char *func )
+{
+    return wine_dbg_printf( "err:%s:%s ", dbg_channel + 1, func );
+}
+
+int __wine_dbg_header_fixme( const char *dbg_channel, const char *func )
+{
+    return wine_dbg_printf( "fixme:%s:%s ", dbg_channel + 1, func );
+}
+
+int __wine_dbg_header_warn( const char *dbg_channel, const char *func )
+{
+    return wine_dbg_printf( "warn:%s:%s ", dbg_channel + 1, func );
+}
+
+int __wine_dbg_header_trace( const char *dbg_channel, const char *func )
+{
+    return wine_dbg_printf( "trace:%s:%s ", dbg_channel + 1, func );
+}
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index 77994993d41..1c66a3cd4cf 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -1,6 +1,12 @@
 name	ntdll
 type	win32
 
+debug_channels (aspi atom cdrom console ddraw debug delayhlp dll dosfs dosmem
+                elfdll file fixup global heap int int10 int16 int17 int19 int21
+                int31 io ldt local module ntdll process profile reg relay resource
+                segment seh selector server snoop string system tape task thread
+                thunk timer toolhelp tweak ver virtual vxd win32)
+
 #note that the Zw... functions are alternate names for the 
 #Nt... functions.  (see www.sysinternals.com for details)
 #if you change a Nt.. function DON'T FORGET to change the
@@ -1000,6 +1006,20 @@ type	win32
 @ stub RtlSetPropertySetClassId
 @ stdcall NtPowerInformation(long long long long long) NtPowerInformation
 
+##################
 # Wine extensions
+#
+# All functions must be prefixed with '__wine_' (for internal functions)
+# or 'wine_' (for user-visible functions) to avoid namespace conflicts.
+
+# Exception handling
 @ cdecl __wine_exception_handler(ptr ptr ptr ptr) __wine_exception_handler
 @ cdecl __wine_finally_handler(ptr ptr ptr ptr) __wine_finally_handler
+
+# Debugging interface
+@ cdecl __wine_dbg_header_err(ptr str) __wine_dbg_header_err
+@ cdecl __wine_dbg_header_fixme(ptr str) __wine_dbg_header_fixme
+@ cdecl __wine_dbg_header_warn(ptr str) __wine_dbg_header_warn
+@ cdecl __wine_dbg_header_trace(ptr str) __wine_dbg_header_trace
+@ cdecl wine_dbg_vprintf(str ptr) wine_dbg_vprintf
+@ varargs wine_dbg_printf(str) wine_dbg_printf
diff --git a/include/debugdefs.h b/include/debugdefs.h
deleted file mode 100644
index 67941f48a20..00000000000
--- a/include/debugdefs.h
+++ /dev/null
@@ -1,365 +0,0 @@
-/* Do not modify this file -- it is automatically generated! */
-
-#include "debugtools.h"
-
-#define DEBUG_CLASS_COUNT __DBCL_COUNT
-
-static const char * const debug_cl_name[] = { "fixme", "err", "warn", "trace" };
-
-char dbch_accel[] = "\003accel";
-char dbch_advapi[] = "\003advapi";
-char dbch_animate[] = "\003animate";
-char dbch_aspi[] = "\003aspi";
-char dbch_atom[] = "\003atom";
-char dbch_avifile[] = "\003avifile";
-char dbch_bitblt[] = "\003bitblt";
-char dbch_bitmap[] = "\003bitmap";
-char dbch_caret[] = "\003caret";
-char dbch_cdrom[] = "\003cdrom";
-char dbch_class[] = "\003class";
-char dbch_clipboard[] = "\003clipboard";
-char dbch_clipping[] = "\003clipping";
-char dbch_combo[] = "\003combo";
-char dbch_comboex[] = "\003comboex";
-char dbch_comm[] = "\003comm";
-char dbch_commctrl[] = "\003commctrl";
-char dbch_commdlg[] = "\003commdlg";
-char dbch_console[] = "\003console";
-char dbch_crtdll[] = "\003crtdll";
-char dbch_cursor[] = "\003cursor";
-char dbch_datetime[] = "\003datetime";
-char dbch_dc[] = "\003dc";
-char dbch_ddeml[] = "\003ddeml";
-char dbch_ddraw[] = "\003ddraw";
-char dbch_debug[] = "\003debug";
-char dbch_debugstr[] = "\003debugstr";
-char dbch_delayhlp[] = "\003delayhlp";
-char dbch_dialog[] = "\003dialog";
-char dbch_dinput[] = "\003dinput";
-char dbch_dll[] = "\003dll";
-char dbch_dosfs[] = "\003dosfs";
-char dbch_dosmem[] = "\003dosmem";
-char dbch_dplay[] = "\003dplay";
-char dbch_driver[] = "\003driver";
-char dbch_dsound[] = "\003dsound";
-char dbch_edit[] = "\003edit";
-char dbch_elfdll[] = "\003elfdll";
-char dbch_enhmetafile[] = "\003enhmetafile";
-char dbch_event[] = "\003event";
-char dbch_exec[] = "\003exec";
-char dbch_file[] = "\003file";
-char dbch_fixup[] = "\003fixup";
-char dbch_font[] = "\003font";
-char dbch_gdi[] = "\003gdi";
-char dbch_global[] = "\003global";
-char dbch_graphics[] = "\003graphics";
-char dbch_header[] = "\003header";
-char dbch_heap[] = "\003heap";
-char dbch_hook[] = "\003hook";
-char dbch_hotkey[] = "\003hotkey";
-char dbch_icmp[] = "\003icmp";
-char dbch_icon[] = "\003icon";
-char dbch_imagehlp[] = "\003imagehlp";
-char dbch_imagelist[] = "\003imagelist";
-char dbch_imm[] = "\003imm";
-char dbch_int[] = "\003int";
-char dbch_int10[] = "\003int10";
-char dbch_int16[] = "\003int16";
-char dbch_int17[] = "\003int17";
-char dbch_int19[] = "\003int19";
-char dbch_int21[] = "\003int21";
-char dbch_int31[] = "\003int31";
-char dbch_io[] = "\003io";
-char dbch_ipaddress[] = "\003ipaddress";
-char dbch_joystick[] = "\003joystick";
-char dbch_key[] = "\003key";
-char dbch_keyboard[] = "\003keyboard";
-char dbch_ldt[] = "\003ldt";
-char dbch_listbox[] = "\003listbox";
-char dbch_listview[] = "\003listview";
-char dbch_local[] = "\003local";
-char dbch_mci[] = "\003mci";
-char dbch_mcianim[] = "\003mcianim";
-char dbch_mciavi[] = "\003mciavi";
-char dbch_mcicda[] = "\003mcicda";
-char dbch_mcimidi[] = "\003mcimidi";
-char dbch_mciwave[] = "\003mciwave";
-char dbch_mdi[] = "\003mdi";
-char dbch_menu[] = "\003menu";
-char dbch_message[] = "\003message";
-char dbch_metafile[] = "\003metafile";
-char dbch_midi[] = "\003midi";
-char dbch_mmaux[] = "\003mmaux";
-char dbch_mmio[] = "\003mmio";
-char dbch_mmsys[] = "\003mmsys";
-char dbch_mmtime[] = "\003mmtime";
-char dbch_module[] = "\003module";
-char dbch_monthcal[] = "\003monthcal";
-char dbch_mpr[] = "\003mpr";
-char dbch_msacm[] = "\003msacm";
-char dbch_msg[] = "\003msg";
-char dbch_msvideo[] = "\003msvideo";
-char dbch_nativefont[] = "\003nativefont";
-char dbch_nonclient[] = "\003nonclient";
-char dbch_ntdll[] = "\003ntdll";
-char dbch_odbc[] = "\003odbc";
-char dbch_ole[] = "\003ole";
-char dbch_opengl[] = "\003opengl";
-char dbch_pager[] = "\003pager";
-char dbch_palette[] = "\003palette";
-char dbch_pidl[] = "\003pidl";
-char dbch_print[] = "\003print";
-char dbch_process[] = "\003process";
-char dbch_profile[] = "\003profile";
-char dbch_progress[] = "\003progress";
-char dbch_prop[] = "\003prop";
-char dbch_propsheet[] = "\003propsheet";
-char dbch_psapi[] = "\003psapi";
-char dbch_psdrv[] = "\003psdrv";
-char dbch_ras[] = "\003ras";
-char dbch_rebar[] = "\003rebar";
-char dbch_reg[] = "\003reg";
-char dbch_region[] = "\003region";
-char dbch_relay[] = "\003relay";
-char dbch_resource[] = "\003resource";
-char dbch_richedit[] = "\003richedit";
-char dbch_scroll[] = "\003scroll";
-char dbch_segment[] = "\003segment";
-char dbch_seh[] = "\003seh";
-char dbch_selector[] = "\003selector";
-char dbch_sendmsg[] = "\003sendmsg";
-char dbch_server[] = "\003server";
-char dbch_setupapi[] = "\003setupapi";
-char dbch_setupx[] = "\003setupx";
-char dbch_shell[] = "\003shell";
-char dbch_snoop[] = "\003snoop";
-char dbch_sound[] = "\003sound";
-char dbch_static[] = "\003static";
-char dbch_statusbar[] = "\003statusbar";
-char dbch_storage[] = "\003storage";
-char dbch_stress[] = "\003stress";
-char dbch_string[] = "\003string";
-char dbch_syscolor[] = "\003syscolor";
-char dbch_system[] = "\003system";
-char dbch_tab[] = "\003tab";
-char dbch_tape[] = "\003tape";
-char dbch_tapi[] = "\003tapi";
-char dbch_task[] = "\003task";
-char dbch_text[] = "\003text";
-char dbch_thread[] = "\003thread";
-char dbch_thunk[] = "\003thunk";
-char dbch_timer[] = "\003timer";
-char dbch_toolbar[] = "\003toolbar";
-char dbch_toolhelp[] = "\003toolhelp";
-char dbch_tooltips[] = "\003tooltips";
-char dbch_trackbar[] = "\003trackbar";
-char dbch_treeview[] = "\003treeview";
-char dbch_ttydrv[] = "\003ttydrv";
-char dbch_tweak[] = "\003tweak";
-char dbch_typelib[] = "\003typelib";
-char dbch_updown[] = "\003updown";
-char dbch_ver[] = "\003ver";
-char dbch_virtual[] = "\003virtual";
-char dbch_vxd[] = "\003vxd";
-char dbch_wave[] = "\003wave";
-char dbch_win[] = "\003win";
-char dbch_win16drv[] = "\003win16drv";
-char dbch_win32[] = "\003win32";
-char dbch_wing[] = "\003wing";
-char dbch_wininet[] = "\003wininet";
-char dbch_winsock[] = "\003winsock";
-char dbch_winspool[] = "\003winspool";
-char dbch_wnet[] = "\003wnet";
-char dbch_x11[] = "\003x11";
-char dbch_x11drv[] = "\003x11drv";
-
-#define DEBUG_CHANNEL_COUNT 166
-
-static char * const debug_channels[DEBUG_CHANNEL_COUNT] = {
-    dbch_accel,
-    dbch_advapi,
-    dbch_animate,
-    dbch_aspi,
-    dbch_atom,
-    dbch_avifile,
-    dbch_bitblt,
-    dbch_bitmap,
-    dbch_caret,
-    dbch_cdrom,
-    dbch_class,
-    dbch_clipboard,
-    dbch_clipping,
-    dbch_combo,
-    dbch_comboex,
-    dbch_comm,
-    dbch_commctrl,
-    dbch_commdlg,
-    dbch_console,
-    dbch_crtdll,
-    dbch_cursor,
-    dbch_datetime,
-    dbch_dc,
-    dbch_ddeml,
-    dbch_ddraw,
-    dbch_debug,
-    dbch_debugstr,
-    dbch_delayhlp,
-    dbch_dialog,
-    dbch_dinput,
-    dbch_dll,
-    dbch_dosfs,
-    dbch_dosmem,
-    dbch_dplay,
-    dbch_driver,
-    dbch_dsound,
-    dbch_edit,
-    dbch_elfdll,
-    dbch_enhmetafile,
-    dbch_event,
-    dbch_exec,
-    dbch_file,
-    dbch_fixup,
-    dbch_font,
-    dbch_gdi,
-    dbch_global,
-    dbch_graphics,
-    dbch_header,
-    dbch_heap,
-    dbch_hook,
-    dbch_hotkey,
-    dbch_icmp,
-    dbch_icon,
-    dbch_imagehlp,
-    dbch_imagelist,
-    dbch_imm,
-    dbch_int,
-    dbch_int10,
-    dbch_int16,
-    dbch_int17,
-    dbch_int19,
-    dbch_int21,
-    dbch_int31,
-    dbch_io,
-    dbch_ipaddress,
-    dbch_joystick,
-    dbch_key,
-    dbch_keyboard,
-    dbch_ldt,
-    dbch_listbox,
-    dbch_listview,
-    dbch_local,
-    dbch_mci,
-    dbch_mcianim,
-    dbch_mciavi,
-    dbch_mcicda,
-    dbch_mcimidi,
-    dbch_mciwave,
-    dbch_mdi,
-    dbch_menu,
-    dbch_message,
-    dbch_metafile,
-    dbch_midi,
-    dbch_mmaux,
-    dbch_mmio,
-    dbch_mmsys,
-    dbch_mmtime,
-    dbch_module,
-    dbch_monthcal,
-    dbch_mpr,
-    dbch_msacm,
-    dbch_msg,
-    dbch_msvideo,
-    dbch_nativefont,
-    dbch_nonclient,
-    dbch_ntdll,
-    dbch_odbc,
-    dbch_ole,
-    dbch_opengl,
-    dbch_pager,
-    dbch_palette,
-    dbch_pidl,
-    dbch_print,
-    dbch_process,
-    dbch_profile,
-    dbch_progress,
-    dbch_prop,
-    dbch_propsheet,
-    dbch_psapi,
-    dbch_psdrv,
-    dbch_ras,
-    dbch_rebar,
-    dbch_reg,
-    dbch_region,
-    dbch_relay,
-    dbch_resource,
-    dbch_richedit,
-    dbch_scroll,
-    dbch_segment,
-    dbch_seh,
-    dbch_selector,
-    dbch_sendmsg,
-    dbch_server,
-    dbch_setupapi,
-    dbch_setupx,
-    dbch_shell,
-    dbch_snoop,
-    dbch_sound,
-    dbch_static,
-    dbch_statusbar,
-    dbch_storage,
-    dbch_stress,
-    dbch_string,
-    dbch_syscolor,
-    dbch_system,
-    dbch_tab,
-    dbch_tape,
-    dbch_tapi,
-    dbch_task,
-    dbch_text,
-    dbch_thread,
-    dbch_thunk,
-    dbch_timer,
-    dbch_toolbar,
-    dbch_toolhelp,
-    dbch_tooltips,
-    dbch_trackbar,
-    dbch_treeview,
-    dbch_ttydrv,
-    dbch_tweak,
-    dbch_typelib,
-    dbch_updown,
-    dbch_ver,
-    dbch_virtual,
-    dbch_vxd,
-    dbch_wave,
-    dbch_win,
-    dbch_win16drv,
-    dbch_win32,
-    dbch_wing,
-    dbch_wininet,
-    dbch_winsock,
-    dbch_winspool,
-    dbch_wnet,
-    dbch_x11,
-    dbch_x11drv
-};
-
-int dbg_header_err( const char *dbg_channel, const char *func )
-{
-    return dbg_printf( "err:%s:%s ", dbg_channel + 1, func );
-}
-
-int dbg_header_fixme( const char *dbg_channel, const char *func )
-{
-    return dbg_printf( "fixme:%s:%s ", dbg_channel + 1, func );
-}
-
-int dbg_header_warn( const char *dbg_channel, const char *func )
-{
-    return dbg_printf( "warn:%s:%s ", dbg_channel + 1, func );
-}
-
-int dbg_header_trace( const char *dbg_channel, const char *func )
-{
-    return dbg_printf( "trace:%s:%s ", dbg_channel + 1, func );
-}
diff --git a/include/debugtools.h b/include/debugtools.h
index 3624b4bcdd7..01c450372e8 100644
--- a/include/debugtools.h
+++ b/include/debugtools.h
@@ -40,59 +40,60 @@ enum __DEBUG_CLASS { __DBCL_FIXME, __DBCL_ERR, __DBCL_WARN, __DBCL_TRACE, __DBCL
 #endif
 
 #define __DPRINTF(dbcl,dbch) \
-  (!__GET_DEBUGGING(dbcl,(dbch)) || (dbg_header_##dbcl((dbch),__FUNCTION__),0)) ? \
-     (void)0 : (void)dbg_printf
+  (!__GET_DEBUGGING(dbcl,(dbch)) || (__wine_dbg_header_##dbcl((dbch),__FUNCTION__),0)) ? \
+     (void)0 : (void)wine_dbg_printf
+
+extern int __wine_dbg_header_err( const char *dbg_channel, const char *func );
+extern int __wine_dbg_header_warn( const char *dbg_channel, const char *func );
+extern int __wine_dbg_header_fixme( const char *dbg_channel, const char *func );
+extern int __wine_dbg_header_trace( const char *dbg_channel, const char *func );
 
 /* Exported definitions and macros */
 
 /* These function return a printable version of a string, including
    quotes.  The string will be valid for some time, but not indefinitely
    as strings are re-used.  */
-extern LPCSTR debugstr_an (LPCSTR s, int n);
-extern LPCSTR debugstr_wn (LPCWSTR s, int n);
-extern LPCSTR debugres_a (LPCSTR res);
-extern LPCSTR debugres_w (LPCWSTR res);
-extern LPCSTR debugstr_guid( const struct _GUID *id );
-extern LPCSTR debugstr_hex_dump (const void *ptr, int len);
-extern int dbg_header_err( const char *dbg_channel, const char *func );
-extern int dbg_header_warn( const char *dbg_channel, const char *func );
-extern int dbg_header_fixme( const char *dbg_channel, const char *func );
-extern int dbg_header_trace( const char *dbg_channel, const char *func );
-extern int dbg_vprintf( const char *format, va_list args );
-
-static inline LPCSTR debugstr_a( LPCSTR s )  { return debugstr_an( s, 80 ); }
-static inline LPCSTR debugstr_w( LPCWSTR s ) { return debugstr_wn( s, 80 ); }
+extern const char *debugstr_an (const char * s, int n);
+extern const char *debugstr_wn (const WCHAR *s, int n);
+extern const char *debugstr_guid( const struct _GUID *id );
+
+extern int wine_dbg_vprintf( const char *format, va_list args );
+
+inline static const char *debugstr_a( const char *s )  { return debugstr_an( s, 80 ); }
+inline static const char *debugstr_w( const WCHAR *s ) { return debugstr_wn( s, 80 ); }
+inline static const char *debugres_a( const char *s )  { return debugstr_an( s, 80 ); }
+inline static const char *debugres_w( const WCHAR *s ) { return debugstr_wn( s, 80 ); }
 
 #ifdef __GNUC__
-extern int dbg_printf(const char *format, ...) __attribute__((format (printf,1,2)));
+extern int wine_dbg_printf(const char *format, ...) __attribute__((format (printf,1,2)));
 #else
-extern int dbg_printf(const char *format, ...);
+extern int wine_dbg_printf(const char *format, ...);
 #endif
 
-#define TRACE        __DPRINTF(trace,__dbch_default)
-#define TRACE_(ch)   __DPRINTF(trace,dbch_##ch)
-#define TRACE_ON(ch) __GET_DEBUGGING(trace,dbch_##ch)
+#define TRACE        __DPRINTF(trace,__wine_dbch___default)
+#define TRACE_(ch)   __DPRINTF(trace,__wine_dbch_##ch)
+#define TRACE_ON(ch) __GET_DEBUGGING(trace,__wine_dbch_##ch)
 
-#define WARN         __DPRINTF(warn,__dbch_default)
-#define WARN_(ch)    __DPRINTF(warn,dbch_##ch)
-#define WARN_ON(ch)  __GET_DEBUGGING(warn,dbch_##ch)
+#define WARN         __DPRINTF(warn,__wine_dbch___default)
+#define WARN_(ch)    __DPRINTF(warn,__wine_dbch_##ch)
+#define WARN_ON(ch)  __GET_DEBUGGING(warn,__wine_dbch_##ch)
 
-#define FIXME        __DPRINTF(fixme,__dbch_default)
-#define FIXME_(ch)   __DPRINTF(fixme,dbch_##ch)
-#define FIXME_ON(ch) __GET_DEBUGGING(fixme,dbch_##ch)
+#define FIXME        __DPRINTF(fixme,__wine_dbch___default)
+#define FIXME_(ch)   __DPRINTF(fixme,__wine_dbch_##ch)
+#define FIXME_ON(ch) __GET_DEBUGGING(fixme,__wine_dbch_##ch)
 
 #undef ERR  /* Solaris got an 'ERR' define in <sys/reg.h> */
-#define ERR          __DPRINTF(err,__dbch_default)
-#define ERR_(ch)     __DPRINTF(err,dbch_##ch)
-#define ERR_ON(ch)   __GET_DEBUGGING(err,dbch_##ch)
+#define ERR          __DPRINTF(err,__wine_dbch___default)
+#define ERR_(ch)     __DPRINTF(err,__wine_dbch_##ch)
+#define ERR_ON(ch)   __GET_DEBUGGING(err,__wine_dbch_##ch)
 
 #define DECLARE_DEBUG_CHANNEL(ch) \
-    extern char dbch_##ch[];
+    extern char __wine_dbch_##ch[];
 #define DEFAULT_DEBUG_CHANNEL(ch) \
-    extern char dbch_##ch[]; static char * const __dbch_default = dbch_##ch;
+    extern char __wine_dbch_##ch[]; static char * const __wine_dbch___default = __wine_dbch_##ch;
 
-#define DPRINTF dbg_printf
-#define MESSAGE dbg_printf
+#define DPRINTF wine_dbg_printf
+#define MESSAGE wine_dbg_printf
 
 #endif  /* __WINE__ */
 
diff --git a/include/main.h b/include/main.h
index 447207203aa..3a90d17df91 100644
--- a/include/main.h
+++ b/include/main.h
@@ -9,7 +9,6 @@
 
 extern BOOL MAIN_MainInit(void);
 extern void MAIN_WineInit(void);
-extern void MAIN_ParseDebugOptions(const char *options);
 
 extern BOOL RELAY_Init(void);
 extern int RELAY_ShowDebugmsgRelay(const char *func);
diff --git a/library/Makefile.in b/library/Makefile.in
index a6d68837a1d..224f1fd2200 100644
--- a/library/Makefile.in
+++ b/library/Makefile.in
@@ -9,6 +9,7 @@ SOVERSION = 1.0
 SONAME    = libwine.so
 
 C_SRCS = \
+	debug.c \
 	port.c
 
 all: libwine.$(LIBEXT)
diff --git a/library/debug.c b/library/debug.c
new file mode 100644
index 00000000000..3f38487b4a5
--- /dev/null
+++ b/library/debug.c
@@ -0,0 +1,118 @@
+/*
+ * Management of the debugging channels
+ *
+ * Copyright 2000 Alexandre Julliard
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+struct dll
+{
+    struct dll   *next;        /* linked list of dlls */
+    struct dll   *prev;
+    char * const *channels;    /* array of channels */
+    int           nb_channels; /* number of channels in array */
+};
+
+static struct dll *first_dll;
+
+struct option
+{
+    struct option *next;       /* next option in list */
+    unsigned char  set;        /* bits to set */
+    unsigned char  clear;      /* bits to clear */
+    char           name[14];   /* channel name, or empty for "all" */
+};
+
+static struct option *first_option;
+static struct option *last_option;
+
+
+static int cmp_name( const void *p1, const void *p2 )
+{
+    const char *name = p1;
+    const char * const *chan = p2;
+    return strcmp( name, *chan + 1 );
+}
+
+/* apply a debug option to the channels of a given dll */
+static void apply_option( struct dll *dll, const struct option *opt )
+{
+    if (opt->name[0])
+    {
+        char **dbch = bsearch( opt->name, dll->channels, dll->nb_channels,
+                               sizeof(*dll->channels), cmp_name );
+        if (dbch) **dbch = (**dbch & ~opt->clear) | opt->set;
+    }
+    else /* all */
+    {
+        int i;
+        for (i = 0; i < dll->nb_channels; i++)
+            dll->channels[i][0] = (dll->channels[i][0] & ~opt->clear) | opt->set;
+    }
+}
+
+/* register a new set of channels for a dll */
+void *wine_dbg_register( char * const *channels, int nb )
+{
+    struct option *opt = first_option;
+    struct dll *dll = malloc( sizeof(*dll) );
+    if (dll)
+    {
+        dll->channels = channels;
+        dll->nb_channels = nb;
+        dll->prev = NULL;
+        if ((dll->next = first_dll)) dll->next->prev = dll;
+        first_dll = dll;
+
+        /* apply existing options to this dll */
+        while (opt)
+        {
+            apply_option( dll, opt );
+            opt = opt->next;
+        }
+    }
+    return dll;
+}
+
+
+/* unregister a set of channels; must pass the pointer obtained from wine_dbg_register */
+void wine_dbg_unregister( void *channel )
+{
+    struct dll *dll = channel;
+    if (dll)
+    {
+        if (dll->next) dll->next->prev = dll->prev;
+        if (dll->prev) dll->prev->next = dll->next;
+        else first_dll = dll->next;
+        free( dll );
+    }
+}
+
+
+/* add a new debug option at the end of the option list */
+void wine_dbg_add_option( const char *name, unsigned char set, unsigned char clear )
+{
+    struct dll *dll = first_dll;
+    struct option *opt;
+
+    if (!(opt = malloc( sizeof(*opt) ))) return;
+    opt->next  = NULL;
+    opt->set   = set;
+    opt->clear = clear;
+    strncpy( opt->name, name, sizeof(opt->name) );
+    opt->name[sizeof(opt->name)-1] = 0;
+    if (last_option) last_option->next = opt;
+    else first_option = opt;
+    last_option = opt;
+
+    /* apply option to all existing dlls */
+    while (dll)
+    {
+        apply_option( dll, opt );
+        dll = dll->next;
+    }
+}
diff --git a/misc/Makefile.in b/misc/Makefile.in
index 90f1dda65d5..84eaf586b21 100644
--- a/misc/Makefile.in
+++ b/misc/Makefile.in
@@ -9,7 +9,6 @@ MODULE    = misc
 C_SRCS = \
 	cdrom.c \
 	cpu.c \
-	debugstr.c \
 	error.c \
 	ext_debugger.c \
 	lstr.c \
diff --git a/misc/debugstr.c b/misc/debugstr.c
deleted file mode 100644
index 021007ab6e0..00000000000
--- a/misc/debugstr.c
+++ /dev/null
@@ -1,332 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <ctype.h>
-
-#include "debugtools.h"
-#include "thread.h"
-#include "winbase.h"
-#include "winnt.h"
-#include "wtypes.h"
-
-/* ---------------------------------------------------------------------- */
-
-struct debug_info
-{
-    char *str_pos;       /* current position in strings buffer */
-    char *out_pos;       /* current position in output buffer */
-    char  strings[500];  /* buffer for temporary strings */
-    char  output[500];   /* current output line */
-};
-
-static struct debug_info tmp;
-
-static inline struct debug_info *get_info(void)
-{
-    struct debug_info *info = NtCurrentTeb()->debug_info;
-    if (!info)
-    {
-        /* setup the temp structure in case HeapAlloc wants to print something */
-        NtCurrentTeb()->debug_info = &tmp;
-        tmp.str_pos = tmp.strings;
-        tmp.out_pos = tmp.output;
-        info = HeapAlloc( GetProcessHeap(), 0, sizeof(*info) );
-        info->str_pos = info->strings;
-        info->out_pos = info->output;
-        NtCurrentTeb()->debug_info = info;
-    }
-    return info;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static void *
-gimme1 (int n)
-{
-    struct debug_info *info = get_info();
-    char *res = info->str_pos;
-
-    if (res + n >= &info->strings[sizeof(info->strings)]) res = info->strings;
-    info->str_pos = res + n;
-    return res;
-}
-
-/* ---------------------------------------------------------------------- */
-
-/* release extra space that we requested in gimme1() */
-static inline void release( void *ptr )
-{
-    struct debug_info *info = NtCurrentTeb()->debug_info;
-    info->str_pos = ptr;
-}
-
-/* ---------------------------------------------------------------------- */
-
-LPCSTR debugstr_an (LPCSTR src, int n)
-{
-  LPSTR dst, res;
-
-  if (!src) return "(null)";
-  if (n < 0) n = 0;
-  dst = res = gimme1 (n * 4 + 6);
-  *dst++ = '"';
-  while (n-- > 0 && *src)
-    {
-      BYTE c = *src++;
-      switch (c)
-	{
-	case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
-	case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
-	case '\t': *dst++ = '\\'; *dst++ = 't'; break;
-	case '"': *dst++ = '\\'; *dst++ = '"'; break;
-	case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
-	default:
-	  if (c >= ' ' && c <= 126)
-	    *dst++ = c;
-	  else
-	    {
-	      *dst++ = '\\';
-	      *dst++ = '0' + ((c >> 6) & 7);
-	      *dst++ = '0' + ((c >> 3) & 7);
-	      *dst++ = '0' + ((c >> 0) & 7);
-	    }
-	}
-    }
-  *dst++ = '"';
-  if (*src)
-    {
-      *dst++ = '.';
-      *dst++ = '.';
-      *dst++ = '.';
-    }
-  *dst++ = '\0';
-  release( dst );
-  return res;
-}
-
-/* ---------------------------------------------------------------------- */
-
-LPCSTR debugstr_wn (LPCWSTR src, int n)
-{
-  LPSTR dst, res;
-
-  if (!src) return "(null)";
-  if (n < 0) n = 0;
-  dst = res = gimme1 (n * 5 + 7);
-  *dst++ = 'L';
-  *dst++ = '"';
-  while (n-- > 0 && *src)
-    {
-      WORD c = *src++;
-      switch (c)
-	{
-	case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
-	case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
-	case '\t': *dst++ = '\\'; *dst++ = 't'; break;
-	case '"': *dst++ = '\\'; *dst++ = '"'; break;
-	case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
-	default:
-	  if (c >= ' ' && c <= 126)
-	    *dst++ = c;
-	  else 
-	    {
-	      *dst++ = '\\';
-              sprintf(dst,"%04x",c);
-              dst+=4;
-	    }
-	}
-    }
-  *dst++ = '"';
-  if (*src)
-    {
-      *dst++ = '.';
-      *dst++ = '.';
-      *dst++ = '.';
-    }
-  *dst++ = '\0';
-  release( dst );
-  return res;
-}
-
-/* ---------------------------------------------------------------------- */
-/* This routine returns a nicely formated name of the resource res
-   If the resource name is a string, it will return '<res-name>'
-   If it is a number, it will return #<4-digit-hex-number> */
-LPCSTR debugres_a( LPCSTR res )
-{
-    char *resname;
-    if (HIWORD(res)) return debugstr_a(res);
-    resname = gimme1(6);
-    sprintf(resname, "#%04x", LOWORD(res) );
-    return resname;
-}
-
-LPCSTR debugres_w( LPCWSTR res )
-{
-    char *resname;
-    if (HIWORD(res)) return debugstr_w(res);
-    resname = gimme1(6);
-    sprintf( resname, "#%04x", LOWORD(res) );
-    return resname;
-}
-
-/* ---------------------------------------------------------------------- */
-
-LPCSTR debugstr_guid( const GUID *id )
-{
-    LPSTR str;
-
-    if (!id) return "(null)";
-    if (!HIWORD(id))
-    {
-        str = gimme1(12);
-        sprintf( str, "<guid-0x%04x>", LOWORD(id) );
-    }
-    else
-    {
-        str = gimme1(40);
-        sprintf( str, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
-                 id->Data1, id->Data2, id->Data3,
-                 id->Data4[0], id->Data4[1], id->Data4[2], id->Data4[3],
-                 id->Data4[4], id->Data4[5], id->Data4[6], id->Data4[7] );
-    }
-    return str;
-}
-
-/* ---------------------------------------------------------------------- */
-
-int dbg_vprintf( const char *format, va_list args )
-{
-    struct debug_info *info = get_info();
-
-    int ret = vsprintf( info->out_pos, format, args );
-    char *p = strrchr( info->out_pos, '\n' );
-    if (!p) info->out_pos += ret;
-    else
-    {
-        char *pos = info->output;
-        p++;
-        write( 2, pos, p - pos );
-        /* move beginning of next line to start of buffer */
-        while ((*pos = *p++)) pos++;
-        info->out_pos = pos;
-    }
-    return ret;
-}
-
-/* ---------------------------------------------------------------------- */
-
-int dbg_printf(const char *format, ...)
-{
-    int ret;
-    va_list valist;
-
-    va_start(valist, format);
-    ret = dbg_vprintf( format, valist);
-    va_end(valist);
-    return ret;
-}
-
-
-/*--< Function >---------------------------------------------------------
-**  
-**              debugstr_hex_dump
-**              
-**  Description:
-**      This function creates a hex dump, with a readable ascii
-**  section, for displaying memory.
-**  
-**  Parameters:
-**      1.  ptr             Pointer to memory
-**      2.  len             How much to dump.
-**
-**  Returns:
-**    Temporarily allocated buffer, with the hex dump in it.
-**  Don't rely on this pointer being around for very long, just
-**  long enough to use it in a TRACE statement; e.g.:
-**  TRACE("struct dump is \n%s", debugstr_hex_dump(&x, sizeof(x)));
-**          
-**-------------------------------------------------------------------------*/
-LPCSTR debugstr_hex_dump (const void *ptr, int len)
-{
-    /* Locals */
-    char          dumpbuf[59];
-    char          charbuf[20];
-    char          tempbuf[8];
-    const char    *p;
-    int           i;
-    unsigned int  nosign;
-    LPSTR         dst;
-    LPSTR         outptr;
-
-/* Begin function dbg_hex_dump */
-
-    /*-----------------------------------------------------------------------
-    **  Allocate an output buffer
-    **      A reasonable value is one line overhand (80 chars), and
-    **      then one line (80) for every 16 bytes.
-    **---------------------------------------------------------------------*/
-    outptr = dst = gimme1 ((len * (80 / 16)) + 80);
-
-    /*-----------------------------------------------------------------------
-    **  Loop throught the input buffer, one character at a time
-    **---------------------------------------------------------------------*/
-    for (i = 0, p = ptr; (i < len); i++, p++)
-    {
-
-        /*-------------------------------------------------------------------
-        **  If we're just starting a line, 
-        **      we need to possibly flush the old line, and then
-        **      intialize the line buffer.
-        **-----------------------------------------------------------------*/
-        if ((i % 16) == 0)
-        {
-            if (i)
-            {
-                sprintf(outptr, "  %-43.43s   %-16.16s\n", dumpbuf, charbuf);
-                outptr += strlen(outptr);
-            }
-            sprintf (dumpbuf, "%04x: ", i);
-            strcpy (charbuf, "");
-        }
-
-        /*-------------------------------------------------------------------
-        **  Add the current data byte to the dump section.
-        **-----------------------------------------------------------------*/
-        nosign = (unsigned char) *p;
-        sprintf (tempbuf, "%02X", nosign);
-
-        /*-------------------------------------------------------------------
-        **  If we're two DWORDS through, add a hyphen for readability,
-        **      if it's a DWORD boundary, add a space for more
-        **      readability.
-        **-----------------------------------------------------------------*/
-        if ((i % 16) == 7)
-            strcat(tempbuf, " - ");
-        else if ( (i % 4) == 3)
-            strcat(tempbuf, " ");
-        strcat (dumpbuf, tempbuf);
-
-        /*-------------------------------------------------------------------
-        **  Add the current byte to the character display part of the
-        **      hex dump
-        **-----------------------------------------------------------------*/
-        sprintf (tempbuf, "%c", isprint(*p) ? *p : '.');
-        strcat (charbuf, tempbuf);
-    }
-
-    /*-----------------------------------------------------------------------
-    **  Flush the last line, if any
-    **---------------------------------------------------------------------*/
-    if (i > 0)
-    {
-        sprintf(outptr, "  %-43.43s   %-16.16s\n", dumpbuf, charbuf);
-        outptr += strlen(outptr);
-    }
-
-    return(dst);
-} /* End function dbg_hex_dump */
-
-
-
diff --git a/misc/main.c b/misc/main.c
index 6233840eaf8..357db380417 100644
--- a/misc/main.c
+++ b/misc/main.c
@@ -27,11 +27,13 @@
 #include "msdos.h"
 #include "options.h"
 #include "debugtools.h"
-#include "debugdefs.h"
 #include "module.h"
 #include "tweak.h"
 
+DECLARE_DEBUG_CHANNEL(file);
 
+
+#if 0
 /***********************************************************************
  *          MAIN_ParseDebugOptions
  *
@@ -176,6 +178,7 @@ void MAIN_ParseDebugOptions( const char *arg )
   MESSAGE("\n\n");
   ExitProcess(1);
 }
+#endif
 
 /***********************************************************************
  *           MAIN_WineInit
diff --git a/misc/options.c b/misc/options.c
index e1e715495b3..575067f7ac8 100644
--- a/misc/options.c
+++ b/misc/options.c
@@ -60,6 +60,7 @@ static char *xstrdup( const char *str )
 }
 
 static void do_config( const char *arg );
+static void do_debugmsg( const char *arg );
 static void do_desktop( const char *arg );
 static void do_display( const char *arg );
 static void do_dll( const char *arg );
@@ -73,7 +74,7 @@ static const struct option option_table[] =
 {
     { "config",       0, 1, 0, do_config,
       "--config name    Specify config file to use" },
-    { "debugmsg",     0, 1, 1, MAIN_ParseDebugOptions,
+    { "debugmsg",     0, 1, 1, do_debugmsg,
       "--debugmsg name  Turn debugging-messages on or off" },
     { "desktop",      0, 1, 1, do_desktop,
       "--desktop geom   Use a desktop window of the given geometry" },
@@ -157,6 +158,62 @@ static void do_config( const char *arg )
     Options.configFileName = xstrdup( arg );
 }
 
+static void do_debugmsg( const char *arg )
+{
+    extern void wine_dbg_add_option( const char *name, unsigned char set, unsigned char clear );
+    static const char * const debug_class_names[__DBCL_COUNT] = { "fixme", "err", "warn", "trace" };
+
+    char *opt, *options = strdup(arg);
+    int i;
+
+    if (!(opt = strtok( options, "," ))) goto error;
+    do
+    {
+        unsigned char set = 0, clear = 0;
+        char *p = strchr( opt, '+' );
+        if (!p) p = strchr( opt, '-' );
+        if (!p || !p[1]) goto error;
+        if (p > opt)
+        {
+            for (i = 0; i < __DBCL_COUNT; i++)
+            {
+                int len = strlen(debug_class_names[i]);
+                if (len != (p - opt)) continue;
+                if (!memcmp( opt, debug_class_names[i], len ))  /* found it */
+                {
+                    if (*p == '+') set |= 1 << i;
+                    else clear |= 1 << i;
+                    break;
+                }
+            }
+            if (i == __DBCL_COUNT) goto error;  /* class name not found */
+        }
+        else
+        {
+            if (*p == '+') set = ~0;
+            else clear = ~0;
+        }
+        p++;
+        if (!strcmp( p, "all" )) p = "";  /* empty string means all */
+        wine_dbg_add_option( p, set, clear );
+        opt = strtok( NULL, "," );
+    } while(opt);
+
+    free( options );
+    return;
+
+ error:
+    MESSAGE("wine: Syntax: --debugmsg [class]+xxx,...  or "
+            "-debugmsg [class]-xxx,...\n");
+    MESSAGE("Example: --debugmsg +all,warn-heap\n"
+            "  turn on all messages except warning heap messages\n");
+    MESSAGE("Available message classes:\n");
+    for( i = 0; i < __DBCL_COUNT; i++) MESSAGE( "%-9s", debug_class_names[i] );
+    MESSAGE("\n\n");
+    ExitProcess(1);
+}
+
+
 static void remove_options( char *argv[], int pos, int count, int inherit )
 {
     if (inherit)
diff --git a/relay32/builtin32.c b/relay32/builtin32.c
index cdb288c098f..e741bc98139 100644
--- a/relay32/builtin32.c
+++ b/relay32/builtin32.c
@@ -249,7 +249,7 @@ static HMODULE BUILTIN32_DoLoadImage( const BUILTIN32_DESCRIPTOR *descr )
         fixup_rva_ptrs( &exports->AddressOfNameOrdinals, addr, 1 );
 
         /* Setup relay debugging entry points */
-        if (WARN_ON(relay) || TRACE_ON(relay)) RELAY_SetupDLL( addr );
+        if (TRACE_ON(relay)) RELAY_SetupDLL( addr );
     }
 
     return (HMODULE)addr;
diff --git a/tools/find_debug_channels b/tools/find_debug_channels
deleted file mode 100755
index 05377e82c96..00000000000
--- a/tools/find_debug_channels
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/bin/sh
-#
-# This script scans the whole source code for symbols of the form 
-# 'xxx(yyy' where:
-#        xxx is either DECLARE_DEBUG_CHANNEL or DEFAULT_DEBUG_CHANNEL
-#        yyy is a C identifier 
-# It outputs on the standard output a sorted list of the 
-# yyy identifiers found in the .c files. 
-# Each identifier is reported once. Header files are not scanned.
-#
-# The script can be given an argument that specifies the files to be
-# searched according to the following scheme:
-#    - if the argument does not contain a slash (/), the script
-#      will search the tree rooted in the current directory for
-#      files that match that description. You can also pass
-#      wildcard arguments, but remember to quote them to prevent
-#      expansion by the shell
-#    - if the argument does contain a slash, only that file is
-#      searched
-#    - if no argument is given, the argument defaults to "*.c"
-#      that is, all C files are searched.
-#    - if more than one argument is given, only the listed files are
-#      searched. Note that in this case, the script will not
-#      attempt to find them in some subdirectories, but rather
-#      it will try to open them in the current directory.
-# Thus, if you want to disable the automatic searching when the file
-# name does not contain a /, either prefix the filename with ./
-# or add /dev/null as another argument.
-#
-# Dimitrie O. Paun <dimi@cs.toronto.edu>
-# Patrik Stridvall <ps@leissner.se>
-#
-
-case "$#" in
-    0 | 1)  files="${1:-*.c}"
-	    if [ "`echo "$files" | sed 's/^\(.*\)\/$/\1/g'`" = "$files" ]; then
-		files=`find . -name "$files" -print`
-	    fi;;
-    *    )  files="$@";;
-esac
-
-(
-grep -h "DECLARE_DEBUG_CHANNEL *(" $files /dev/null | \
-    sed 's/.*DECLARE_DEBUG_CHANNEL( *\([A-Za-z0-9_]*\) *).*/\1/g'
-grep -h "DEFAULT_DEBUG_CHANNEL *(" $files /dev/null | \
-    sed 's/.*DEFAULT_DEBUG_CHANNEL( *\([A-Za-z0-9_]*\) *).*/\1/g'
-) | sort | uniq
diff --git a/tools/make_debug b/tools/make_debug
index e5a59f0044a..7916f8ec529 100755
--- a/tools/make_debug
+++ b/tools/make_debug
@@ -1,60 +1,56 @@
-#!/bin/sh
+#!/usr/bin/perl
 #
-# This script generates the required file for supporting the debug
-# channels used throught the code.
-# The generated file is
-#   include/debugdefs.h
-# The script must be run in the root directory of the project.
+# Update the list of debug channels of a given spec file
 #
-# Dimitrie O. Paun <dimi@cs.toronto.edu>
-# Patrik Stridvall <ps@leissner.se>
+# Copyright 2000 Alexandre Julliard
+#
+# Usage: make_debug spec_file [source_files...]
 #
 
-DEBUG_CHANNELS=`tools/find_debug_channels`
-
-exec > include/debugdefs.h
-
-cat <<EOF
-/* Do not modify this file -- it is automatically generated! */
-
-#include "debugtools.h"
-
-#define DEBUG_CLASS_COUNT __DBCL_COUNT
-
-static const char * const debug_cl_name[] = { "fixme", "err", "warn", "trace" };
-
-EOF
-
-chno=0
-for ch in $DEBUG_CHANNELS
-do
-    echo "char dbch_$ch[] = \"\\003$ch\";"
-    chno=`expr $chno + 1`
-done
-echo
-echo "#define DEBUG_CHANNEL_COUNT $chno"
+die "Usage: make_debug spec_file [source]\n" unless @ARGV;
 
-count=1
-echo
-echo 'static char * const debug_channels[DEBUG_CHANNEL_COUNT] = {'
-for ch in $DEBUG_CHANNELS
-do
-    if [ "${count}" != "${chno}" ]; then
-	echo "    dbch_${ch},"
-    else
-	echo "    dbch_${ch}"
-    fi
-    count=`expr $count + 1`
-done
-echo '};'
+$SPEC = shift @ARGV;
 
-for cls in err fixme warn trace
-do
-    cat <<EOF
+# read in all the source files
+if (@ARGV)
+{
+    while (<>)
+    {
+        if (/DECLARE_DEBUG_CHANNEL\s*\(\s*([A-Za-z0-9_]+)\s*\)/) { $channels{$1} = 1; }
+        if (/DEFAULT_DEBUG_CHANNEL\s*\(\s*([A-Za-z0-9_]+)\s*\)/) { $channels{$1} = 1; }
+    }
+}
+@dbg_channels = sort keys %channels;
+
+# read the whole spec file
+undef $/;
+open SPEC or die "Cannot open $SPEC\n";
+$spec = <SPEC>;
+close SPEC;
+
+# build the new channel list
+$channel_str = "debug_channels (";
+$pos = length($channel_str);
+for ($i = 0; $i <= $#dbg_channels; $i++)
+{
+   $channel_str .= $dbg_channels[$i];
+   $pos += length($dbg_channels[$i]);
+   if ($i < $#dbg_channels)
+   {
+       if ($pos >= 75) { $pos = 16; $channel_str .= "\n" . (" " x $pos); }
+       else { $channel_str .= " "; $pos++; }
+   }
+}
+$channel_str .= ")";
 
-int dbg_header_$cls( const char *dbg_channel, const char *func )
+# replace the list in the spec file
+if (!($spec =~ s/debug_channels\s*\(([^)]*)\)/$channel_str/))
 {
-    return dbg_printf( "$cls:%s:%s ", dbg_channel + 1, func );
+    die "Could not replace debug_channels\n" if @dbg_channels;
+    exit 0;
 }
-EOF
-done
+
+# output the modified spec file
+open OUTPUT, ">$SPEC" or die "Cannot modify $SPEC\n";
+print OUTPUT $spec;
+close OUTPUT;
-- 
GitLab