home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programming
/
powerprogramming1994.iso
/
progtool
/
irit
/
drawfuns.arc
/
MATHERR.C
< prev
next >
Wrap
Text File
|
1989-08-02
|
5KB
|
168 lines
/*****************************************************************************
* 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;
}