2018-03-12 14:31:22 -04:00
|
|
|
/***********************************************************************************************************************************
|
|
|
|
Debug Routines
|
|
|
|
***********************************************************************************************************************************/
|
|
|
|
#ifndef COMMON_DEBUG_H
|
|
|
|
#define COMMON_DEBUG_H
|
|
|
|
|
2018-05-18 11:57:32 -04:00
|
|
|
#include "common/stackTrace.h"
|
|
|
|
#include "common/type/convert.h"
|
|
|
|
|
2018-03-12 14:31:22 -04:00
|
|
|
/***********************************************************************************************************************************
|
|
|
|
NDEBUG indicates to C library routines that debugging is off -- set a more readable flag to use when debugging is on
|
|
|
|
***********************************************************************************************************************************/
|
|
|
|
#ifndef NDEBUG
|
|
|
|
#define DEBUG
|
|
|
|
#endif
|
|
|
|
|
2018-03-12 17:15:14 -04:00
|
|
|
/***********************************************************************************************************************************
|
|
|
|
Extern variables that are needed for unit testing
|
|
|
|
***********************************************************************************************************************************/
|
|
|
|
#ifdef DEBUG_UNIT
|
|
|
|
#define DEBUG_UNIT_EXTERN
|
|
|
|
#else
|
|
|
|
#define DEBUG_UNIT_EXTERN \
|
|
|
|
static
|
|
|
|
#endif
|
|
|
|
|
2018-05-18 11:57:32 -04:00
|
|
|
/***********************************************************************************************************************************
|
|
|
|
Base function debugging macros
|
|
|
|
|
|
|
|
In debug mode parameters will always be recorded in the stack trace while in production mode they will only be recorded when the log
|
|
|
|
level is set to debug or trace.
|
|
|
|
***********************************************************************************************************************************/
|
|
|
|
#define FUNCTION_DEBUG_LEVEL() \
|
|
|
|
FUNCTION_DEBUG_logLevel
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
#define FUNCTION_DEBUG_BEGIN_BASE(logLevel) \
|
|
|
|
LogLevel FUNCTION_DEBUG_LEVEL() = STACK_TRACE_PUSH(logLevel); \
|
|
|
|
\
|
|
|
|
{ \
|
|
|
|
stackTraceParamLog();
|
|
|
|
|
|
|
|
#define FUNCTION_DEBUG_END_BASE() \
|
|
|
|
LOG_WILL(FUNCTION_DEBUG_LEVEL(), 0, "(%s)", stackTraceParam()); \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define FUNCTION_DEBUG_PARAM_BASE_BEGIN() \
|
|
|
|
stackTraceTestStop() \
|
|
|
|
|
|
|
|
#define FUNCTION_DEBUG_PARAM_BASE_END() \
|
|
|
|
stackTraceTestStart()
|
|
|
|
#else
|
|
|
|
#define FUNCTION_DEBUG_BEGIN_BASE(logLevel) \
|
|
|
|
LogLevel FUNCTION_DEBUG_LEVEL() = STACK_TRACE_PUSH(logLevel); \
|
|
|
|
\
|
|
|
|
if (logWill(FUNCTION_DEBUG_LEVEL())) \
|
|
|
|
{ \
|
|
|
|
stackTraceParamLog()
|
|
|
|
|
|
|
|
#define FUNCTION_DEBUG_END_BASE() \
|
|
|
|
LOG(FUNCTION_DEBUG_LEVEL(), 0, "(%s)", stackTraceParam()); \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define FUNCTION_DEBUG_PARAM_BASE_BEGIN()
|
|
|
|
#define FUNCTION_DEBUG_PARAM_BASE_END()
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/***********************************************************************************************************************************
|
|
|
|
General purpose function debugging macros
|
|
|
|
|
|
|
|
FUNCTION_DEBUG_VOID() is provided as a shortcut for functions that have no parameters.
|
|
|
|
***********************************************************************************************************************************/
|
|
|
|
#define FUNCTION_DEBUG_BEGIN(logLevel) \
|
|
|
|
FUNCTION_DEBUG_BEGIN_BASE(logLevel)
|
|
|
|
|
|
|
|
#define FUNCTION_DEBUG_END() \
|
|
|
|
FUNCTION_DEBUG_END_BASE()
|
|
|
|
|
|
|
|
#define FUNCTION_DEBUG_VOID(logLevel) \
|
|
|
|
FUNCTION_DEBUG_BEGIN_BASE(logLevel); \
|
|
|
|
FUNCTION_DEBUG_END_BASE()
|
|
|
|
|
|
|
|
#define FUNCTION_DEBUG_PARAM(typeMacroPrefix, param) \
|
|
|
|
FUNCTION_DEBUG_PARAM_BASE_BEGIN(); \
|
|
|
|
stackTraceParamAdd(FUNCTION_DEBUG_##typeMacroPrefix##_FORMAT(param, stackTraceParamBuffer(#param), STACK_TRACE_PARAM_MAX)); \
|
|
|
|
FUNCTION_DEBUG_PARAM_BASE_END()
|
|
|
|
|
|
|
|
#define FUNCTION_DEBUG_PARAM_PTR(typeName, param) \
|
|
|
|
FUNCTION_DEBUG_PARAM_BASE_BEGIN(); \
|
|
|
|
stackTraceParamAdd(ptrToLog(param, typeName, stackTraceParamBuffer(#param), STACK_TRACE_PARAM_MAX )); \
|
|
|
|
FUNCTION_DEBUG_PARAM_BASE_END()
|
|
|
|
|
|
|
|
/***********************************************************************************************************************************
|
|
|
|
Functions and macros to render various data types
|
|
|
|
***********************************************************************************************************************************/
|
|
|
|
size_t objToLog(const void *object, const char *objectName, char *buffer, size_t bufferSize);
|
|
|
|
size_t ptrToLog(const void *pointer, const char *pointerName, char *buffer, size_t bufferSize);
|
|
|
|
size_t strzToLog(const char *string, char *buffer, size_t bufferSize);
|
|
|
|
|
|
|
|
#define FUNCTION_DEBUG_BOOL_TYPE \
|
|
|
|
bool
|
|
|
|
#define FUNCTION_DEBUG_BOOL_FORMAT(value, buffer, bufferSize) \
|
|
|
|
cvtBoolToZ(value, buffer, bufferSize)
|
|
|
|
|
|
|
|
#define FUNCTION_DEBUG_BOOLP_TYPE \
|
|
|
|
bool *
|
|
|
|
#define FUNCTION_DEBUG_BOOLP_FORMAT(value, buffer, bufferSize) \
|
|
|
|
ptrToLog(value, "bool *", buffer, bufferSize)
|
|
|
|
|
2018-08-14 16:18:17 -04:00
|
|
|
#define FUNCTION_DEBUG_CHAR_TYPE \
|
|
|
|
char
|
|
|
|
#define FUNCTION_DEBUG_CHAR_FORMAT(value, buffer, bufferSize) \
|
|
|
|
cvtCharToZ(value, buffer, bufferSize)
|
|
|
|
|
2018-05-18 11:57:32 -04:00
|
|
|
#define FUNCTION_DEBUG_CHARP_TYPE \
|
|
|
|
char *
|
|
|
|
#define FUNCTION_DEBUG_CHARP_FORMAT(value, buffer, bufferSize) \
|
|
|
|
ptrToLog(value, "char *", buffer, bufferSize)
|
|
|
|
|
|
|
|
#define FUNCTION_DEBUG_CONST_CHARPP_TYPE \
|
|
|
|
const char **
|
|
|
|
#define FUNCTION_DEBUG_CONST_CHARPP_FORMAT(value, buffer, bufferSize) \
|
|
|
|
ptrToLog(value, "char **", buffer, bufferSize)
|
|
|
|
|
|
|
|
#define FUNCTION_DEBUG_CHARPY_TYPE \
|
|
|
|
char *[]
|
|
|
|
#define FUNCTION_DEBUG_CHARPY_FORMAT(value, buffer, bufferSize) \
|
|
|
|
ptrToLog(value, "char *[]", buffer, bufferSize)
|
|
|
|
|
|
|
|
#define FUNCTION_DEBUG_DOUBLE_TYPE \
|
|
|
|
double
|
|
|
|
#define FUNCTION_DEBUG_DOUBLE_FORMAT(value, buffer, bufferSize) \
|
|
|
|
cvtDoubleToZ(value, buffer, bufferSize)
|
|
|
|
|
|
|
|
#define FUNCTION_DEBUG_DOUBLEP_TYPE \
|
|
|
|
double *
|
|
|
|
#define FUNCTION_DEBUG_DOUBLEP_FORMAT(value, buffer, bufferSize) \
|
|
|
|
ptrToLog(value, "double *", buffer, bufferSize)
|
|
|
|
|
|
|
|
#define FUNCTION_DEBUG_INT_TYPE \
|
|
|
|
int
|
|
|
|
#define FUNCTION_DEBUG_INT_FORMAT(value, buffer, bufferSize) \
|
|
|
|
cvtIntToZ(value, buffer, bufferSize)
|
|
|
|
|
|
|
|
#define FUNCTION_DEBUG_INTP_TYPE \
|
|
|
|
int *
|
|
|
|
#define FUNCTION_DEBUG_INTP_FORMAT(value, buffer, bufferSize) \
|
|
|
|
ptrToLog(value, "int *", buffer, bufferSize)
|
|
|
|
|
|
|
|
#define FUNCTION_DEBUG_INT64_TYPE \
|
|
|
|
int64_t
|
|
|
|
#define FUNCTION_DEBUG_INT64_FORMAT(value, buffer, bufferSize) \
|
|
|
|
cvtInt64ToZ(value, buffer, bufferSize)
|
|
|
|
|
|
|
|
#define FUNCTION_DEBUG_ENUM_TYPE \
|
|
|
|
unsigned int
|
|
|
|
#define FUNCTION_DEBUG_ENUM_FORMAT(value, buffer, bufferSize) \
|
|
|
|
FUNCTION_DEBUG_UINT_FORMAT(value, buffer, bufferSize)
|
|
|
|
|
|
|
|
#define FUNCTION_DEBUG_FUNCTIONP_FORMAT(value, buffer, bufferSize) \
|
|
|
|
ptrToLog(value == NULL ? NULL : (void *)1, "function *", buffer, bufferSize)
|
|
|
|
|
|
|
|
#define FUNCTION_DEBUG_MODE_TYPE \
|
|
|
|
mode_t
|
|
|
|
#define FUNCTION_DEBUG_MODE_FORMAT(value, buffer, bufferSize) \
|
|
|
|
cvtModeToZ(value, buffer, bufferSize)
|
|
|
|
|
2018-11-08 08:37:57 -05:00
|
|
|
#define FUNCTION_DEBUG_TIMEMSEC_TYPE \
|
|
|
|
TimeMSec
|
|
|
|
#define FUNCTION_DEBUG_TIMEMSEC_FORMAT(value, buffer, bufferSize) \
|
|
|
|
cvtUInt64ToZ(value, buffer, bufferSize)
|
|
|
|
|
2018-05-18 11:57:32 -04:00
|
|
|
#define FUNCTION_DEBUG_UCHARP_TYPE \
|
|
|
|
unsigned char *
|
|
|
|
#define FUNCTION_DEBUG_UCHARP_FORMAT(value, buffer, bufferSize) \
|
|
|
|
ptrToLog(value, "unsigned char *", buffer, bufferSize)
|
|
|
|
|
|
|
|
#define FUNCTION_DEBUG_SIZE_TYPE \
|
|
|
|
size_t
|
|
|
|
#define FUNCTION_DEBUG_SIZE_FORMAT(value, buffer, bufferSize) \
|
|
|
|
cvtSizeToZ(value, buffer, bufferSize)
|
|
|
|
|
|
|
|
#define FUNCTION_DEBUG_UINT_TYPE \
|
|
|
|
unsigned int
|
|
|
|
#define FUNCTION_DEBUG_UINT_FORMAT(value, buffer, bufferSize) \
|
|
|
|
cvtUIntToZ(value, buffer, bufferSize)
|
|
|
|
|
2018-10-19 10:51:33 +02:00
|
|
|
#define FUNCTION_DEBUG_UINTP_TYPE \
|
|
|
|
unsigned int *
|
|
|
|
#define FUNCTION_DEBUG_UINTP_FORMAT(value, buffer, bufferSize) \
|
|
|
|
ptrToLog(value, "unsigned int *", buffer, bufferSize)
|
|
|
|
|
2018-05-18 11:57:32 -04:00
|
|
|
#define FUNCTION_DEBUG_UINT16_TYPE \
|
|
|
|
uint16_t
|
|
|
|
#define FUNCTION_DEBUG_UINT16_FORMAT(value, buffer, bufferSize) \
|
|
|
|
FUNCTION_DEBUG_UINT_FORMAT(value, buffer, bufferSize)
|
|
|
|
|
|
|
|
#define FUNCTION_DEBUG_UINT32_TYPE \
|
|
|
|
uint32_t
|
|
|
|
#define FUNCTION_DEBUG_UINT32_FORMAT(value, buffer, bufferSize) \
|
|
|
|
FUNCTION_DEBUG_UINT_FORMAT(value, buffer, bufferSize)
|
|
|
|
|
|
|
|
#define FUNCTION_DEBUG_UINT64_TYPE \
|
|
|
|
uint64_t
|
|
|
|
#define FUNCTION_DEBUG_UINT64_FORMAT(value, buffer, bufferSize) \
|
|
|
|
cvtUInt64ToZ(value, buffer, bufferSize)
|
|
|
|
|
|
|
|
#define FUNCTION_DEBUG_VOIDP_TYPE \
|
|
|
|
void *
|
|
|
|
#define FUNCTION_DEBUG_VOIDP_FORMAT(value, buffer, bufferSize) \
|
|
|
|
ptrToLog(value, "void *", buffer, bufferSize)
|
|
|
|
|
2018-09-14 16:08:33 -04:00
|
|
|
#define FUNCTION_DEBUG_CONST_VOIDP_TYPE \
|
|
|
|
const void *
|
|
|
|
#define FUNCTION_DEBUG_CONST_VOIDP_FORMAT(value, buffer, bufferSize) \
|
|
|
|
FUNCTION_DEBUG_VOIDP_FORMAT(value, buffer, bufferSize)
|
|
|
|
|
2018-05-18 11:57:32 -04:00
|
|
|
#define FUNCTION_DEBUG_VOIDPP_TYPE \
|
|
|
|
void **
|
|
|
|
#define FUNCTION_DEBUG_VOIDPP_FORMAT(value, buffer, bufferSize) \
|
|
|
|
ptrToLog(value, "void **", buffer, bufferSize)
|
|
|
|
|
|
|
|
#define FUNCTION_DEBUG_STRINGZ_TYPE \
|
|
|
|
const char *
|
|
|
|
#define FUNCTION_DEBUG_STRINGZ_FORMAT(value, buffer, bufferSize) \
|
|
|
|
strzToLog(value, buffer, bufferSize)
|
|
|
|
|
|
|
|
/***********************************************************************************************************************************
|
|
|
|
Assert function to be used with function debugging
|
|
|
|
|
|
|
|
The assert statement is compiled into production code but only runs when the log level >= debug
|
|
|
|
***********************************************************************************************************************************/
|
|
|
|
#define FUNCTION_DEBUG_ASSERT(condition) \
|
|
|
|
do \
|
|
|
|
{ \
|
|
|
|
if (!(condition)) \
|
|
|
|
THROW_FMT(AssertError, "function debug assertion '%s' failed", #condition); \
|
|
|
|
} \
|
|
|
|
while (0)
|
|
|
|
|
|
|
|
/***********************************************************************************************************************************
|
|
|
|
Macros to return function results (or void)
|
|
|
|
***********************************************************************************************************************************/
|
|
|
|
#define FUNCTION_DEBUG_RESULT(typeMacroPrefix, result) \
|
|
|
|
do \
|
|
|
|
{ \
|
|
|
|
FUNCTION_DEBUG_##typeMacroPrefix##_TYPE FUNCTION_DEBUG_RESULT_result = result; \
|
|
|
|
\
|
|
|
|
STACK_TRACE_POP(); \
|
|
|
|
\
|
|
|
|
if (logWill(FUNCTION_DEBUG_LEVEL())) \
|
|
|
|
{ \
|
|
|
|
char buffer[STACK_TRACE_PARAM_MAX]; \
|
|
|
|
\
|
|
|
|
FUNCTION_DEBUG_##typeMacroPrefix##_FORMAT(FUNCTION_DEBUG_RESULT_result, buffer, sizeof(buffer)); \
|
|
|
|
LOG(FUNCTION_DEBUG_LEVEL(), 0, "=> %s", buffer); \
|
|
|
|
} \
|
|
|
|
\
|
|
|
|
return FUNCTION_DEBUG_RESULT_result; \
|
|
|
|
} \
|
|
|
|
while(0)
|
|
|
|
|
|
|
|
#define FUNCTION_DEBUG_RESULT_VOID() \
|
|
|
|
do \
|
|
|
|
{ \
|
|
|
|
STACK_TRACE_POP(); \
|
|
|
|
\
|
|
|
|
LOG_WILL(FUNCTION_DEBUG_LEVEL(), 0, "=> void"); \
|
|
|
|
} \
|
|
|
|
while(0)
|
|
|
|
|
|
|
|
/***********************************************************************************************************************************
|
|
|
|
Function Test Macros
|
|
|
|
|
|
|
|
In debug builds these macros will update the stack trace with function names and parameters but not log. In production builds all
|
|
|
|
test macros are compiled out.
|
|
|
|
***********************************************************************************************************************************/
|
|
|
|
#ifdef DEBUG
|
|
|
|
#define FUNCTION_TEST_BEGIN() \
|
|
|
|
if (stackTraceTest()) \
|
|
|
|
{ \
|
|
|
|
STACK_TRACE_PUSH(logLevelDebug); \
|
|
|
|
stackTraceParamLog()
|
|
|
|
|
|
|
|
#define FUNCTION_TEST_PARAM(typeMacroPrefix, param) \
|
|
|
|
FUNCTION_DEBUG_PARAM(typeMacroPrefix, param)
|
|
|
|
|
|
|
|
#define FUNCTION_TEST_PARAM_PTR(typeName, param) \
|
|
|
|
FUNCTION_DEBUG_PARAM_PTR(typeName, param)
|
|
|
|
|
|
|
|
#define FUNCTION_TEST_END() \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define FUNCTION_TEST_VOID() \
|
|
|
|
FUNCTION_TEST_BEGIN(); \
|
|
|
|
FUNCTION_TEST_END();
|
|
|
|
|
|
|
|
#define FUNCTION_TEST_ASSERT(condition) \
|
|
|
|
do \
|
|
|
|
{ \
|
|
|
|
if (!(condition)) \
|
|
|
|
THROW_FMT(AssertError, "function test assertion '%s' failed", #condition); \
|
|
|
|
} \
|
|
|
|
while (0)
|
|
|
|
|
|
|
|
#define FUNCTION_TEST_RESULT(typeMacroPrefix, result) \
|
|
|
|
do \
|
|
|
|
{ \
|
|
|
|
FUNCTION_DEBUG_##typeMacroPrefix##_TYPE FUNCTION_DEBUG_RESULT_result = result; \
|
|
|
|
\
|
|
|
|
if (stackTraceTest()) \
|
|
|
|
STACK_TRACE_POP(); \
|
|
|
|
\
|
|
|
|
return FUNCTION_DEBUG_RESULT_result; \
|
|
|
|
} \
|
|
|
|
while(0);
|
|
|
|
|
|
|
|
#define FUNCTION_TEST_RESULT_VOID() \
|
|
|
|
do \
|
|
|
|
{ \
|
|
|
|
if (stackTraceTest()) \
|
|
|
|
STACK_TRACE_POP(); \
|
|
|
|
} \
|
|
|
|
while(0);
|
|
|
|
#else
|
|
|
|
#define FUNCTION_TEST_BEGIN()
|
|
|
|
#define FUNCTION_TEST_PARAM(typeMacroPrefix, param)
|
|
|
|
#define FUNCTION_TEST_PARAM_PTR(typeName, param)
|
|
|
|
#define FUNCTION_TEST_END()
|
|
|
|
#define FUNCTION_TEST_VOID()
|
|
|
|
#define FUNCTION_TEST_ASSERT(condition)
|
|
|
|
#define FUNCTION_TEST_RESULT(typeMacroPrefix, result) \
|
|
|
|
return result
|
|
|
|
#define FUNCTION_TEST_RESULT_VOID()
|
|
|
|
#endif
|
|
|
|
|
2018-03-12 14:31:22 -04:00
|
|
|
#endif
|