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