/** \file CustomAssert.h
* Defines the functionality for assertions. Essentially, extends the
* standard C library assertions by providing slightly more detailed
* information on what went wrong, and logging the information into an
* appropriate log file.
*
* In addition to the persistent and non-persistent asserts, there is
* also a WEAK_ASSERT macro, which essentially just calls the custom
* assert function so that if an error is caught, it will be
* logged. But the error is not considered fatal enough to warrant a
* halt on the game execution, so it goes on.
*
* Revision History:
* 2003-09-22 v1.1 - Added the WEAK_ASSERT macro
*
* @warning - The macros use EMBEDDED x86 ASSEMBLY to halt
* application execution. Thus, the code will not work on machines
* with non-Intel-compatible processors. (Which rules out SPARC
* machines, for instance.)
*
* @note There are two types of asserts here. The regular Assert macro
* is just like the standard assertion in that it will only be used if
* the program is compiled in DEBUG mode. The PersistentAssert will be
* evaluated always, regardless of debug status.
*
* @todo Add the functionality to show a dialog box with the assertion
* is an error was encountered.
*
* @author Vovansim (aka Scorpion)
* @version 1.1
* @date September 22, 2003
*/
#ifndef CUSTOM_ASSERTION_MACRO
#define CUSTOM_ASSERTION_MACRO
#include
#include "LogManager.h"
/**
* Define the __ASM__ macro here. This guy is responsible for choosing
* appropriate syntax for including inline assembly depending on the
* compiler, since they use different ones.
*/
#ifdef __ASM__ //Clean up
#undef __ASM__
#endif
#ifdef __ASM_BREAK_SIGNAL__
#undef __ASM_BREAK_SIGNAL__
#endif
#if (defined WIN32) //This is the way VS likes its asm
#define __ASM__(code) __asm { code }
//VS doesn't like any prefixes before its literals
#define __ASM_BREAK_SIGNAL__ int 3
#elif (defined __GNUC__) //This is the way GCC likes its asm
#define __ASM__(code) __asm__(#code);
//GCC likes a $ prefix before its literals
#define __ASM_BREAK_SIGNAL__ int $3
#else //If you use a different compiler, gotta
//find out how it likes its asm
#error "Please define the syntax for inline assembly for your compiler."
#endif
/**
* Checks if the expression is true. If it is not, then the execution
* of the program is halted and the error description is written into
* a log file. The contents of the log file depend on whether the
* program was compiled in DEBUG mode or not. If the _DEBUG symbol was
* not defined, only the description of the error will be
* written. Otherwise, the entry will also contain the name of the
* source file where the error was detected and the line # in the
* source code.
*
* @param expression - Expression to evaluate
* @param description - Description of the error
* @param lineNum - line number of the code that broke
* @param fileName - the name of the source file where the assertion was fired
*/
inline bool CustomAssertFunction(bool expression, char* description,
int lineNum, char* fileName) {
bool result = expression;
if(!result) {
//Assertion failed. Write logs:
#ifdef _DEBUG
LogManager::GetInstance()->Write(LET_Application, "%s: Ln%d - %s",
fileName, lineNum, description);
#else
LogManager::GetInstance()->Write(LET_Application, description);
#endif//_DEBUG
}
return result;
}
#ifdef _DEBUG
#define ASSERT( exp, description ) \
if(!CustomAssertFunction( (bool)( exp ), ( description ), \
__LINE__, __FILE__)) { __ASM__(__ASM_BREAK_SIGNAL__); }
#else
#define ASSERT( exp, description ) ((void)( 0 ))
#endif//_DEBUG
#ifdef _DEBUG
#define PERSISTENT_ASSERT( exp, description ) ASSERT(( exp ), ( description ))
#else
#define PERSISTENT_ASSERT( exp, description ) \
if(!CustomAssertFunction( (bool)( exp ), ( description ), \
__LINE__, __FILE__)) { abort(); }
#endif//_DEBUG
#define WEAK_ASSERT( exp, description ) \
CustomAssertFunction( (bool)( exp ), ( description ),\
__LINE__, __FILE__)
#endif//CUSTOM_ASSERTION_MACRO