Tizen 2.1 base
[external/mawk.git] / fpe_check.c
1
2 /* This code attempts to figure out what the default
3    floating point exception handling does.
4 */
5
6 /* $Log: fpe_check.c,v $
7  * Revision 1.7  1996/08/30 00:07:14  mike
8  * Modifications to the test and implementation of the bug fix for
9  * solaris overflow in strtod.
10  *
11  * Revision 1.6  1996/08/25 19:25:46  mike
12  * Added test for solaris strtod overflow bug.
13  *
14  * Revision 1.5  1996/08/11 22:10:39  mike
15  * Some systems blow the !(d==d) test for a NAN.  Added a work around.
16  *
17  * Revision 1.4  1995/01/09  01:22:28  mike
18  * check sig handler ret type to make fpe_check.c more robust
19  *
20  * Revision 1.3  1994/12/18  20:54:00  mike
21  * check NetBSD mathlib defines
22  *
23  * Revision 1.2  1994/12/14  14:37:26  mike
24  * add messages to user
25  *
26 */
27
28 #include <setjmp.h>
29 #include <signal.h>
30 #include <math.h>
31
32 /* Sets up NetBSD 1.0A for ieee floating point */
33 #if defined(_LIB_VERSION_TYPE) && defined(_LIB_VERSION) && defined(_IEEE_)
34 _LIB_VERSION_TYPE _LIB_VERSION = _IEEE_;
35 #endif
36
37 void message(s)
38    char *s ;
39 {
40    printf("\t%s\n", s) ;
41 }
42
43 jmp_buf jbuff ;
44 int may_be_safe_to_look_at_why = 0 ;
45 int why_v ;
46 int checking_for_strtod_ovf_bug = 0 ;
47
48 RETSIGTYPE fpe_catch() ;
49 int is_nan() ;
50 void check_strtod_ovf() ;
51 double strtod() ;
52
53 double
54 div_by(x,y)
55    double x ;
56    double y ;
57 {
58    return x/y ;
59 }
60
61 double overflow(x)
62    double x ;
63 {
64    double y ;
65
66    do
67    {
68       y = x ;
69       x *= x ;
70    } while( y != x ) ;
71    return x ;
72 }
73
74    
75 void check_fpe_traps()
76 {
77    int traps = 0 ;
78
79    if (setjmp(jbuff) == 0)
80    {
81       div_by(44.0, 0.0) ;
82       message("division by zero does not generate an exception") ;
83    }
84    else
85    {
86       traps = 1 ;
87       message("division by zero generates an exception") ;
88       signal(SIGFPE, fpe_catch) ; /* set again if sysV */
89    }
90
91    if ( setjmp(jbuff) == 0 )
92    {
93       overflow(1000.0) ;
94       message("overflow does not generate an exception") ;
95    }
96    else
97    {
98       traps |= 2 ;
99       message("overflow generates an exception") ;
100       signal(SIGFPE, fpe_catch) ; 
101    }
102
103    if ( traps == 0 )
104    {
105       double maybe_nan = log(-8.0) ;
106
107       if (is_nan(maybe_nan))
108       {
109          message("math library supports ieee754") ;
110       }
111       else
112       {
113          traps |= 4 ;
114          message("math library does not support ieee754") ;
115       }
116    }
117
118    exit(traps) ;
119 }
120
121 int is_nan(d)
122    double d ;
123 {
124    char command[128] ;
125
126    if (!(d==d))  return 1 ;
127
128    /* on some systems with an ieee754 bug, we need to make another check */
129    sprintf(command, 
130            "echo '%f' | egrep '[nN][aA][nN]|\\?' >/dev/null", d) ; 
131    return system(command)==0 ;
132 }
133
134 /*
135 Only get here if we think we have Berkeley type signals so we can
136 look at a second argument to fpe_catch() to get the reason for
137 an exception
138 */
139 void
140 get_fpe_codes()  
141 {
142    int divz ;
143    int ovf ;
144
145    may_be_safe_to_look_at_why = 1 ;
146
147    if( setjmp(jbuff) == 0 ) div_by(1000.0, 0.0) ;
148    else  
149    {
150       divz = why_v ;
151       signal(SIGFPE, fpe_catch) ;
152    }
153
154    if( setjmp(jbuff) == 0 ) overflow(1000.0) ;
155    else  
156    {
157       ovf = why_v ;
158       signal(SIGFPE, fpe_catch) ;
159    }
160
161
162    /* make some guesses if sane values */
163    if ( divz>0 && ovf>0 && divz != ovf )
164    {
165       printf("X FPE_ZERODIVIDE %d\n", divz) ;
166       printf("X FPE_OVERFLOW %d\n", ovf) ;
167       exit(0) ;
168    }
169    else exit(1) ;
170 }
171
172 int
173 main(argc)
174    int argc ;
175 {
176
177    signal(SIGFPE, fpe_catch) ;
178    switch(argc) {
179       case 1 : 
180          check_fpe_traps() ;
181          break ;
182       case 2 : 
183          get_fpe_codes() ;
184          break ;
185       default: 
186          check_strtod_ovf() ;
187          break ;
188    }
189    /* not reached */
190    return 0 ;
191
192
193 /* put this down here in attempt to defeat ambitious compiler that
194    may have seen a prototype without 2nd argument */
195    
196 RETSIGTYPE fpe_catch(signal, why)
197    int signal ;
198    int why ;
199 {
200    if (checking_for_strtod_ovf_bug) exit(1) ;
201    if ( may_be_safe_to_look_at_why ) why_v = why ;
202    longjmp(jbuff,1) ;
203 }
204
205 char longstr[] =
206 "1234567890\
207 1234567890\
208 1234567890\
209 1234567890\
210 1234567890\
211 1234567890\
212 1234567890\
213 1234567890\
214 1234567890\
215 1234567890\
216 1234567890\
217 1234567890\
218 1234567890\
219 1234567890\
220 1234567890\
221 1234567890\
222 1234567890\
223 1234567890\
224 1234567890\
225 1234567890\
226 1234567890\
227 1234567890\
228 1234567890\
229 1234567890\
230 1234567890\
231 1234567890\
232 1234567890\
233 1234567890\
234 1234567890\
235 1234567890\
236 1234567890\
237 1234567890\
238 1234567890\
239 1234567890\
240 1234567890\
241 1234567890\
242 1234567890\
243 1234567890\
244 1234567890\
245 1234567890" ;
246
247 #ifdef  USE_IEEEFP_H
248 #include <ieeefp.h>
249 #endif
250
251 void
252 check_strtod_ovf()
253 {
254     double x ; 
255
256 #ifdef USE_IEEEFP_H
257     fpsetmask(fpgetmask()|FP_X_OFL|FP_X_DZ) ;
258 #endif
259
260     checking_for_strtod_ovf_bug = 1 ;
261     strtod(longstr,(char**)0) ;
262     exit(0) ;
263 }