mirror of
https://github.com/SDL-Hercules-390/hyperion.git
synced 2026-07-26 02:29:51 +02:00
3d239d3db5
* 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.
231 lines
9.6 KiB
C
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
|
|
|
|
/*----------------------------------------------------------------------------*/
|