/***************************************************************************** * Module to handle floating point errors: * * Action taken in floating point error is set via the Action selected during * * set up (see MathErr.h for different possible actions). * * * * This file is compiled under MSDOS only. * * * * Written by: Gershon Elber IBM PC Ver 1.0, Mar. 1989 * *****************************************************************************/ #include #include #include #include #include #include #include #include "matherr.h" #include "program.h" #include "graphgen.h" #ifndef TRUE #define TRUE -1 #define FALSE 0 #endif TRUE static char *MathError = NULL; static int MEAction = ME_IGNORE; static void far *MEAddr = NULL; static void PerformMEAction(void); static void cdecl DefaultFPEHandler(int Sig, int Type, int *RegList); /***************************************************************************** * Routine to set up the math error traping routines: * * 1. redefine matherr routine, so it traps the floating points transadental * * functions (sin, cos, log etc.). * * 2. Traps and SIGFPE signals into our handler (traps lower level errors * * such as div by zero). * *****************************************************************************/ void MathErrorSetUp(int Action, void far *Addr) { signal(SIGFPE, DefaultFPEHandler); /* Will trap floating point errors. */ MEAction = Action; MEAddr = Addr; } /***************************************************************************** * Routine to fetch last math error if was was or NULL otherwise and reset * * it to the next time... * *****************************************************************************/ char *MathErrorGet(void) { char *p; p = MathError; MathError = NULL; return p; } /***************************************************************************** * Routine to kill current process after closing all open devices and * * printing exact math error causing this death. * *****************************************************************************/ static void PerformMEAction(void) { void (far *PFunc)(); switch (MEAction) { case ME_KILL: # ifdef HAS_GRAPHICS GGCloseGraph(); /* Close the graphic driver. */ # endif HAS_GRAPHICS fprintf(stderr, "Fatal Math Error - %s\n", MathError); MyExit(1); break; case ME_IGNORE: break; case ME_LONGJMP: longjmp(*(((jmp_buf *) MEAddr)), 1); break; case ME_CALL: PFunc = MEAddr; (PFunc)(); break; } } /***************************************************************************** * Routine that is called from the floating point package in case of fatal * * floating point error. Print error message, long jump to main loop. Default * * FPE handler - must be reset after redirected to other module. * *****************************************************************************/ static void cdecl DefaultFPEHandler(int Sig, int Type, int *RegList) { switch (Type) { case FPE_INTOVFLOW: MathError = "integer overflow"; break; case FPE_INTDIV0: MathError = "integer divide by zero"; break; case FPE_INVALID: MathError = "invalid operation"; break; case FPE_ZERODIVIDE: MathError = "division by zero"; break; case FPE_OVERFLOW: MathError = "numeric overflow"; break; case FPE_UNDERFLOW: MathError = "numeric underflow"; break; case FPE_INEXACT: MathError = "precision lost"; break; case FPE_EXPLICITGEN: MathError = "explicit signal"; break; } PerformMEAction(); } /***************************************************************************** * Routine to trap math errors - set GlobalMathError to error number, and * * GlobalMathFunc to the math function with the error. Return TRUE to * * make it believe that everything is ok. now... * *****************************************************************************/ int cdecl matherr(struct exception _FAR *except) { static char s[32]; except -> retval = 1.0; /* return something reasonable... */ switch(except -> type) { case DOMAIN: strcpy(s, "DOMAIN "); break; case SING: strcpy(s, "SING "); break; case OVERFLOW: strcpy(s, "O.F. "); break; case UNDERFLOW: strcpy(s, "U.F. "); break; case TLOSS: strcpy(s, "TLOSS "); break; default: strcpy(s, "Undef. "); break; } strcat(s, "err, func. "); strcat(s, except -> name); MathError = s; PerformMEAction(); return TRUE; }