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