home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / i / iritsm3s.zip / poly3d / matherr.c < prev    next >
C/C++ Source or Header  |  1992-02-10  |  5KB  |  166 lines

  1. /*****************************************************************************
  2. * Module to handle floating point errors:                     *
  3. * Action taken in floating point error is set via the Action selected during *
  4. * set up (see MathErr.h for different possible actions).             *
  5. *                                         *
  6. * This file is compiled under MSDOS only.                     *
  7. *                                         *
  8. * Written by:  Gershon Elber            IBM PC Ver 1.0,    Mar. 1989    *
  9. *****************************************************************************/
  10.  
  11. #include <stdio.h>
  12. #include <math.h>
  13. #include <string.h>
  14. #include <float.h>
  15. #include <signal.h>
  16. #include <setjmp.h>
  17. #include <graphics.h>
  18. #include "matherr.h"
  19. #include "program.h"
  20. #include "graphgen.h"
  21.  
  22. #ifndef TRUE
  23. #define TRUE    -1
  24. #define FALSE    0
  25. #endif TRUE
  26.  
  27. static char *MathError = NULL;
  28. static int MEAction = ME_IGNORE;
  29. static void far *MEAddr = NULL;
  30.  
  31. static void PerformMEAction(void);
  32. static void cdecl DefaultFPEHandler(int Sig, int Type, int *RegList);
  33.  
  34. /*****************************************************************************
  35. *   Routine to set up the math error traping routines:                 *
  36. * 1. redefine matherr routine, so it traps the floating points transadental  *
  37. *    functions (sin, cos, log etc.).                         *
  38. * 2. Traps and SIGFPE signals into our handler (traps lower level errors     *
  39. *    such as div by zero).                             *
  40. *****************************************************************************/
  41. void MathErrorSetUp(int Action, void far *Addr)
  42. {
  43.     signal(SIGFPE, DefaultFPEHandler);     /* Will trap floating point errors. */
  44.     MEAction = Action;
  45.     MEAddr = Addr;
  46. }
  47.  
  48. /*****************************************************************************
  49. *   Routine to fetch last math error if was was or NULL otherwise and reset  *
  50. * it to the next time...                             *
  51. *****************************************************************************/
  52. char *MathErrorGet(void)
  53. {
  54.     char *p;
  55.  
  56.     p = MathError;
  57.     MathError = NULL;
  58.     return p;
  59. }
  60.  
  61. /*****************************************************************************
  62. *   Routine to kill current process after closing all open devices and         *
  63. * printing exact math error causing this death.                     *
  64. *****************************************************************************/
  65. static void PerformMEAction(void)
  66. {
  67.     void (far *PFunc)();
  68.  
  69.     switch (MEAction) {
  70.     case ME_KILL:
  71. #        ifdef HAS_GRAPHICS
  72.         GGCloseGraph();            /* Close the graphic driver. */
  73. #        endif HAS_GRAPHICS
  74.         fprintf(stderr, "Fatal Math Error - %s\n", MathError);
  75.         MyExit(1);
  76.         break;
  77.     case ME_IGNORE:
  78.         break;
  79.     case ME_LONGJMP:
  80.         longjmp(*(((jmp_buf *) MEAddr)), 1);
  81.         break;
  82.     case ME_CALL:
  83.         PFunc = MEAddr;
  84.         (PFunc)();
  85.         break;
  86.     }
  87. }
  88.  
  89. /*****************************************************************************
  90. *   Routine that is called from the floating point package in case of fatal  *
  91. * floating point error. Print error message, long jump to main loop. Default *
  92. * FPE handler - must be reset after redirected to other module.             *
  93. *****************************************************************************/
  94. static void cdecl DefaultFPEHandler(int Sig, int Type, int *RegList)
  95. {
  96.     switch (Type) {
  97.     case FPE_INTOVFLOW:
  98.         MathError = "integer overflow";
  99.         break;
  100.     case FPE_INTDIV0:
  101.         MathError = "integer divide by zero";
  102.         break;
  103.     case FPE_INVALID:
  104.         MathError = "invalid operation";
  105.         break;
  106.     case FPE_ZERODIVIDE:
  107.         MathError = "division by zero";
  108.         break;
  109.     case FPE_OVERFLOW:
  110.         MathError = "numeric overflow";
  111.         break;
  112.     case FPE_UNDERFLOW:
  113.         MathError = "numeric underflow";
  114.         break;
  115.     case FPE_INEXACT:
  116.         MathError = "precision lost";
  117.         break;
  118.     case FPE_EXPLICITGEN:
  119.         MathError = "explicit signal";
  120.         break;
  121.     }
  122.     PerformMEAction();
  123. }
  124.  
  125. /*****************************************************************************
  126. * Routine to trap math errors -    set GlobalMathError to error number, and     *
  127. * GlobalMathFunc to the    math function with the error. Return TRUE to         *
  128. * make it believe that everything is ok. now...                     *
  129. *****************************************************************************/
  130. int cdecl matherr(struct exception _FAR *except)
  131. {
  132.     static char s[32];
  133.  
  134.     except -> retval = 1.0;           /* return something reasonable... */
  135.  
  136.     switch(except -> type) {
  137.     case DOMAIN:
  138.         strcpy(s, "DOMAIN ");
  139.         break;
  140.     case SING:
  141.         strcpy(s, "SING ");
  142.         break;
  143.     case OVERFLOW:
  144.         strcpy(s, "O.F. ");
  145.         break;
  146.     case UNDERFLOW:
  147.         strcpy(s, "U.F. ");
  148.         break;
  149.     case TLOSS:
  150.         strcpy(s, "TLOSS ");
  151.         break;
  152.     default:
  153.         strcpy(s, "Undef. ");
  154.         break;
  155.     }
  156.     strcat(s, "err, func. ");
  157.     strcat(s, except -> name);
  158.  
  159.     MathError = s;
  160.  
  161.     PerformMEAction();
  162.  
  163.     return TRUE;
  164. }
  165.  
  166.