/** \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