/********************************************
mawk_matherr.c
libmawk changes (C) 2009-2010, Tibor 'Igor2' Palinkas;
based on mawk code coming with the below copyright:
copyright 1991, Michael D. Brennan
This is a source file for mawk, an implementation of
the AWK programming language.
Mawk is distributed without warranty under the terms of
the GNU General Public License, version 2, 1991.
********************************************/
#include "mawk.h"
#include "num.h"
struct exception {
int dummy;
};
/* Sets up NetBSD 1.0A for ieee floating point */
#if defined(_LIB_VERSION_TYPE) && defined(_LIB_VERSION) && defined(_IEEE_)
_LIB_VERSION_TYPE _LIB_VERSION = _IEEE_;
#endif
#ifdef USE_IEEEFP_H
#include <ieeefp.h>
#endif
#ifndef TURN_OFF_FPE_TRAPS
#define TURN_OFF_FPE_TRAPS() /* nothing */
#endif
#ifndef TURN_ON_FPE_TRAPS
#define TURN_ON_FPE_TRAPS() /* nothing */
#endif
#ifdef SV_SIGINFO
#include <siginfo.h>
#define FPE_ZERODIVIDE FPE_FLTDIV
#define FPE_OVERFLOW FPE_FLTOVF
#endif
#ifdef FPE_TRAPS_ON
#include <signal.h>
/* machine dependent changes might be needed here */
#ifdef SV_SIGINFO
static void fpe_catch(int signal, siginfo_t *sip)
{
int why = sip->si_code;
#else
static void fpe_catch(int signal, int why)
{
#endif /* SV_SIGINFO */
#if NOINFO_SIGFPE
mawk_rt_error("floating point exception, probably mawk_overflow");
/* does not return */
#else
switch (why) {
case FPE_ZERODIVIDE:
mawk_rt_error("division by zero");
case FPE_OVERFLOW:
mawk_rt_error("floating point mawk_overflow");
default:
mawk_rt_error("floating point exception");
}
#endif /* noinfo_sigfpe */
}
void mawk_fpe_init(void)
{
return;
TURN_ON_FPE_TRAPS();
#ifndef SV_SIGINFO
signal(SIGFPE, fpe_catch);
#else
{
struct sigaction x;
memset(&x, 0, sizeof(x));
x.sa_handler = fpe_catch;
x.sa_flags = SA_SIGINFO;
sigaction(SIGFPE, &x, (struct sigaction *) 0);
}
#endif
#ifdef HAVE_STRTOD_OVF_BUG
/* we've already turned the traps on */
working_mask = fpgetmask();
MAWK->entry_mask = working_mask & ~FP_X_DZ & ~FP_X_OFL;
#endif
}
#else /* FPE_TRAPS not defined */
void mawk_fpe_init(void)
{
return;
TURN_OFF_FPE_TRAPS();
}
#endif
#ifndef NO_MATHERR
#ifndef FPE_TRAPS_ON
/* If we are not trapping math errors, we will shutup the library calls
*/
int mawk_matherr(struct exception *e)
{
return 1;
}
#else /* print error message and exit */
int mawk_matherr(struct exception *e)
{
char *error;
switch (e->type) {
case DOMAIN:
case SING:
error = "domain error";
break;
case OVERFLOW:
error = "mawk_overflow";
break;
case TLOSS:
case PLOSS:
error = "loss of significance";
break;
case UNDERFLOW:
e->retval = MAWK_NUM_ZERO;
return 1; /* ignore it */
}
if (strcmp(e->name, "atan2") == 0)
mawk_rt_error("atan2(%g,%g) : %s", e->arg1, e->arg2, error);
else
mawk_rt_error("%s(%g) : %s", e->name, e->arg1, error);
/* won't get here */
return 0;
}
#endif /* FPE_TRAPS_ON */
#endif /* ! no mawk_matherr */
/* this is how one gets the libm calls to do the right
thing on bsd43_vax */
#ifdef BSD43_VAX
#include <errno.h>
double infnan(int arg)
{
switch (arg) {
case ERANGE:
errno = ERANGE;
return HUGE;
case -ERANGE:
errno = EDOM;
return -HUGE;
default:
errno = EDOM;
}
return MAWK_NUM_ZERO;
}
#endif /* BSD43_VAX */
/* This routine is for XENIX-68K 2.3A.
Error check routine to be called after fp arithmetic.
*/
#if SW_FP_CHECK
/* Definitions of bit values in iserr() return value */
#define OVFLOW 2
#define UFLOW 4
#define ZERODIV 8
#define OVFLFIX 32
#define INFNAN 64
void fpcheck(void)
{
register int fperrval;
char *errdesc;
if ((fperrval = iserr()) == 0)
return; /* no error */
errdesc = (char *) 0;
if (fperrval & INFNAN)
errdesc = "arg is infinity or NAN";
else if (fperrval & ZERODIV)
errdesc = "division by zero";
else if (fperrval & OVFLOW)
errdesc = "mawk_overflow";
else if (fperrval & UFLOW); /* ignored */
if (errdesc)
mawk_rt_error("%s", errdesc);
}
#endif
#ifdef HAVE_STRTOD_OVF_BUG
/* buggy strtod in solaris, probably any sysv with ieee754
strtod can generate an fpe */
double strtod_with_ovf_bug(const char *s, char **ep)
{
double ret;
fpsetmask(MAWK->entry_mask); /* traps off */
#undef strtod /* make real strtod visible */
ret = strtod(s, ep);
fpsetmask(working_mask); /* traps on */
return ret;
}
#endif