Git init
[external/mawk.git] / matherr.c
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