1 /* $OpenBSD: except.c,v 1.7 2004/07/22 19:29:42 kettenis Exp $ */ 2 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <signal.h> 6 #include <assert.h> 7 #include <ieeefp.h> 8 #include <float.h> 9 #include <err.h> 10 11 volatile int signal_status; 12 13 volatile const double one = 1.0; 14 volatile const double zero = 0.0; 15 volatile const double huge = DBL_MAX; 16 volatile const double tiny = DBL_MIN; 17 18 void 19 sigfpe(int sig, siginfo_t *si, void *v) 20 { 21 char buf[132]; 22 23 if (si) { 24 snprintf(buf, sizeof(buf), "sigfpe: addr=%p, code=%d\n", 25 si->si_addr, si->si_code); 26 write(1, buf, strlen(buf)); 27 } 28 _exit(signal_status); 29 } 30 31 32 int 33 main(int argc, char *argv[]) 34 { 35 struct sigaction sa; 36 volatile double x; 37 38 if (argc != 2) { 39 fprintf(stderr, "usage: %s condition\n", argv[0]); 40 exit(1); 41 } 42 43 /* 44 * check to make sure that all exceptions are masked and 45 * that the accumulated exception status is clear. 46 */ 47 assert(fpgetmask() == 0); 48 assert(fpgetsticky() == 0); 49 50 memset(&sa, 0, sizeof(sa)); 51 sa.sa_sigaction = sigfpe; 52 sa.sa_flags = SA_SIGINFO; 53 sigaction(SIGFPE, &sa, NULL); 54 signal_status = 1; 55 56 /* trip divide by zero */ 57 x = one / zero; 58 assert(fpgetsticky() & FP_X_DZ); 59 fpsetsticky(0); 60 61 /* trip invalid operation */ 62 x = zero / zero; 63 assert(fpgetsticky() & FP_X_INV); 64 fpsetsticky(0); 65 66 /* trip overflow */ 67 x = huge * huge; 68 assert(fpgetsticky() & FP_X_OFL); 69 fpsetsticky(0); 70 71 /* trip underflow */ 72 x = tiny * tiny; 73 assert(fpgetsticky() & FP_X_UFL); 74 fpsetsticky(0); 75 76 signal_status = 0; 77 78 if (strcmp(argv[1], "fltdiv") == 0) { 79 /* unmask and then trip divide by zero */ 80 fpsetmask(FP_X_DZ); 81 x = one / zero; 82 } else if (strcmp(argv[1], "fltinv") == 0) { 83 /* unmask and then trip invalid operation */ 84 fpsetmask(FP_X_INV); 85 x = zero / zero; 86 } else if (strcmp(argv[1], "fltovf") == 0) { 87 /* unmask and then trip overflow */ 88 fpsetmask(FP_X_OFL); 89 x = huge * huge; 90 } else if (strcmp(argv[1], "fltund") == 0) { 91 /* unmask and then trip underflow */ 92 fpsetmask(FP_X_UFL); 93 x = tiny * tiny; 94 } else { 95 errx(1, "unrecognized condition %s", argv[1]); 96 } 97 98 errx(1, "signal wasn't caught"); 99 } 100