1
0
mirror of https://github.com/wine-mirror/wine synced 2024-07-08 20:06:18 +00:00

New debug channel mechanism allowing decentralized channel

declarations.
This commit is contained in:
Alexandre Julliard 2000-11-05 04:51:34 +00:00
parent 9a634693e7
commit 94613ab03e
15 changed files with 523 additions and 834 deletions

View File

@ -7,6 +7,7 @@ SOVERSION = 1.0
C_SRCS = \
critsection.c \
debugtools.c \
exception.c \
error.c \
file.c \

238
dlls/ntdll/debugtools.c Normal file
View File

@ -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 );
}

View File

@ -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

View File

@ -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 );
}

View File

@ -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 );
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 );
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 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__ */

View File

@ -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);

View File

@ -9,6 +9,7 @@ SOVERSION = 1.0
SONAME = libwine.so
C_SRCS = \
debug.c \
port.c
all: libwine.$(LIBEXT)

118
library/debug.c Normal file
View File

@ -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;
}
}

View File

@ -9,7 +9,6 @@ MODULE = misc
C_SRCS = \
cdrom.c \
cpu.c \
debugstr.c \
error.c \
ext_debugger.c \
lstr.c \

View File

@ -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 */

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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

View File

@ -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`
die "Usage: make_debug spec_file [source]\n" unless @ARGV;
exec > include/debugdefs.h
$SPEC = shift @ARGV;
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"
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 '};'
for cls in err fixme warn trace
do
cat <<EOF
int dbg_header_$cls( const char *dbg_channel, const char *func )
# read in all the source files
if (@ARGV)
{
return dbg_printf( "$cls:%s:%s ", dbg_channel + 1, func );
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; }
}
}
EOF
done
@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 .= ")";
# replace the list in the spec file
if (!($spec =~ s/debug_channels\s*\(([^)]*)\)/$channel_str/))
{
die "Could not replace debug_channels\n" if @dbg_channels;
exit 0;
}
# output the modified spec file
open OUTPUT, ">$SPEC" or die "Cannot modify $SPEC\n";
print OUTPUT $spec;
close OUTPUT;