2009-12-29 14:34 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
* harbour/include/hbapi.h
* harbour/src/common/hbprintf.c
+ added new function 'int hb_printf_params( const char * format )' which
returns number of parameters necessary for format string
* harbour/src/common/hbtrace.c
* added protection against recursive calls when number of parameters
used by HB_TRACE message us bigger then 16 and fm.c module was compiled
with HB_TR_DEBUG macro
% use the same number of characters for unicode and byte string buffers
% use common memory area (union) for unicode and byte messages to reduce
C stack usage
Please test these modifications in real MS-Windows systems.
This commit is contained in:
@@ -17,6 +17,21 @@
|
||||
past entries belonging to author(s): Viktor Szakats.
|
||||
*/
|
||||
|
||||
2009-12-29 14:34 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
|
||||
* harbour/include/hbapi.h
|
||||
* harbour/src/common/hbprintf.c
|
||||
+ added new function 'int hb_printf_params( const char * format )' which
|
||||
returns number of parameters necessary for format string
|
||||
|
||||
* harbour/src/common/hbtrace.c
|
||||
* added protection against recursive calls when number of parameters
|
||||
used by HB_TRACE message us bigger then 16 and fm.c module was compiled
|
||||
with HB_TR_DEBUG macro
|
||||
% use the same number of characters for unicode and byte string buffers
|
||||
% use common memory area (union) for unicode and byte messages to reduce
|
||||
C stack usage
|
||||
Please test these modifications in real MS-Windows systems.
|
||||
|
||||
2009-12-29 00:41 UTC-0800 Pritpal Bedi (pritpal@vouchcac.com)
|
||||
* contrib/hbqt/qtgui/QTextCursor.cpp
|
||||
* contrib/hbqt/qtgui/TQTextCursor.prg
|
||||
|
||||
@@ -935,6 +935,7 @@ extern HB_EXPORT BOOL hb_strToNum( const char * szNum, HB_LONG * plVal, dou
|
||||
extern HB_EXPORT BOOL hb_strnToNum( const char * szNum, ULONG ulLen, HB_LONG * plVal, double * pdVal ); /* converts string to number, returns HB_TRUE if results is double */
|
||||
extern HB_EXPORT int hb_snprintf( char * buffer, size_t bufsize, const char * format, ... ) HB_PRINTF_FORMAT( 3, 4 ); /* snprintf() equivalent */
|
||||
extern HB_EXPORT int hb_vsnprintf( char * buffer, size_t bufsize, const char * format, va_list ap ); /* vsnprintf() equivalent */
|
||||
extern HB_EXPORT int hb_printf_params( const char * format );
|
||||
|
||||
extern HB_EXPORT BOOL hb_strMatchFile( const char * pszString, const char * szPattern ); /* compare two strings using platform dependent rules for file matching */
|
||||
extern HB_EXPORT BOOL hb_strMatchRegExp( const char * szString, const char * szPattern ); /* compare two strings using a regular expression pattern */
|
||||
|
||||
@@ -728,6 +728,187 @@ static size_t put_str( char *buffer, size_t bufsize, size_t size,
|
||||
return size;
|
||||
}
|
||||
|
||||
int hb_printf_params( const char * format )
|
||||
{
|
||||
int iParam = 0, iMax = 0;
|
||||
char c;
|
||||
|
||||
do
|
||||
{
|
||||
c = *format++;
|
||||
if( c == '%' )
|
||||
{
|
||||
const char * pattern = format;
|
||||
int value, param = 0;
|
||||
|
||||
c = *format++;
|
||||
if( c != 0 && c != '%' )
|
||||
{
|
||||
/* parameter position */
|
||||
if( c >= '0' && c <= '9' )
|
||||
{
|
||||
c = get_decimal( c, &format, ¶m );
|
||||
if( c != '$' )
|
||||
format = pattern;
|
||||
c = *format++;
|
||||
}
|
||||
|
||||
/* flags */
|
||||
value = 0;
|
||||
while( !value ) switch( c )
|
||||
{
|
||||
case '#':
|
||||
case '0':
|
||||
case '-':
|
||||
case ' ':
|
||||
case '+':
|
||||
#ifdef _SUSV2_COMPAT_
|
||||
case '\'': /* group with locale thousands' grouping characters */
|
||||
#endif
|
||||
c = *format++;
|
||||
break;
|
||||
default:
|
||||
value = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* field width */
|
||||
if( c == '*' )
|
||||
{
|
||||
c = *format++;
|
||||
if( c >= '0' && c <= '9' )
|
||||
{
|
||||
c = get_decimal( c, &format, &value );
|
||||
if( c == '$' )
|
||||
{
|
||||
if( value > iMax )
|
||||
iMax = value;
|
||||
c = *format++;
|
||||
}
|
||||
/* else error, wrong format */
|
||||
}
|
||||
else
|
||||
++iParam;
|
||||
}
|
||||
else if( c >= '0' && c <= '9' )
|
||||
c = get_decimal( c, &format, &value );
|
||||
|
||||
/* precision */
|
||||
if( c == '.' )
|
||||
{
|
||||
c = *format++;
|
||||
if( c == '*' )
|
||||
{
|
||||
c = *format++;
|
||||
if( c >= '0' && c <= '9' )
|
||||
{
|
||||
c = get_decimal( c, &format, &value );
|
||||
if( c == '$' )
|
||||
{
|
||||
if( value > iMax )
|
||||
iMax = value;
|
||||
c = *format++;
|
||||
}
|
||||
/* else error, wrong format */
|
||||
}
|
||||
else
|
||||
++iParam;
|
||||
}
|
||||
else if( c >= '0' && c <= '9' )
|
||||
c = get_decimal( c, &format, &value );
|
||||
}
|
||||
|
||||
/* length modifier */
|
||||
switch( c )
|
||||
{
|
||||
case 'h':
|
||||
c = *format++;
|
||||
if( c == 'h' )
|
||||
c = *format++;
|
||||
break;
|
||||
case 'l':
|
||||
c = *format++;
|
||||
if( c == 'l' )
|
||||
c = *format++;
|
||||
break;
|
||||
case 'L':
|
||||
c = *format++;
|
||||
break;
|
||||
case 'j':
|
||||
c = *format++;
|
||||
break;
|
||||
case 'z':
|
||||
c = *format++;
|
||||
break;
|
||||
case 't':
|
||||
c = *format++;
|
||||
break;
|
||||
case 'I': /* MS-Windows extension */
|
||||
if( format[ 0 ] == '6' && format[ 1 ] == '4' )
|
||||
{
|
||||
format += 2;
|
||||
c = *format++;
|
||||
break;
|
||||
}
|
||||
else if( format[ 0 ] == '1' && format[ 1 ] == '6' )
|
||||
{
|
||||
format += 2;
|
||||
c = *format++;
|
||||
break;
|
||||
}
|
||||
else if( format[ 0 ] == '3' && format[ 1 ] == '2' )
|
||||
{
|
||||
format += 2;
|
||||
c = *format++;
|
||||
}
|
||||
/* no break; */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* conversion specifier */
|
||||
switch( c )
|
||||
{
|
||||
#ifndef __NO_DOUBLE__
|
||||
case 'a':
|
||||
case 'A':
|
||||
case 'e':
|
||||
case 'E':
|
||||
case 'g':
|
||||
case 'G':
|
||||
case 'f': /* double decimal notation */
|
||||
case 'F': /* double decimal notation */
|
||||
#endif
|
||||
case 'd':
|
||||
case 'i': /* signed int decimal conversion */
|
||||
case 'o': /* unsigned int octal conversion */
|
||||
case 'u': /* unsigned int decimal conversion */
|
||||
case 'x': /* unsigned int hexadecimal conversion */
|
||||
case 'X': /* unsigned int hexadecimal conversion */
|
||||
case 'p': /* void * pointer */
|
||||
case 'c': /* signed int casted to unsigned char */
|
||||
case 's': /* const char * */
|
||||
case 'n': /* store current result size in int * arg */
|
||||
if( param == 0 )
|
||||
++iParam;
|
||||
else if( param > iMax )
|
||||
iMax = param;
|
||||
break;
|
||||
case '%': /* store % consuming arguments % */
|
||||
break;
|
||||
default: /* error, wrong format, store pattern */
|
||||
format = pattern;
|
||||
c = '%';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while( c );
|
||||
|
||||
return iParam > iMax ? iParam : iMax;
|
||||
}
|
||||
|
||||
int hb_vsnprintf( char * buffer, size_t bufsize, const char * format, va_list ap )
|
||||
{
|
||||
va_list args;
|
||||
@@ -779,15 +960,10 @@ int hb_vsnprintf( char * buffer, size_t bufsize, const char * format, va_list ap
|
||||
{
|
||||
c = get_decimal( c, &format, &value );
|
||||
if( c == '$' )
|
||||
{
|
||||
param = value;
|
||||
c = *format++;
|
||||
}
|
||||
else
|
||||
{
|
||||
format = pattern;
|
||||
c = *format++;
|
||||
}
|
||||
c = *format++;
|
||||
}
|
||||
|
||||
/* flags */
|
||||
@@ -934,7 +1110,6 @@ int hb_vsnprintf( char * buffer, size_t bufsize, const char * format, va_list ap
|
||||
}
|
||||
|
||||
/* conversion specifier */
|
||||
|
||||
switch( c )
|
||||
{
|
||||
#ifndef __NO_DOUBLE__
|
||||
|
||||
@@ -223,30 +223,33 @@ static void hb_tracelog_( int level, const char * file, int line, const char * p
|
||||
|
||||
if( s_winout )
|
||||
{
|
||||
char buffer1[ 1024 ];
|
||||
char buffer2[ 1024 ];
|
||||
char message[ 1024 ];
|
||||
union
|
||||
{
|
||||
char psz[ 1024 ];
|
||||
TCHAR lp[ 1024 ];
|
||||
} buf;
|
||||
|
||||
/* TOFIX: This might invoke recursive call to tracee engine when
|
||||
there is more than 16 format strings. */
|
||||
hb_vsnprintf( buffer1, sizeof( buffer1 ), fmt, ap );
|
||||
|
||||
/* We add \r\n at the end of the buffer to make WinDbg display look readable. */
|
||||
if( proc )
|
||||
hb_snprintf( buffer2, sizeof( buffer2 ), "%s:%d:%s() %s %s\n",
|
||||
file, line, proc, pszLevel, buffer1 );
|
||||
/* NOTE: This is protection against recursive call to trace engine when
|
||||
there is more than 16 parameters in format string */
|
||||
if( hb_xtraced() && hb_printf_params( fmt ) > 16 )
|
||||
hb_snprintf( message, sizeof( message ), "more then 16 parameters in message '%s'", fmt );
|
||||
else
|
||||
hb_snprintf( buffer2, sizeof( buffer2 ), "%s:%d: %s %s\n",
|
||||
file, line, pszLevel, buffer1 );
|
||||
hb_vsnprintf( message, sizeof( message ), fmt, ap );
|
||||
|
||||
/* We add \n at the end of the buffer to make WinDbg display look readable. */
|
||||
if( proc )
|
||||
hb_snprintf( buf.psz, sizeof( buf.psz ), "%s:%d:%s() %s %s\n",
|
||||
file, line, proc, pszLevel, message );
|
||||
else
|
||||
hb_snprintf( buf.psz, sizeof( buf.psz ), "%s:%d: %s %s\n",
|
||||
file, line, pszLevel, message );
|
||||
|
||||
#if defined( UNICODE )
|
||||
{
|
||||
TCHAR lpOutputString[ 2048 ];
|
||||
MultiByteToWideChar( CP_ACP, 0, buffer2, -1, lpOutputString, HB_SIZEOFARRAY( lpOutputString ) );
|
||||
OutputDebugString( lpOutputString );
|
||||
}
|
||||
#else
|
||||
OutputDebugString( buffer2 );
|
||||
memcpy( message, buf.psz, sizeof( message ) );
|
||||
MultiByteToWideChar( CP_ACP, 0, message, -1, buf.lp, HB_SIZEOFARRAY( buf.lp ) );
|
||||
#endif
|
||||
OutputDebugString( buf.lp );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user