home *** CD-ROM | disk | FTP | other *** search
/ Acorn User 11 / AUCD11B.iso / LANGUAGES / WraithSet / AwkStuff / MawkSrc / c / fpe_check < prev    next >
Encoding:
Text File  |  1996-08-29  |  4.5 KB  |  264 lines

  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. /* put this down here in attempt to defeat ambitious compiler that
  193.    may have seen a prototype without 2nd argument */
  194.    
  195. RETSIGTYPE fpe_catch(signal, why)
  196.    int signal ;
  197.    int why ;
  198. {
  199.    if (checking_for_strtod_ovf_bug) exit(1) ;
  200.    if ( may_be_safe_to_look_at_why ) why_v = why ;
  201.    longjmp(jbuff,1) ;
  202. }
  203.  
  204. char longstr[] =
  205. "1234567890\
  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.  
  246. #ifdef  USE_IEEEFP_H
  247. #include <ieeefp.h>
  248. #endif
  249.  
  250. void
  251. check_strtod_ovf()
  252. {
  253.     double x ; 
  254.  
  255. #ifdef USE_IEEEFP_H
  256.     fpsetmask(fpgetmask()|FP_X_OFL|FP_X_DZ) ;
  257. #endif
  258.  
  259.     checking_for_strtod_ovf_bug = 1 ;
  260.     strtod(longstr,(char**)0) ;
  261.     exit(0) ;
  262. }
  263.