xref: /openbsd-src/regress/lib/libc/ieeefp/except/except.c (revision 996267948a0b9dfab1b68d3bac3b7b96fedbaac1)
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