|
|
// Ruler
// 1 2 3 4 5 6 7 8
//345678901234567890123456789012345678901234567890123456789012345678901234567890
/********************************************************************/ /* */ /* The standard layout. */ /* */ /* The standard layout for 'cpp' files in this code is as */ /* follows: */ /* */ /* 1. Include files. */ /* 2. Constants local to the class. */ /* 3. Data structures local to the class. */ /* 4. Data initializations. */ /* 5. Static functions. */ /* 6. Class functions. */ /* */ /* The constructor is typically the first function, class */ /* member functions appear in alphabetical order with the */ /* destructor appearing at the end of the file. Any section */ /* or function this is not required is simply omitted. */ /* */ /********************************************************************/
#include "LibraryPCH.hpp"
#include "Global.hpp"
#include "Spinlock.hpp"
/********************************************************************/ /* */ /* Constants local to the class. */ /* */ /* The constants supplied here control various debug settings. */ /* */ /********************************************************************/
CONST SBIT32 MaxDebugFileName = 128; CONST SBIT32 DebugBufferSize = 512; #ifdef ENABLE_DEBUG
#ifdef ENABLE_DEBUG_FILE
/********************************************************************/ /* */ /* Static member initialization. */ /* */ /* Static member initialization sets the initial value for all */ /* static members. */ /* */ /********************************************************************/
STATIC CHAR DebugModuleName[ MaxDebugFileName ] = ""; STATIC SPINLOCK Spinlock;
/********************************************************************/ /* */ /* Debug file name. */ /* */ /* We sometimes want to change the debug file name to prevent */ /* the debug file being overwritten by a DLLs output or a later */ /* run of the same application. */ /* */ /********************************************************************/
HANDLE DebugFileHandle( VOID ) { AUTO CHAR FileName[ MaxDebugFileName ]; STATIC HANDLE DebugFile = INVALID_HANDLE_VALUE;
//
// We will open the debug file if it is not
// already open.
//
if ( DebugFile == INVALID_HANDLE_VALUE ) { //
// Construct the full file name.
//
sprintf ( FileName, "C:\\Temp\\DebugTrace%s.log", DebugModuleName );
//
// Now lets try to open the file.
//
DebugFile = ( CreateFile ( ((LPCTSTR) FileName), (GENERIC_READ | GENERIC_WRITE), FILE_SHARE_READ, NULL, CREATE_ALWAYS, NULL, NULL ) );
//
// When the file will not open for some reason
// we try an alternative path.
//
if ( DebugFile == INVALID_HANDLE_VALUE ) { //
// Construct the alternate file name.
//
sprintf ( FileName, "C:\\DebugTrace%s.log", DebugModuleName );
//
// Try again using an alternative name.
//
DebugFile = ( CreateFile ( ((LPCTSTR) FileName), (GENERIC_READ | GENERIC_WRITE), FILE_SHARE_READ, NULL, CREATE_ALWAYS, NULL, NULL ) ); } }
return DebugFile; }
/********************************************************************/ /* */ /* Debug file name. */ /* */ /* We sometimes want to change the debug file name to prevent */ /* the debug file being overwritten by a DLLs output or a later */ /* run of the same application. */ /* */ /********************************************************************/
VOID DebugFileName( CONST CHAR *FileName ) { AUTO CHAR EditBuffer[ MaxDebugFileName ]; REGISTER CHAR *Current;
//
// Copy the file name into an edit buffer
// so we can remove any directories or
// trailing names.
//
strncpy( EditBuffer,FileName,MaxDebugFileName );
EditBuffer[ (MaxDebugFileName-1) ] = '\0';
//
// Scan backwards to remove any suffix.
//
for ( Current = & EditBuffer[ (strlen( EditBuffer )-1) ]; (Current > EditBuffer) && ((*Current) != '.') && ((*Current) != '\\'); Current -- );
if ( (Current > EditBuffer) && (*Current) == '.' ) { (*Current) = '\0'; }
//
// Scan backwards to the first directory name.
//
for ( Current = & EditBuffer[ (strlen( EditBuffer )-1) ]; (Current > EditBuffer) && ((*Current) != '\\'); Current -- );
if ( (*Current) == '\\' ) { Current ++; }
//
// Copy the edited file name.
//
DebugModuleName[0] = '-';
strncpy( & DebugModuleName[1],Current,(MaxDebugFileName-1) ); } #endif
#endif
/********************************************************************/ /* */ /* Debug printing. */ /* */ /* We sometimes need to print message during debugging. We */ /* do this using the following 'printf' like function. */ /* */ /********************************************************************/
VOID DebugPrint( CONST CHAR *Format,... ) { AUTO CHAR Buffer[ DebugBufferSize ];
//
// Start of variable arguments.
//
va_list Arguments;
va_start(Arguments, Format);
//
// Format the string to be printed.
//
_vsnprintf ( Buffer, (DebugBufferSize-1), Format, Arguments );
//
// Force null termination.
//
Buffer[ (DebugBufferSize-1) ] = '\0';
#ifdef ENABLE_DEBUG_FILE
//
// Claim a spinlock to prevent multiple
// threads executing overlapping writes.
//
Spinlock.ClaimLock();
//
// We will write to the debug file if there
// is a valid handle.
//
if ( DebugFileHandle() != INVALID_HANDLE_VALUE ) { REGISTER CHAR *Current = Buffer; REGISTER SBIT32 Length;
//
// A number of windows applications are too
// stupid to understand a simple '\n'. So
// here we convert all "\n" to "\r\n".
//
for ( /* void */;(*Current) != '\0';Current += Length ) { STATIC DWORD Written;
//
// Count the characters until the next
// newline or end of string.
//
for ( Length=0; ((Current[ Length ] != '\n') && (Current[ Length ] != '\0')); Length ++ );
//
// Write the string and then add a return
// newline sequence.
//
WriteFile ( DebugFileHandle(), ((LPCVOID) Current), ((DWORD) Length), & Written, NULL );
//
// Generate a newline (if needed).
//
if ( Current[ Length ] == '\n' ) { WriteFile ( DebugFileHandle(), ((LPCVOID) "\r\n"), ((DWORD) (sizeof("\r\n") - 1)), & Written, NULL );
Length ++; } }
//
// Flush the file buffers.
//
FlushFileBuffers( DebugFileHandle() ); }
//
// Release any lock claimed earlier.
//
Spinlock.ReleaseLock(); #else
//
// Write to the debug window.
//
OutputDebugString( Buffer ); #endif
//
// End of variable arguments.
//
va_end( Arguments ); }
/********************************************************************/ /* */ /* Software failure. */ /* */ /* We know that when this function is called the application */ /* has failed so we simply try to cleanly exit in the vain */ /* hope that the failure can be caught and corrected. */ /* */ /********************************************************************/
VOID Failure( char *Message,BOOLEAN Report ) { #ifdef ENABLE_DEBUG
//
// Report the fault to the debug stream
// (if required).
//
if ( Report ) { DebugPrint( "*** Software Failure: %s ***\n",Message ); } #endif
//
// Raise an exception.
//
#ifdef DISABLE_STRUCTURED_EXCEPTIONS
throw ((FAULT) Message); #else
RaiseException( 1,0,1,((CONST DWORD*) Message) ); #endif
}
|