home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- * 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). *
- * *
- * Written by: Gershon Elber IBM PC Ver 1.0, Mar. 1989 *
- *****************************************************************************/
-
- #include <stdio.h>
- #include <math.h>
- #include <string.h>
- #include <float.h>
- #include <signal.h>
- #include <setjmp.h>
- #include <graphics.h>
- #include "MathErr.h"
- #include "Program.h"
-
- #ifdef HAS_GRAPHICS
- #include "GraphGnG.h"
- #endif HAS_GRAPHICS
-
- #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 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 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 matherr(except)
- struct exception *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;
- }
-
-