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