Commit a443761b authored by Alexandre Julliard's avatar Alexandre Julliard

Export the temp buffer functionality in the debug functions interface

to allow sharing more code between libwine and ntdll.
parent 2f967872
......@@ -42,6 +42,8 @@
WINE_DECLARE_DEBUG_CHANNEL(tid);
static struct __wine_debug_functions default_funcs;
/* ---------------------------------------------------------------------- */
/* filter for page-fault exceptions */
......@@ -59,7 +61,7 @@ static inline struct debug_info *get_info(void)
}
/* 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();
char *res = info->str_pos;
......@@ -70,101 +72,10 @@ static void *gimme1(int n)
}
/* 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();
info->str_pos = ptr;
}
/* 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;
info->str_pos = ptr + size;
}
/***********************************************************************
......@@ -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 )
{
char *res, *old_pos;
const char *res;
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 */
old_pos = info->str_pos;
char *old_pos = info->str_pos;
__TRY
{
res = put_string_a( src, n );
res = default_funcs.dbgstr_an( src, n );
}
__EXCEPT(page_fault)
{
release( old_pos );
release_temp_buffer( old_pos, 0 );
return "(invalid)";
}
__ENDTRY
......@@ -202,26 +106,18 @@ static const char *NTDLL_dbgstr_an( const char *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();
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 */
old_pos = info->str_pos;
char *old_pos = info->str_pos;
__TRY
{
res = put_string_w( src, n );
res = default_funcs.dbgstr_wn( src, n );
}
__EXCEPT(page_fault)
{
release( old_pos );
release_temp_buffer( old_pos, 0 );
return "(invalid)";
}
__ENDTRY
......@@ -229,20 +125,6 @@ static const char *NTDLL_dbgstr_wn( const WCHAR *src, int n )
}
/***********************************************************************
* 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
*/
static int NTDLL_dbg_vprintf( const char *format, va_list args )
......@@ -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 =
{
get_temp_buffer,
release_temp_buffer,
NTDLL_dbgstr_an,
NTDLL_dbgstr_wn,
NTDLL_dbg_vsprintf,
NTDLL_dbg_vprintf,
NTDLL_dbg_vlog
};
......@@ -319,6 +202,6 @@ void debug_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 */
}
......@@ -137,15 +137,17 @@ struct __wine_debug_channel
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_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_vlog)( enum __wine_debug_class cls, struct __wine_debug_channel *channel,
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
......
......@@ -198,7 +198,7 @@ int wine_dbg_parse_options( const char *str )
return errors;
}
/* varargs wrapper for __wine_dbg_vprintf */
/* varargs wrapper for funcs.dbg_vprintf */
int wine_dbg_printf( const char *format, ... )
{
int ret;
......@@ -210,21 +210,25 @@ int wine_dbg_printf( const char *format, ... )
return ret;
}
/* varargs wrapper for __wine_dbg_vsprintf */
/* printf with temp buffer allocation */
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_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);
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,
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 */
/* 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 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 */
static const char *default_dbgstr_an( const char *str, int n )
{
static const char hex[16] = "0123456789abcdef";
char *dst, *res;
size_t size;
if (!HIWORD(str))
if (!((ULONG_PTR)str >> 16))
{
if (!str) return "(null)";
res = get_tmp_space( 6 );
res = funcs.get_temp_buffer( 6 );
sprintf( res, "#%04x", LOWORD(str) );
return res;
}
if (n == -1) n = strlen(str);
if (n < 0) n = 0;
else if (n > 200) n = 200;
dst = res = get_tmp_space( n * 4 + 6 );
size = 10 + min( 300, n * 4 );
dst = res = funcs.get_temp_buffer( size );
*dst++ = '"';
while (n-- > 0)
while (n-- > 0 && dst <= res + size - 9)
{
unsigned char c = *str++;
switch (c)
......@@ -286,9 +299,9 @@ static const char *default_dbgstr_an( const char *str, int n )
else
{
*dst++ = '\\';
*dst++ = '0' + ((c >> 6) & 7);
*dst++ = '0' + ((c >> 3) & 7);
*dst++ = '0' + ((c >> 0) & 7);
*dst++ = 'x';
*dst++ = hex[(c >> 4) & 0x0f];
*dst++ = hex[c & 0x0f];
}
}
}
......@@ -299,7 +312,8 @@ static const char *default_dbgstr_an( const char *str, int n )
*dst++ = '.';
*dst++ = '.';
}
*dst = 0;
*dst++ = 0;
funcs.release_temp_buffer( res, dst - 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 )
{
char *dst, *res;
size_t size;
if (!HIWORD(str))
if (!((ULONG_PTR)str >> 16))
{
if (!str) return "(null)";
res = get_tmp_space( 6 );
res = funcs.get_temp_buffer( 6 );
sprintf( res, "#%04x", LOWORD(str) );
return res;
}
if (n == -1) n = strlenW(str);
if (n < 0) n = 0;
else if (n > 200) n = 200;
dst = res = get_tmp_space( n * 5 + 7 );
size = 12 + min( 300, n * 5 );
dst = res = funcs.get_temp_buffer( n * 5 + 7 );
*dst++ = 'L';
*dst++ = '"';
while (n-- > 0)
while (n-- > 0 && dst <= res + size - 10)
{
WCHAR c = *str++;
switch (c)
......@@ -350,22 +365,12 @@ static const char *default_dbgstr_wn( const WCHAR *str, int n )
*dst++ = '.';
*dst++ = '.';
}
*dst = 0;
*dst++ = 0;
funcs.release_temp_buffer( res, dst - 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 */
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 );
}
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 =
{
get_temp_buffer,
release_temp_buffer,
default_dbgstr_an,
default_dbgstr_wn,
default_dbg_vsprintf,
default_dbg_vprintf,
default_dbg_vlog
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment