home *** CD-ROM | disk | FTP | other *** search
/ Acorn User 11 / AUCD11B.iso / LANGUAGES / WraithSet / AwkStuff / MawkSrc / c / matherr < prev    next >
Text File  |  1996-09-01  |  5KB  |  278 lines

  1.  
  2. /********************************************
  3. matherr.c
  4. copyright 1991, Michael D. Brennan
  5.  
  6. This is a source file for mawk, an implementation of
  7. the AWK programming language.
  8.  
  9. Mawk is distributed without warranty under the terms of
  10. the GNU General Public License, version 2, 1991.
  11. ********************************************/
  12.  
  13. /*$Log: matherr.c,v $
  14.  *Revision 1.9  1996/09/01 16:54:35  mike
  15.  *Third try at bug fix for solaris strtod.
  16.  *
  17.  * Revision 1.6  1994/12/18  20:53:43  mike
  18.  * check NetBSD mathlib defines
  19.  *
  20.  * Revision 1.5  1994/12/14  14:48:57  mike
  21.  * add <siginfo.h> include -- sysV doesn't have it inside <signal.h>
  22.  * restore #else that had been removed
  23.  *
  24.  * Revision 1.4  1994/10/11  00:36:17  mike
  25.  * systemVr4 siginfo
  26.  *
  27.  * Revision 1.3  1993/07/17  13:23:04  mike
  28.  * indent and general code cleanup
  29.  *
  30.  * Revision 1.2     1993/07/04  12:52:03  mike
  31.  * start on autoconfig changes
  32.  *
  33.  * Revision 5.2     1992/03/31  16:14:44  brennan
  34.  * patch2:
  35.  * TURN_ON_FPE_TRAPS() macro
  36.  * USE_IEEEFP_H macro
  37.  *
  38.  * Revision 5.1     91/12/05  07:56:18  brennan
  39.  * 1.1 pre-release
  40.  *
  41. */
  42.  
  43. #include  "mawk.h"
  44. #include  <math.h>
  45.  
  46. /* Sets up NetBSD 1.0A for ieee floating point */
  47. #if defined(_LIB_VERSION_TYPE) && defined(_LIB_VERSION) && defined(_IEEE_)
  48. _LIB_VERSION_TYPE _LIB_VERSION = _IEEE_;
  49. #endif
  50.  
  51. #ifdef    USE_IEEEFP_H
  52. #include <ieeefp.h>
  53. #ifdef   HAVE_STRTOD_OVF_BUG
  54. static fp_except entry_mask ;
  55. static fp_except working_mask ;
  56. #endif
  57. #endif
  58.  
  59. #ifndef     TURN_OFF_FPE_TRAPS
  60. #define     TURN_OFF_FPE_TRAPS()    /* nothing */
  61. #endif
  62.  
  63. #ifndef     TURN_ON_FPE_TRAPS
  64. #define     TURN_ON_FPE_TRAPS()    /* nothing */
  65. #endif
  66.  
  67. #ifdef  SV_SIGINFO
  68. #include <siginfo.h>
  69. #define  FPE_ZERODIVIDE  FPE_FLTDIV
  70. #define  FPE_OVERFLOW    FPE_FLTOVF
  71. #endif
  72.  
  73. #ifdef     FPE_TRAPS_ON
  74. #include <signal.h>
  75.  
  76. /* machine dependent changes might be needed here */
  77.  
  78. #ifdef   SV_SIGINFO
  79. static void
  80. fpe_catch(signal, sip)
  81.    int signal; 
  82.    siginfo_t *sip ;
  83. {
  84.    int why = sip->si_code ;
  85.  
  86. #else
  87.  
  88. static void
  89. fpe_catch(signal, why)
  90.    int signal, why ;
  91. {
  92. #endif /* SV_SIGINFO  */
  93.  
  94. #if   NOINFO_SIGFPE
  95.    rt_error("floating point exception, probably overflow") ;
  96.    /* does not return */
  97. #else
  98.  
  99.    switch (why)
  100.    {
  101.       case FPE_ZERODIVIDE:
  102.      rt_error("division by zero") ;
  103.  
  104.       case FPE_OVERFLOW:
  105.      rt_error("floating point overflow") ;
  106.  
  107.       default:
  108.      rt_error("floating point exception") ;
  109.    }
  110. #endif /* noinfo_sigfpe */
  111. }
  112.  
  113. void
  114. fpe_init()
  115. {
  116.    TURN_ON_FPE_TRAPS() ;
  117.  
  118. #ifndef  SV_SIGINFO
  119.    signal(SIGFPE, fpe_catch) ;
  120.  
  121. #else
  122.    { struct sigaction x ;
  123.  
  124.      memset(&x, 0, sizeof(x)) ;
  125.      x.sa_handler = fpe_catch ;
  126.      x.sa_flags = SA_SIGINFO ;
  127.  
  128.      sigaction(SIGFPE, &x, (struct sigaction*)0) ;
  129.    }
  130. #endif
  131.  
  132. #ifdef  HAVE_STRTOD_OVF_BUG
  133.    /* we've already turned the traps on */
  134.    working_mask = fpgetmask() ;
  135.    entry_mask = working_mask & ~FP_X_DZ & ~FP_X_OFL ;
  136. #endif
  137. }
  138.  
  139. #else /* FPE_TRAPS not defined */
  140.  
  141. void
  142. fpe_init()
  143. {
  144.    TURN_OFF_FPE_TRAPS() ;
  145. }
  146. #endif
  147.  
  148. #ifndef     NO_MATHERR
  149.  
  150. #ifndef     FPE_TRAPS_ON
  151.  
  152. /* If we are not trapping math errors, we will shutup the library calls
  153. */
  154.  
  155. int
  156. matherr(e)
  157.    struct exception *e ;
  158. {
  159.    return 1 ;
  160. }
  161.  
  162. #else /* print error message and exit */
  163.  
  164. int
  165. matherr(e)
  166.    struct exception *e ;
  167. {
  168.    char *error ;
  169.  
  170.    switch (e->type)
  171.    {
  172.       case DOMAIN:
  173.       case SING:
  174.      error = "domain error" ;
  175.      break ;
  176.  
  177.       case OVERFLOW:
  178.      error = "overflow" ;
  179.      break ;
  180.  
  181.       case TLOSS:
  182.       case PLOSS:
  183.      error = "loss of significance" ;
  184.      break ;
  185.  
  186.       case UNDERFLOW:
  187.      e->retval = 0.0 ;
  188.      return 1 ;         /* ignore it */
  189.    }
  190.  
  191.    if (strcmp(e->name, "atan2") == 0)  rt_error("atan2(%g,%g) : %s",
  192.            e->arg1, e->arg2, error) ;
  193.    else     rt_error("%s(%g) : %s", e->name, e->arg1, error) ;
  194.  
  195.    /* won't get here */
  196.    return 0 ;
  197. }
  198. #endif /* FPE_TRAPS_ON */
  199.  
  200. #endif /*  ! no matherr */
  201.  
  202.  
  203. /* this is how one gets the libm calls to do the right
  204. thing on bsd43_vax
  205. */
  206.  
  207. #ifdef     BSD43_VAX
  208.  
  209. #include <errno.h>
  210.  
  211. double    infnan(arg)
  212.    int arg ;
  213. {
  214.    switch (arg)
  215.    {
  216.      case  ERANGE : errno = ERANGE ; return HUGE ;
  217.      case -ERANGE : errno = EDOM ; return -HUGE ;
  218.       default:
  219.      errno = EDOM ;
  220.    }
  221.    return 0.0 ;
  222. }
  223.  
  224. #endif /* BSD43_VAX */
  225.  
  226. /* This routine is for XENIX-68K 2.3A.
  227.     Error check routine to be called after fp arithmetic.
  228. */
  229.  
  230. #if SW_FP_CHECK
  231. /* Definitions of bit values in iserr() return value */
  232.  
  233. #define OVFLOW        2
  234. #define UFLOW        4
  235. #define ZERODIV        8
  236. #define OVFLFIX        32
  237. #define INFNAN        64
  238.  
  239. void
  240. fpcheck()
  241. {
  242.    register int fperrval ;
  243.    char *errdesc ;
  244.  
  245.    if ((fperrval = iserr()) == 0)
  246.       return ;             /* no error */
  247.  
  248.    errdesc = (char *) 0 ;
  249.  
  250.    if (fperrval & INFNAN)  errdesc = "arg is infinity or NAN" ;
  251.    else if (fperrval & ZERODIV)     errdesc = "division by zero" ;
  252.    else if (fperrval & OVFLOW)    errdesc = "overflow" ;
  253.    else if (fperrval & UFLOW) ; /* ignored */
  254.  
  255.    if (errdesc)     rt_error("%s", errdesc) ;
  256. }
  257.  
  258. #endif
  259.  
  260. #ifdef HAVE_STRTOD_OVF_BUG
  261. /* buggy strtod in solaris, probably any sysv with ieee754
  262.    strtod can generate an fpe  */
  263.  
  264. double
  265. strtod_with_ovf_bug(s, ep)
  266.    const char *s ;
  267.    char **ep ;
  268. {
  269.    double ret ;
  270.  
  271.    fpsetmask(entry_mask) ;  /* traps off */
  272. #undef strtod               /* make real strtod visible */
  273.    ret = strtod(s, ep) ;
  274.    fpsetmask(working_mask) ; /* traps on */
  275.    return ret ;
  276. }
  277. #endif
  278.