/*++ Copyright (c) 2004, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at http://opensource.org/licenses/bsd-license.php THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. Module Name: Exceptions.c Abstract: Exception logging routines. --*/ #include #include #include // for memset() #include "Exceptions.h" // // Max length of a saved exception message // #define MAX_EXCEPTION_MSG 200 // // We use this structure to track exceptions thrown. We nest deeper on // TryException() calls, and come back out on CatchException() calls. // We save off the first exception message for a given exception level, // but we save the count of how many were thrown. // typedef struct { int ExceptionCount; char ExceptionMsg[MAX_EXCEPTION_MSG]; } EXCEPTION_LOG; static EXCEPTION_LOG ExceptionLog[MAX_EXCEPTION_NESTING + 1]; static int ExceptionLevel; // // Initialize our data and structures for tracking exceptions. // int InitExceptions ( VOID ) { ExceptionLevel = -1; memset ((char *) &ExceptionLog, 0, sizeof (ExceptionLog)); return 0; } // // This function replaces the _try() exception macro. It sets the // nesting level. // int TryException ( VOID ) { // // Boost our exception level if we would not go out of range // ExceptionLevel++; if (ExceptionLevel >= MAX_EXCEPTION_NESTING) { fprintf (stderr, "ERROR: Max exception nesting level exceeded\n"); ExceptionLevel--; return 1; } return 0; } // // This function replaces the _catch() exception macro. It's used to decrement // the nesting level and return any exeption error messages that were // thrown at the current nesting level. // char * CatchException ( VOID ) { // // Return a pointer to exception message. NULL if no exceptions at this level // if (ExceptionLevel >= 0) { ExceptionLevel--; if (ExceptionLog[ExceptionLevel + 1].ExceptionMsg[0]) { return ExceptionLog[ExceptionLevel + 1].ExceptionMsg; } else { return NULL; } } else { fprintf (stderr, "ERROR: Invalid nesting level call to CatchException()\n"); return NULL; } } // // This function can be used to test for exceptions between the TryException() // and CatchException() calls in a given function. // int ExceptionThrown ( VOID ) { return ExceptionLog[ExceptionLevel].ExceptionCount; } // // This function replaces the _throw() exception macro. It saves off the // given error message at the current exeption level nesting. // int ThrowException ( char *Msg ) { if (ExceptionLevel < 0) { // // fprintf (stderr, "ERROR: Exception thrown out of scope"); // Haven't yet enabled handling of exceptions, so just emit the message. // fprintf (stderr, Msg); return 1; } // // Only log the first // if (ExceptionLog[ExceptionLevel].ExceptionMsg[0] == 0) { strncpy (ExceptionLog[ExceptionLevel].ExceptionMsg, Msg, MAX_EXCEPTION_MSG); } ExceptionLog[ExceptionLevel].ExceptionCount++; return 0; }