Files
gottfriedleibniz 3d239d3db5 cleanup va_start/va_end and introduce vasprintf (#826)
* refactor: cleanup va_start/va_end

- Missing va_end statements;
- Incorrect va_copy ordering in BFR_VSNPRINTF;
- Sanitize snprintf results or ensure buffer is initially \0'd.

* refactor: introduce vasprintf

Replace dynamic format string allocation (i.e., incrementing a buffer by
a fixed amount until vsnprintf returns success) with vasprintf.
Polyfill'ing for builds that do not include the GNU extension.
2026-04-30 12:44:49 -07:00

231 lines
9.6 KiB
C

/* DBGTRACE.H (C) Copyright "Fish" (David B. Trout), 2011 */
/* TRACE/ASSERT/VERIFY debugging macros */
/* */
/* Released under "The Q Public License Version 1" */
/* (http://www.hercules-390.org/herclic.html) as modifications to */
/* Hercules. */
/*-------------------------------------------------------------------*/
/* */
/* This header implements the TRACE, ASSERT and VERIFY debugging */
/* macros. Use TRACE statements during and after developing your */
/* code to display helpful debugging messages. Use ASSERT to test */
/* for a condition which should always be true. Use VERIFY whenever */
/* the condition must always be evaluated even for non-debug builds */
/* such as when the VERIFY conditional itself uses a function call */
/* which must always be called. */
/* */
/* You should #define ENABLE_TRACING_STMTS to either 0 or 1 before */
/* #including this header. If left undefined then the _DEBUG switch */
/* controls if they're enabled or not (default is yes for _DEBUG). */
/* This allows you to enable/disable TRACING separate from _DEBUG */
/* on an individual module by module basis if needed or desired. */
/* */
/*-------------------------------------------------------------------*/
/* */
/* PROGRAMMING NOTE */
/* */
/* This header PURPOSELY DOES NOT prevent itself from being included */
/* multiple times. This is so default handling can be overridden by */
/* simply #defining 'ENABLE_TRACING_STMTS' and then #including this */
/* header again to activate the new settings. */
/* */
/*-------------------------------------------------------------------*/
#undef ISSUE_UNEXPECTED_MSG
#define ISSUE_UNEXPECTED_MSG() \
do \
{ \
const char* file = __FILE__; \
const char* func = __FUNCTION__; \
int line = __LINE__; \
\
const char* p = strrchr( file, '\\' ); /* Windows */ \
if (!p) p = strrchr( file, '/' ); /* non-Windows */ \
if (p) ++p; \
if (p) file = p; \
\
/* HHC02218 "** UNEXPECTED! ** file \"%s\", line %d, function \"%s\"" */ \
\
fprintf( stdout, "HHC02218E ** UNEXPECTED! ** file \"%s\", line %d, function \"%s\"\n", \
file, line, func ); \
} \
while(0)
#undef BREAK_INTO_DEBUGGER
#if defined( _MSVC_ )
#define BREAK_INTO_DEBUGGER() \
\
do \
{ \
ISSUE_UNEXPECTED_MSG(); \
if (IsDebuggerPresent()) \
__debugbreak(); \
} \
while(0)
#else
#define BREAK_INTO_DEBUGGER() \
\
do \
{ \
ISSUE_UNEXPECTED_MSG(); \
if (sysblk.is_debugger_present) \
raise( SIGTRAP ); \
} \
while(0)
#endif
/*-------------------------------------------------------------------*/
/* Implement debugging macros and function -- IF REQUESTED! */
/*-------------------------------------------------------------------*/
#undef _ENABLE_TRACING_STMTS_IMPL
#if defined( ENABLE_TRACING_STMTS )
#if ENABLE_TRACING_STMTS
#define _ENABLE_TRACING_STMTS_IMPL 1
#else
#define _ENABLE_TRACING_STMTS_IMPL 0
#endif
#else
#if defined(DEBUG) || defined(_DEBUG)
#define _ENABLE_TRACING_STMTS_IMPL 1
#else
#define _ENABLE_TRACING_STMTS_IMPL 0
#endif
#endif
/*-------------------------------------------------------------------*/
/* Implement TRACE, ASSERT and VERIFY macros */
/*-------------------------------------------------------------------*/
#undef VERIFY
#undef ASSERT
#undef TRACE
// VERIFY conditions are ALWAYS evaluated
// ASSERT conditions MIGHT NOT be evaluated
// TRACE just issues a message if debugging
#if !_ENABLE_TRACING_STMTS_IMPL
// Debugging NOT requested: define "do nothing" macros
#define VERIFY(a) ((void)(a)) // (just call the function)
#define ASSERT(a) // (do nothing)
#define TRACE(...) // (do nothing)
#else // implement TRACE, ASSERT and VERIFY macros
#if defined( _MSVC_ ) // Windows...
#define TRACE(...) \
do \
{ \
/* Write to Hercules log */ \
logmsg(__VA_ARGS__); \
\
/* And to debugger pane too */ \
if (IsDebuggerPresent()) \
DebuggerTrace(__VA_ARGS__); \
} \
while (0)
#define ASSERT(a) \
do \
{ \
if (!(a)) \
{ \
/* Programming Note: message formatted specifically for Visual Studio F4-key "next message" compatibility */ \
TRACE("%s(%d) : warning HHC90999W : *** Assertion Failed! *** function: %s\n",__FILE__,__LINE__,__FUNCTION__); \
BREAK_INTO_DEBUGGER(); \
} \
} \
while(0)
#else // Linux...
#define TRACE(...) \
do \
{ \
/* Write to Hercules log */ \
logmsg(__VA_ARGS__); \
} \
while (0)
#define ASSERT(a) \
do \
{ \
if (!(a)) \
{ \
TRACE("HHC91999W *** Assertion Failed! *** %s(%d)\n",__FILE__,__LINE__); \
BREAK_INTO_DEBUGGER(); \
} \
} \
while(0)
#endif // _MSVC_ or Linux
// Both MSVC *and* Linux...
#define VERIFY ASSERT
#endif // !_ENABLE_TRACING_STMTS_IMPL */
/*-------------------------------------------------------------------*/
/* DebuggerTrace: format string and write to debugger pane */
/*-------------------------------------------------------------------*/
#if defined( _MSVC_ ) && _ENABLE_TRACING_STMTS_IMPL
// (static function: only need to implement this once)
#ifndef _ENABLE_TRACING_STMTS_DEBUGGERTRACE_DEFINED
#define _ENABLE_TRACING_STMTS_DEBUGGERTRACE_DEFINED
static inline void DebuggerTrace( char* fmt, ...)
{
va_list vl;
int expectedLen, actualLen;
size_t bufCount;
char *buf = NULL;
va_start( vl, fmt );
expectedLen = _vscprintf( fmt , vl );
va_end( vl );
if (expectedLen < 0)
{
DebuggerTrace_Fail:
BREAK_INTO_DEBUGGER();
if (buf != NULL)
free(buf);
return;
}
bufCount = ((size_t)expectedLen) + 1;
if ((buf = (char *)malloc( bufCount )) == NULL)
goto DebuggerTrace_Fail;
va_start( vl, fmt );
actualLen = _vsnprintf_s( buf, bufCount, _TRUNCATE, fmt, vl );
va_end( vl );
if (actualLen < 0)
goto DebuggerTrace_Fail;
/* Write to debugger pane */
OutputDebugStringA( buf );
free( buf );
}
#endif // _ENABLE_TRACING_STMTS_DEBUGGERTRACE_DEFINED
#endif // defined( _MSVC_ ) && _ENABLE_TRACING_STMTS_IMPL
/*----------------------------------------------------------------------------*/