mirror of
https://github.com/reactos/wine.git
synced 2025-02-09 05:36:56 +00:00
Export the temp buffer functionality in the debug functions interface
to allow sharing more code between libwine and ntdll.
This commit is contained in:
parent
2f9678727f
commit
a443761b8d
@ -42,6 +42,8 @@
|
|||||||
|
|
||||||
WINE_DECLARE_DEBUG_CHANNEL(tid);
|
WINE_DECLARE_DEBUG_CHANNEL(tid);
|
||||||
|
|
||||||
|
static struct __wine_debug_functions default_funcs;
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
/* filter for page-fault exceptions */
|
/* filter for page-fault exceptions */
|
||||||
@ -59,7 +61,7 @@ static inline struct debug_info *get_info(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* allocate some tmp space for a string */
|
/* allocate some tmp space for a string */
|
||||||
static void *gimme1(int n)
|
static char *get_temp_buffer( size_t n )
|
||||||
{
|
{
|
||||||
struct debug_info *info = get_info();
|
struct debug_info *info = get_info();
|
||||||
char *res = info->str_pos;
|
char *res = info->str_pos;
|
||||||
@ -70,101 +72,10 @@ static void *gimme1(int n)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* release extra space that we requested in gimme1() */
|
/* release extra space that we requested in gimme1() */
|
||||||
static inline void release( void *ptr )
|
static void release_temp_buffer( char *ptr, size_t size )
|
||||||
{
|
{
|
||||||
struct debug_info *info = get_info();
|
struct debug_info *info = get_info();
|
||||||
info->str_pos = ptr;
|
info->str_pos = ptr + size;
|
||||||
}
|
|
||||||
|
|
||||||
/* put an ASCII string into the debug buffer */
|
|
||||||
inline static char *put_string_a( const char *src, int n )
|
|
||||||
{
|
|
||||||
static const char hex[16] = "0123456789abcdef";
|
|
||||||
char *dst, *res;
|
|
||||||
size_t size;
|
|
||||||
|
|
||||||
if (n == -1) n = strlen(src);
|
|
||||||
if (n < 0) n = 0;
|
|
||||||
size = 10 + min( 300, n * 4 );
|
|
||||||
dst = res = gimme1( size );
|
|
||||||
*dst++ = '"';
|
|
||||||
while (n-- > 0 && dst <= res + size - 9)
|
|
||||||
{
|
|
||||||
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++ = 'x';
|
|
||||||
*dst++ = hex[(c >> 4) & 0x0f];
|
|
||||||
*dst++ = hex[c & 0x0f];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*dst++ = '"';
|
|
||||||
if (*src)
|
|
||||||
{
|
|
||||||
*dst++ = '.';
|
|
||||||
*dst++ = '.';
|
|
||||||
*dst++ = '.';
|
|
||||||
}
|
|
||||||
*dst++ = '\0';
|
|
||||||
release( dst );
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* put a Unicode string into the debug buffer */
|
|
||||||
inline static char *put_string_w( const WCHAR *src, int n )
|
|
||||||
{
|
|
||||||
char *dst, *res;
|
|
||||||
size_t size;
|
|
||||||
|
|
||||||
if (n == -1) n = strlenW(src);
|
|
||||||
if (n < 0) n = 0;
|
|
||||||
size = 12 + min( 300, n * 5 );
|
|
||||||
dst = res = gimme1( size );
|
|
||||||
*dst++ = 'L';
|
|
||||||
*dst++ = '"';
|
|
||||||
while (n-- > 0 && dst <= res + size - 10)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
@ -172,25 +83,18 @@ inline static char *put_string_w( const WCHAR *src, int n )
|
|||||||
*/
|
*/
|
||||||
static const char *NTDLL_dbgstr_an( const char *src, int n )
|
static const char *NTDLL_dbgstr_an( const char *src, int n )
|
||||||
{
|
{
|
||||||
char *res, *old_pos;
|
const char *res;
|
||||||
struct debug_info *info = get_info();
|
struct debug_info *info = get_info();
|
||||||
|
|
||||||
if (!HIWORD(src))
|
|
||||||
{
|
|
||||||
if (!src) return "(null)";
|
|
||||||
res = gimme1(6);
|
|
||||||
sprintf(res, "#%04x", LOWORD(src) );
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
/* save current position to restore it on exception */
|
/* save current position to restore it on exception */
|
||||||
old_pos = info->str_pos;
|
char *old_pos = info->str_pos;
|
||||||
|
|
||||||
__TRY
|
__TRY
|
||||||
{
|
{
|
||||||
res = put_string_a( src, n );
|
res = default_funcs.dbgstr_an( src, n );
|
||||||
}
|
}
|
||||||
__EXCEPT(page_fault)
|
__EXCEPT(page_fault)
|
||||||
{
|
{
|
||||||
release( old_pos );
|
release_temp_buffer( old_pos, 0 );
|
||||||
return "(invalid)";
|
return "(invalid)";
|
||||||
}
|
}
|
||||||
__ENDTRY
|
__ENDTRY
|
||||||
@ -202,46 +106,24 @@ static const char *NTDLL_dbgstr_an( const char *src, int n )
|
|||||||
*/
|
*/
|
||||||
static const char *NTDLL_dbgstr_wn( const WCHAR *src, int n )
|
static const char *NTDLL_dbgstr_wn( const WCHAR *src, int n )
|
||||||
{
|
{
|
||||||
char *res, *old_pos;
|
const char *res;
|
||||||
struct debug_info *info = get_info();
|
struct debug_info *info = get_info();
|
||||||
|
|
||||||
if (!HIWORD(src))
|
|
||||||
{
|
|
||||||
if (!src) return "(null)";
|
|
||||||
res = gimme1(6);
|
|
||||||
sprintf(res, "#%04x", LOWORD(src) );
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* save current position to restore it on exception */
|
/* save current position to restore it on exception */
|
||||||
old_pos = info->str_pos;
|
char *old_pos = info->str_pos;
|
||||||
|
|
||||||
__TRY
|
__TRY
|
||||||
{
|
{
|
||||||
res = put_string_w( src, n );
|
res = default_funcs.dbgstr_wn( src, n );
|
||||||
}
|
}
|
||||||
__EXCEPT(page_fault)
|
__EXCEPT(page_fault)
|
||||||
{
|
{
|
||||||
release( old_pos );
|
release_temp_buffer( old_pos, 0 );
|
||||||
return "(invalid)";
|
return "(invalid)";
|
||||||
}
|
}
|
||||||
__ENDTRY
|
__ENDTRY
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* NTDLL_dbg_vsprintf
|
|
||||||
*/
|
|
||||||
static const char *NTDLL_dbg_vsprintf( const char *format, va_list args )
|
|
||||||
{
|
|
||||||
static const int max_size = 200;
|
|
||||||
|
|
||||||
char *res = gimme1( max_size );
|
|
||||||
int len = vsnprintf( res, max_size, format, args );
|
|
||||||
if (len == -1 || len >= max_size) res[max_size-1] = 0;
|
|
||||||
else release( res + len + 1 );
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* NTDLL_dbg_vprintf
|
* NTDLL_dbg_vprintf
|
||||||
*/
|
*/
|
||||||
@ -305,9 +187,10 @@ static int NTDLL_dbg_vlog( enum __wine_debug_class cls, struct __wine_debug_chan
|
|||||||
|
|
||||||
static const struct __wine_debug_functions funcs =
|
static const struct __wine_debug_functions funcs =
|
||||||
{
|
{
|
||||||
|
get_temp_buffer,
|
||||||
|
release_temp_buffer,
|
||||||
NTDLL_dbgstr_an,
|
NTDLL_dbgstr_an,
|
||||||
NTDLL_dbgstr_wn,
|
NTDLL_dbgstr_wn,
|
||||||
NTDLL_dbg_vsprintf,
|
|
||||||
NTDLL_dbg_vprintf,
|
NTDLL_dbg_vprintf,
|
||||||
NTDLL_dbg_vlog
|
NTDLL_dbg_vlog
|
||||||
};
|
};
|
||||||
@ -319,6 +202,6 @@ void debug_init(void)
|
|||||||
{
|
{
|
||||||
extern void __wine_dbg_ntdll_init(void);
|
extern void __wine_dbg_ntdll_init(void);
|
||||||
|
|
||||||
__wine_dbg_set_functions( &funcs, sizeof(funcs) );
|
__wine_dbg_set_functions( &funcs, &default_funcs, sizeof(funcs) );
|
||||||
__wine_dbg_ntdll_init(); /* hack: register debug channels early */
|
__wine_dbg_ntdll_init(); /* hack: register debug channels early */
|
||||||
}
|
}
|
||||||
|
@ -137,15 +137,17 @@ struct __wine_debug_channel
|
|||||||
|
|
||||||
struct __wine_debug_functions
|
struct __wine_debug_functions
|
||||||
{
|
{
|
||||||
|
char * (*get_temp_buffer)( size_t n );
|
||||||
|
void (*release_temp_buffer)( char *buffer, size_t n );
|
||||||
const char * (*dbgstr_an)( const char * s, int n );
|
const char * (*dbgstr_an)( const char * s, int n );
|
||||||
const char * (*dbgstr_wn)( const WCHAR *s, int n );
|
const char * (*dbgstr_wn)( const WCHAR *s, int n );
|
||||||
const char * (*dbg_vsprintf)( const char *format, va_list args );
|
|
||||||
int (*dbg_vprintf)( const char *format, va_list args );
|
int (*dbg_vprintf)( const char *format, va_list args );
|
||||||
int (*dbg_vlog)( enum __wine_debug_class cls, struct __wine_debug_channel *channel,
|
int (*dbg_vlog)( enum __wine_debug_class cls, struct __wine_debug_channel *channel,
|
||||||
const char *function, const char *format, va_list args );
|
const char *function, const char *format, va_list args );
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void __wine_dbg_set_functions( const struct __wine_debug_functions *funcs, size_t size );
|
extern void __wine_dbg_set_functions( const struct __wine_debug_functions *new_funcs,
|
||||||
|
struct __wine_debug_functions *old_funcs, size_t size );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Exported definitions and macros
|
* Exported definitions and macros
|
||||||
|
@ -198,7 +198,7 @@ int wine_dbg_parse_options( const char *str )
|
|||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* varargs wrapper for __wine_dbg_vprintf */
|
/* varargs wrapper for funcs.dbg_vprintf */
|
||||||
int wine_dbg_printf( const char *format, ... )
|
int wine_dbg_printf( const char *format, ... )
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@ -210,21 +210,25 @@ int wine_dbg_printf( const char *format, ... )
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* printf with temp buffer allocation */
|
||||||
/* varargs wrapper for __wine_dbg_vsprintf */
|
|
||||||
const char *wine_dbg_sprintf( const char *format, ... )
|
const char *wine_dbg_sprintf( const char *format, ... )
|
||||||
{
|
{
|
||||||
const char *ret;
|
static const int max_size = 200;
|
||||||
|
char *ret;
|
||||||
|
int len;
|
||||||
va_list valist;
|
va_list valist;
|
||||||
|
|
||||||
va_start(valist, format);
|
va_start(valist, format);
|
||||||
ret = funcs.dbg_vsprintf( format, valist );
|
ret = funcs.get_temp_buffer( max_size );
|
||||||
|
len = vsnprintf( ret, max_size, format, valist );
|
||||||
|
if (len == -1 || len >= max_size) ret[max_size-1] = 0;
|
||||||
|
else funcs.release_temp_buffer( ret, len + 1 );
|
||||||
va_end(valist);
|
va_end(valist);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* varargs wrapper for __wine_dbg_vlog */
|
/* varargs wrapper for funcs.dbg_vlog */
|
||||||
int wine_dbg_log( enum __wine_debug_class cls, struct __wine_debug_channel *channel,
|
int wine_dbg_log( enum __wine_debug_class cls, struct __wine_debug_channel *channel,
|
||||||
const char *func, const char *format, ... )
|
const char *func, const char *format, ... )
|
||||||
{
|
{
|
||||||
@ -240,7 +244,7 @@ int wine_dbg_log( enum __wine_debug_class cls, struct __wine_debug_channel *chan
|
|||||||
|
|
||||||
/* allocate some tmp string space */
|
/* allocate some tmp string space */
|
||||||
/* FIXME: this is not 100% thread-safe */
|
/* FIXME: this is not 100% thread-safe */
|
||||||
static char *get_tmp_space( int size )
|
static char *get_temp_buffer( size_t size )
|
||||||
{
|
{
|
||||||
static char *list[32];
|
static char *list[32];
|
||||||
static int pos;
|
static int pos;
|
||||||
@ -253,24 +257,33 @@ static char *get_tmp_space( int size )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* release unused part of the buffer */
|
||||||
|
static void release_temp_buffer( char *buffer, size_t size )
|
||||||
|
{
|
||||||
|
/* don't bother doing anything */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* default implementation of wine_dbgstr_an */
|
/* default implementation of wine_dbgstr_an */
|
||||||
static const char *default_dbgstr_an( const char *str, int n )
|
static const char *default_dbgstr_an( const char *str, int n )
|
||||||
{
|
{
|
||||||
|
static const char hex[16] = "0123456789abcdef";
|
||||||
char *dst, *res;
|
char *dst, *res;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
if (!HIWORD(str))
|
if (!((ULONG_PTR)str >> 16))
|
||||||
{
|
{
|
||||||
if (!str) return "(null)";
|
if (!str) return "(null)";
|
||||||
res = get_tmp_space( 6 );
|
res = funcs.get_temp_buffer( 6 );
|
||||||
sprintf( res, "#%04x", LOWORD(str) );
|
sprintf( res, "#%04x", LOWORD(str) );
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
if (n == -1) n = strlen(str);
|
if (n == -1) n = strlen(str);
|
||||||
if (n < 0) n = 0;
|
if (n < 0) n = 0;
|
||||||
else if (n > 200) n = 200;
|
size = 10 + min( 300, n * 4 );
|
||||||
dst = res = get_tmp_space( n * 4 + 6 );
|
dst = res = funcs.get_temp_buffer( size );
|
||||||
*dst++ = '"';
|
*dst++ = '"';
|
||||||
while (n-- > 0)
|
while (n-- > 0 && dst <= res + size - 9)
|
||||||
{
|
{
|
||||||
unsigned char c = *str++;
|
unsigned char c = *str++;
|
||||||
switch (c)
|
switch (c)
|
||||||
@ -286,9 +299,9 @@ static const char *default_dbgstr_an( const char *str, int n )
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
*dst++ = '\\';
|
*dst++ = '\\';
|
||||||
*dst++ = '0' + ((c >> 6) & 7);
|
*dst++ = 'x';
|
||||||
*dst++ = '0' + ((c >> 3) & 7);
|
*dst++ = hex[(c >> 4) & 0x0f];
|
||||||
*dst++ = '0' + ((c >> 0) & 7);
|
*dst++ = hex[c & 0x0f];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -299,7 +312,8 @@ static const char *default_dbgstr_an( const char *str, int n )
|
|||||||
*dst++ = '.';
|
*dst++ = '.';
|
||||||
*dst++ = '.';
|
*dst++ = '.';
|
||||||
}
|
}
|
||||||
*dst = 0;
|
*dst++ = 0;
|
||||||
|
funcs.release_temp_buffer( res, dst - res );
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,21 +322,22 @@ static const char *default_dbgstr_an( const char *str, int n )
|
|||||||
static const char *default_dbgstr_wn( const WCHAR *str, int n )
|
static const char *default_dbgstr_wn( const WCHAR *str, int n )
|
||||||
{
|
{
|
||||||
char *dst, *res;
|
char *dst, *res;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
if (!HIWORD(str))
|
if (!((ULONG_PTR)str >> 16))
|
||||||
{
|
{
|
||||||
if (!str) return "(null)";
|
if (!str) return "(null)";
|
||||||
res = get_tmp_space( 6 );
|
res = funcs.get_temp_buffer( 6 );
|
||||||
sprintf( res, "#%04x", LOWORD(str) );
|
sprintf( res, "#%04x", LOWORD(str) );
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
if (n == -1) n = strlenW(str);
|
if (n == -1) n = strlenW(str);
|
||||||
if (n < 0) n = 0;
|
if (n < 0) n = 0;
|
||||||
else if (n > 200) n = 200;
|
size = 12 + min( 300, n * 5 );
|
||||||
dst = res = get_tmp_space( n * 5 + 7 );
|
dst = res = funcs.get_temp_buffer( n * 5 + 7 );
|
||||||
*dst++ = 'L';
|
*dst++ = 'L';
|
||||||
*dst++ = '"';
|
*dst++ = '"';
|
||||||
while (n-- > 0)
|
while (n-- > 0 && dst <= res + size - 10)
|
||||||
{
|
{
|
||||||
WCHAR c = *str++;
|
WCHAR c = *str++;
|
||||||
switch (c)
|
switch (c)
|
||||||
@ -350,22 +365,12 @@ static const char *default_dbgstr_wn( const WCHAR *str, int n )
|
|||||||
*dst++ = '.';
|
*dst++ = '.';
|
||||||
*dst++ = '.';
|
*dst++ = '.';
|
||||||
}
|
}
|
||||||
*dst = 0;
|
*dst++ = 0;
|
||||||
|
funcs.release_temp_buffer( res, dst - res );
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* default implementation of wine_dbg_vsprintf */
|
|
||||||
static const char *default_dbg_vsprintf( const char *format, va_list args )
|
|
||||||
{
|
|
||||||
static const int max_size = 200;
|
|
||||||
|
|
||||||
char *res = get_tmp_space( max_size );
|
|
||||||
int len = vsnprintf( res, max_size, format, args );
|
|
||||||
if (len == -1 || len >= max_size) res[max_size-1] = 0;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* default implementation of wine_dbg_vprintf */
|
/* default implementation of wine_dbg_vprintf */
|
||||||
static int default_dbg_vprintf( const char *format, va_list args )
|
static int default_dbg_vprintf( const char *format, va_list args )
|
||||||
{
|
{
|
||||||
@ -408,16 +413,19 @@ const char *wine_dbgstr_w( const WCHAR *s )
|
|||||||
return funcs.dbgstr_wn( s, -1 );
|
return funcs.dbgstr_wn( s, -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
void __wine_dbg_set_functions( const struct __wine_debug_functions *new_funcs, size_t size )
|
void __wine_dbg_set_functions( const struct __wine_debug_functions *new_funcs,
|
||||||
|
struct __wine_debug_functions *old_funcs, size_t size )
|
||||||
{
|
{
|
||||||
memcpy( &funcs, new_funcs, min(sizeof(funcs),size) );
|
if (old_funcs) memcpy( old_funcs, &funcs, min(sizeof(funcs),size) );
|
||||||
|
if (new_funcs) memcpy( &funcs, new_funcs, min(sizeof(funcs),size) );
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct __wine_debug_functions funcs =
|
static struct __wine_debug_functions funcs =
|
||||||
{
|
{
|
||||||
|
get_temp_buffer,
|
||||||
|
release_temp_buffer,
|
||||||
default_dbgstr_an,
|
default_dbgstr_an,
|
||||||
default_dbgstr_wn,
|
default_dbgstr_wn,
|
||||||
default_dbg_vsprintf,
|
|
||||||
default_dbg_vprintf,
|
default_dbg_vprintf,
|
||||||
default_dbg_vlog
|
default_dbg_vlog
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user