xref: /openbsd-src/regress/lib/libc/ieeefp/except/except.c (revision cd1eb269cafb12c415be1749cd4a4b5422710415)
1*cd1eb269Snaddy /*	$OpenBSD: except.c,v 1.12 2010/05/08 19:16:33 naddy Exp $	*/
2133306f0Sniklas 
3306c0413Sdavid #include <sys/types.h>
4306c0413Sdavid #include <unistd.h>
5df930be7Sderaadt #include <stdio.h>
61821443cSdavid #include <stdlib.h>
7*cd1eb269Snaddy #include <string.h>
8df930be7Sderaadt #include <signal.h>
9df930be7Sderaadt #include <assert.h>
10df930be7Sderaadt #include <ieeefp.h>
11df930be7Sderaadt #include <float.h>
1299626794Skettenis #include <err.h>
13df930be7Sderaadt 
147e796478Smickey volatile sig_atomic_t signal_status;
15df930be7Sderaadt 
16350c519bSmickey volatile const double one  = 1.0;
17350c519bSmickey volatile const double zero = 0.0;
18350c519bSmickey volatile const double huge = DBL_MAX;
19350c519bSmickey volatile const double tiny = DBL_MIN;
20df930be7Sderaadt 
21350c519bSmickey void
sigfpe(int sig,siginfo_t * si,void * v)22350c519bSmickey sigfpe(int sig, siginfo_t *si, void *v)
23db3296cfSderaadt {
24350c519bSmickey 	char buf[132];
25350c519bSmickey 
26350c519bSmickey 	if (si) {
27350c519bSmickey 		snprintf(buf, sizeof(buf), "sigfpe: addr=%p, code=%d\n",
28350c519bSmickey 		    si->si_addr, si->si_code);
29350c519bSmickey 		write(1, buf, strlen(buf));
30db3296cfSderaadt 	}
3199626794Skettenis 	_exit(signal_status);
32350c519bSmickey }
33350c519bSmickey 
34db3296cfSderaadt 
3507ea8d15Smillert int
main(int argc,char * argv[])36db3296cfSderaadt main(int argc, char *argv[])
37df930be7Sderaadt {
38350c519bSmickey 	struct sigaction sa;
39df930be7Sderaadt 	volatile double x;
40df930be7Sderaadt 
4199626794Skettenis 	if (argc != 2) {
4299626794Skettenis 		fprintf(stderr, "usage: %s condition\n", argv[0]);
4399626794Skettenis 		exit(1);
4499626794Skettenis 	}
4599626794Skettenis 
46df930be7Sderaadt 	/*
47df930be7Sderaadt 	 * check to make sure that all exceptions are masked and
48df930be7Sderaadt 	 * that the accumulated exception status is clear.
49df930be7Sderaadt  	 */
50df930be7Sderaadt 	assert(fpgetmask() == 0);
51df930be7Sderaadt 	assert(fpgetsticky() == 0);
52df930be7Sderaadt 
53350c519bSmickey 	memset(&sa, 0, sizeof(sa));
54350c519bSmickey 	sa.sa_sigaction = sigfpe;
55350c519bSmickey 	sa.sa_flags = SA_SIGINFO;
56350c519bSmickey 	sigaction(SIGFPE, &sa, NULL);
5799626794Skettenis 	signal_status = 1;
58df930be7Sderaadt 
59a359bea4Smiod 	if (strcmp(argv[1], "fltdiv") == 0) {
60df930be7Sderaadt 		/* trip divide by zero */
61df930be7Sderaadt 		x = one / zero;
62df930be7Sderaadt 		assert(fpgetsticky() & FP_X_DZ);
63df930be7Sderaadt 		fpsetsticky(0);
64df930be7Sderaadt 
65a359bea4Smiod 		/* and now unmask to get a signal */
66a359bea4Smiod 		signal_status = 0;
67a359bea4Smiod 		fpsetmask(FP_X_DZ);
68a359bea4Smiod 		x = one / zero;
69a359bea4Smiod 	} else if (strcmp(argv[1], "fltinv") == 0) {
70df930be7Sderaadt 		/* trip invalid operation */
71df930be7Sderaadt 		x = zero / zero;
72df930be7Sderaadt 		assert(fpgetsticky() & FP_X_INV);
73df930be7Sderaadt 		fpsetsticky(0);
74df930be7Sderaadt 
75a359bea4Smiod 		/* and now unmask to get a signal */
76a359bea4Smiod 		signal_status = 0;
77a359bea4Smiod 		fpsetmask(FP_X_INV);
78a359bea4Smiod 		x = zero / zero;
79a359bea4Smiod 	} else if (strcmp(argv[1], "fltovf") == 0) {
80df930be7Sderaadt 		/* trip overflow */
81df930be7Sderaadt 		x = huge * huge;
82df930be7Sderaadt 		assert(fpgetsticky() & FP_X_OFL);
83df930be7Sderaadt 		fpsetsticky(0);
84df930be7Sderaadt 
85a359bea4Smiod 		/* and now unmask to get a signal */
86a359bea4Smiod 		signal_status = 0;
87a359bea4Smiod 		fpsetmask(FP_X_OFL);
88a359bea4Smiod 		x = huge * huge;
89a359bea4Smiod 	} else if (strcmp(argv[1], "fltund") == 0) {
90df930be7Sderaadt 		/* trip underflow */
91df930be7Sderaadt 		x = tiny * tiny;
92df930be7Sderaadt 		assert(fpgetsticky() & FP_X_UFL);
93df930be7Sderaadt 		fpsetsticky(0);
94df930be7Sderaadt 
95a359bea4Smiod 		/* and now unmask to get a signal */
9699626794Skettenis 		signal_status = 0;
97df930be7Sderaadt 		fpsetmask(FP_X_UFL);
98df930be7Sderaadt 		x = tiny * tiny;
9999626794Skettenis 	} else {
10099626794Skettenis 		errx(1, "unrecognized condition %s", argv[1]);
101df930be7Sderaadt 	}
102df930be7Sderaadt 
103d3e4cc37Skettenis 	/*
104d3e4cc37Skettenis 	 * attempt to trigger the exception on machines where
105d3e4cc37Skettenis 	 * floating-point exceptions are deferred.
106d3e4cc37Skettenis 	 */
107d3e4cc37Skettenis 	x = one * one;
108d3e4cc37Skettenis 
10999626794Skettenis 	errx(1, "signal wasn't caught");
11099626794Skettenis }
111