/****************************************************************************** ** Filename: danerror.c ** Purpose: Routines for managing error trapping ** Author: Dan Johnson ** History: 3/17/89, DSJ, Created. ** ** (c) Copyright Hewlett-Packard Company, 1988. ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** http://www.apache.org/licenses/LICENSE-2.0 ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. ******************************************************************************/ /**---------------------------------------------------------------------------- Include Files and Type Defines ----------------------------------------------------------------------------**/ #include "general.h" #include "danerror.h" #include "callcpp.h" #include "globaloc.h" #ifdef __UNIX__ #include "assert.h" #endif #include #include #define MAXTRAPDEPTH 100 #define ERRORTRAPDEPTH 1000 /**---------------------------------------------------------------------------- Global Data Definitions and Declarations ----------------------------------------------------------------------------**/ static jmp_buf ErrorTrapStack[MAXTRAPDEPTH]; static VOID_PROC ProcTrapStack[MAXTRAPDEPTH]; static INT32 CurrentTrapDepth = 0; /**---------------------------------------------------------------------------- Public Code ----------------------------------------------------------------------------**/ /*---------------------------------------------------------------------------*/ void ReleaseErrorTrap() { /* ** Parameters: ** None ** Globals: ** CurrentTrapDepth number of traps on the stack ** Operation: ** This routine removes the current error trap from the ** error trap stack, thus returning control to the previous ** error trap. If the error trap stack is empty, nothing is ** done. ** Return: ** None ** Exceptions: ** None ** History: ** 4/3/89, DSJ, Created. */ if (CurrentTrapDepth > 0) { CurrentTrapDepth--; } } /* ReleaseErrorTrap */ /*---------------------------------------------------------------------------*/ void DoError(int Error, const char *Message) { /* ** Parameters: ** Error error number which is to be trapped ** Message pointer to a string to be printed as an error message ** Globals: ** ErrorTrapStack stack of error traps ** CurrentTrapDepth number of traps on the stack ** Operation: ** This routine prints the specified error message to stderr. ** It then jumps to the current error trap. If the error trap ** stack is empty, the calling program is terminated with a ** fatal error message. ** Return: ** None - this routine does not return. ** Exceptions: ** Empty error trap stack terminates the calling program. ** History: ** 4/3/89, DSJ, Created. */ if (Message != NULL) { cprintf ("\nError: %s!\n", Message); } if (CurrentTrapDepth <= 0) { cprintf ("\nFatal error: No error trap defined!\n"); /* SPC 20/4/94 There used to be a call to abort() here. I've changed it to call into the C++ error code to generate a meaningful status code */ signal_termination_handler(Error); } if (ProcTrapStack[CurrentTrapDepth - 1] != DO_NOTHING) (*ProcTrapStack[CurrentTrapDepth - 1]) (); longjmp (ErrorTrapStack[CurrentTrapDepth - 1], 1); } /* DoError */ /**---------------------------------------------------------------------------- Private Code ----------------------------------------------------------------------------**/ /*---------------------------------------------------------------------------*/ jmp_buf &PushErrorTrap(VOID_PROC Procedure) { /* ** Parameters: ** Procedure trap procedure to execute ** Globals: ** ErrorTrapStack stack of error traps ** CurrentTrapDepth number of traps on the stack ** Operation: ** This routine pushes a new error trap onto the top of ** the error trap stack. This new error trap can then be ** used in a call to setjmp. This trap is then in effect ** until ReleaseErrorTrap is called. WARNING: a procedure ** that calls PushErrorTrap should never exit before calling ** ReleaseErrorTrap. ** Return: ** Pointer to a new error trap buffer ** Exceptions: ** Traps an error if the error trap stack is already full ** History: ** 3/17/89, DSJ, Created. ** 9/12/90, DSJ, Added trap procedure parameter. */ if (CurrentTrapDepth >= MAXTRAPDEPTH) DoError (ERRORTRAPDEPTH, "Error trap depth exceeded"); ProcTrapStack[CurrentTrapDepth] = Procedure; return ErrorTrapStack[CurrentTrapDepth++]; } /* PushErrorTrap */