#include "maxLogger.h" /* Globals & Static Members */ Logger *Logger::globalLoggingInstance = 0; /* Error Logger Member Functions */ Logger::Logger() { VoidEverything(); LogInstance( LLOGGING, SAT_MEDIUM_LEVEL, "A new, void Logging instance has been created." ); } Logger::Logger( LoggingPipeType toWhere, char *additionalStringInfo ) { VoidEverything(); SetPipeInstance( toWhere, additionalStringInfo ); sprintf( GetLogString(), "A new, piped logging instance has been created with data '%s'.", additionalStringInfo ); LogInstance( LLOGGING, SAT_MEDIUM_LEVEL, GetLogString() ); } Logger::~Logger() { //Send message telling everyone we're going away. LogInstance( LLOGGING, SAT_MEDIUM_LEVEL, "Error logger shutting down!" ); //If we've got an open file, close that muthafugga! if ( ( myLogDestination == PIPE_TO_FILE ) && myFileOutputLog.is_open() ) myFileOutputLog.close(); VoidEverything(); } /* Public, Static Member Functions */ void Logger::FunctionEntry( char *newFunctionName ) { if ( !globalLoggingInstance ) globalLoggingInstance = new Logger(); if ( globalLoggingInstance ) globalLoggingInstance->FunctionEntryInstance( newFunctionName ); } void Logger::FunctionExit() { if ( !globalLoggingInstance ) globalLoggingInstance = new Logger(); if ( globalLoggingInstance ) globalLoggingInstance->FunctionExitInstance(); } int Logger::GetHierarchyLevel() { if ( !globalLoggingInstance ) globalLoggingInstance = new Logger(); if ( globalLoggingInstance ) return globalLoggingInstance->GetHierarchyLevelInstance(); else return 0; } char * Logger::GetLogString() { if ( !globalLoggingInstance ) globalLoggingInstance = new Logger(); if ( globalLoggingInstance ) return globalLoggingInstance->GetLogStringInstance(); else return 0; } void Logger::Log( SystemType whichSystem, SystemAspectType whichErrorKind, char *errorDescription ) { if ( !globalLoggingInstance ) globalLoggingInstance = new Logger(); if ( globalLoggingInstance ) globalLoggingInstance->LogInstance( whichSystem, whichErrorKind, errorDescription ); } void Logger::SetCurrentFunctionName( char *newFunctionName ) { if ( !globalLoggingInstance ) globalLoggingInstance = new Logger(); if ( globalLoggingInstance ) globalLoggingInstance->SetCurrentFunctionNameInstance( newFunctionName ); } void Logger::SetHierarchyLevel( unsigned int newIndentLevel ) { if ( !globalLoggingInstance ) globalLoggingInstance = new Logger(); if ( globalLoggingInstance ) globalLoggingInstance->SetHierarchyLevelInstance( newIndentLevel ); } void Logger::SetOneErrorMask( SystemType whichType, long int whichErrors ) { if ( !globalLoggingInstance ) globalLoggingInstance = new Logger(); if ( globalLoggingInstance ) globalLoggingInstance->SetOneErrorMaskInstance( whichType, whichErrors ); } void Logger::SetPipe( LoggingPipeType toWhere, char *additionalStringInfo ) { if ( !globalLoggingInstance ) globalLoggingInstance = new Logger(); if ( globalLoggingInstance ) globalLoggingInstance->SetPipeInstance( toWhere, additionalStringInfo ); } /* Private Member Functions */ void Logger::FunctionEntryInstance( char *newFunctionName ) { SetCurrentFunctionNameInstance( newFunctionName ); SetHierarchyLevelInstance( GetHierarchyLevelInstance() + 1 ); } void Logger::FunctionExitInstance() { char endMsg[64]; SetHierarchyLevelInstance( GetHierarchyLevelInstance() - 1 ); if ( myFunctionNames.back() ) { if ( myWrittenHierarchyLevel >= myHierarchyLevel ) { sprintf( endMsg, "#END {%s}", myFunctionNames.back() ); WriteToPipe( endMsg ); //LogInstance( LLOGGING, this->SAT_HIGH_LEVEL, GetLogStringInstance()); --myWrittenHierarchyLevel; } free( (void *)myFunctionNames.back() ); myFunctionNames.pop_back(); } } int Logger::GetHierarchyLevelInstance() { return myHierarchyLevel; } char * Logger::GetLogStringInstance() { return myLogString; } void Logger::LogInstance( SystemType whichSystem, SystemAspectType whichErrorKind, char *errorDescription ) { unsigned int i; char *typeBuf; char beginMsg[64]; if ( !errorDescription ) return; if ( !( (int)whichErrorKind & myErrorMasks[(int)whichSystem] ) ) return; typeBuf = (char *)malloc( strlen( errorDescription ) + 64 ); if ( !typeBuf ) return; typeBuf = strcpy( typeBuf, errorDescription ); switch( whichErrorKind ) { case SAT_NONE: break; case SAT_NULL_ERROR: strcat( typeBuf, " - (***!!!NULL ERROR!!!***, " ); break; case SAT_CRITICAL_ERROR: strcat( typeBuf, " - (***!!!CRITICAL ERROR!!!***, " ); break; case SAT_PARAMETER_INVALID_ERROR: strcat( typeBuf, " - (***PARAMETER ERROR***, " ); break; case SAT_OTHER_ERROR: strcat( typeBuf, " - (***OTHER ERROR***, " ); break; case SAT_HIGH_LEVEL: strcat( typeBuf, " - (---HIGH LEVEL---, " ); break; case SAT_MEDIUM_LEVEL: strcat( typeBuf, " - (MEDIUM LEVEL, " ); break; case SAT_LOW_LEVEL: strcat( typeBuf, " - (LOW LEVEL, " ); break; case SAT_DEBUG_SPAM_LEVEL: strcat( typeBuf, " - (SPAM LEVEL, " ); break; case SAT_ALL: strcat( typeBuf, " - (ALL INCLUSIVE, " ); break; } switch( whichSystem ) { case ST_MAP_ME_TO_APP_SPECIFIC_SYSTEM1: strcat( typeBuf, "SYS_ONE)" ); break; case ST_MAP_ME_TO_APP_SPECIFIC_SYSTEM2: strcat( typeBuf, "SYS_TWO)" ); break; case ST_MAP_ME_TO_APP_SPECIFIC_SYSTEM3: strcat( typeBuf, "SYS_THREE)" ); break; case ST_MAP_ME_TO_APP_SPECIFIC_SYSTEM4: strcat( typeBuf, "SYS_FOUR)" ); break; case ST_MAP_ME_TO_APP_SPECIFIC_SYSTEM5: strcat( typeBuf, "SYS_FIVE)" ); break; case ST_MAP_ME_TO_APP_SPECIFIC_SYSTEM6: strcat( typeBuf, "SYS_SIX)" ); break; case ST_MAP_ME_TO_APP_SPECIFIC_SYSTEM7: strcat( typeBuf, "SYS_SEVEN)" ); break; case ST_MAP_ME_TO_APP_SPECIFIC_SYSTEM8: strcat( typeBuf, "SYS_EIGHT)" ); break; } //Now that we've created the correct logging line to print, we need to worry //about function entries and exits. Only do this if we're not writing to a dialog box. if ( myLogDestination != PIPE_TO_DIALOG_BOX ) { unsigned int tempHierarchyLevel = myHierarchyLevel; i = 0; for( CharStarVectorIterator hierarchyDepthIterator = myFunctionNames.begin(); hierarchyDepthIterator != myFunctionNames.end(); ++hierarchyDepthIterator ) { ++i; //Since we're writing some output, we need to print all function headings //leading up to this output, bumping up our written hierarchy level to match //the "actual" level. //If we've reached a function level that's deeper than what we've written out already... if ( i > myWrittenHierarchyLevel ) { myHierarchyLevel = myWrittenHierarchyLevel; sprintf( beginMsg, "#BEGIN {%s}", *hierarchyDepthIterator ); WriteToPipe( beginMsg ); myHierarchyLevel = tempHierarchyLevel; ++myWrittenHierarchyLevel; } } } WriteToPipe( typeBuf ); free(typeBuf); } void Logger::SetCurrentFunctionNameInstance( char *newFunctionName ) { char *newBuf; //No FunctionEntry Instance allowed...that function uses this! if ( !newFunctionName ) { LogInstance( LLOGGING, SAT_NULL_ERROR, "newFunctionName is null!" ); return; } newBuf = strdup( newFunctionName ); myFunctionNames.push_back( newBuf ); } void Logger::SetHierarchyLevelInstance( unsigned int newIndentLevel ) { myHierarchyLevel = newIndentLevel; } void Logger::SetOneErrorMaskInstance( SystemType whichType, long int whichErrors ) { if ( ( (int)whichType < 0 ) || ( (int)whichType >= MY_MAX_NUM_SYSTEMS ) ) { LogInstance( LLOGGING, SAT_PARAMETER_INVALID_ERROR, "whichType is out of bounds!" ); return; } //Now that the sanity check is out of the way, let us change the error mask! myErrorMasks[(int)whichType] = whichErrors; sprintf( GetLogStringInstance(), "Set error mask for system with ID %x to %x.", (int)whichType, whichErrors ); LogInstance( LLOGGING, SAT_LOW_LEVEL, GetLogStringInstance() ); } void Logger::SetPipeInstance( LoggingPipeType toWhere, char *additionalStringInfo ) { myLogDestination = toWhere; switch( myLogDestination ) { case PIPE_TO_FILE: if ( myFileOutputLog.is_open() ) myFileOutputLog.close(); if ( additionalStringInfo ) myFileOutputLog.open( additionalStringInfo, ofstream::out | ofstream::trunc ); else myFileOutputLog.open( "Kens_Logger_Log_File.txt", ofstream::out | ofstream::trunc ); LogInstance( LLOGGING, SAT_LOW_LEVEL, "Error output piped to file." ); break; case PIPE_TO_COUT: LogInstance( LLOGGING, SAT_LOW_LEVEL, "Error output piped to cout." ); break; case PIPE_TO_CERR: LogInstance( LLOGGING, SAT_LOW_LEVEL, "Error output piped to cerr." ); break; case PIPE_TO_DIALOG_BOX: LogInstance( LLOGGING, SAT_LOW_LEVEL, "Error output piped to dialog box." ); break; case PIPE_TO_DEV_NULL: LogInstance( LLOGGING, SAT_LOW_LEVEL, "Error output piped to dev null." ); break; } } void Logger::VoidEverything() { myLogDestination = PIPE_TO_DEV_NULL; myHierarchyLevel = 0; myWrittenHierarchyLevel = 0; //(Get rid of the stack of called functions.) for (CharStarVectorIterator it = myFunctionNames.begin(); it < myFunctionNames.end(); it++) { if (*it) free ((void *)(*it)); } myFunctionNames.erase( myFunctionNames.begin(), myFunctionNames.end() ); //Make it so that our logger blindly accepts all logs... for( int i = 0; i < MY_MAX_NUM_SYSTEMS; ++i ) SetOneErrorMaskInstance( (SystemType)i, (long int)SAT_ALL ); //...but pipes them all to /dev/null. Mwahaha! The irony! strncpy( myLogString, "No Error", LOGGER_STRING_BUFFER_SIZE - 1 ); } void Logger::WriteToPipe( char *textToPipe ) { switch( myLogDestination ) { case PIPE_TO_FILE: if ( myFileOutputLog.is_open() ) { for (unsigned int i = 0; i < myHierarchyLevel; ++i ) myFileOutputLog << " "; myFileOutputLog << textToPipe << endl; myFileOutputLog.flush(); } break; case PIPE_TO_COUT: cout << "(" << textToPipe << ")" << endl; break; case PIPE_TO_CERR: cerr << "(" << textToPipe << ")" << endl; break; case PIPE_TO_DIALOG_BOX: MessageBox( NULL, textToPipe, "Logger", MB_OK ); break; case PIPE_TO_DEV_NULL: break; } }