Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / regress / lib / libc / ieeefp / except / except.c
blobf9062a0d020222d64711f0d61ad54a5f243f4a51
1 /* $NetBSD: except.c,v 1.10 2006/05/10 19:07:22 mrg Exp $ */
3 /*-
4 * Copyright (c) 1995 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
29 #include <stdio.h>
30 #include <signal.h>
31 #include <assert.h>
32 #include <ieeefp.h>
33 #include <float.h>
34 #include <setjmp.h>
35 #include <stdlib.h>
37 void sigfpe(int, siginfo_t *, void *);
38 volatile sig_atomic_t signal_caught;
39 volatile int sicode;
41 #ifdef USE_FLOAT
42 #define FPTYPE float
43 #else
44 #ifdef USE_LONGDOUBLE
45 #define FPTYPE long double
46 #else
47 #define FPTYPE double
48 #endif
49 #endif
50 static volatile const FPTYPE one = 1.0;
51 static volatile const FPTYPE zero = 0.0;
52 #ifdef USE_FLOAT
53 static volatile const float huge = FLT_MAX;
54 static volatile const float tiny = FLT_MIN;
55 #else
56 #ifdef USE_LONGDOUBLE
57 static volatile const long double huge = LDBL_MAX;
58 static volatile const long double tiny = LDBL_MIN;
59 #else
60 static volatile const double huge = DBL_MAX;
61 static volatile const double tiny = DBL_MIN;
62 #endif
63 #endif
64 static volatile FPTYPE x;
66 /* trip divide by zero */
67 static void
68 dz()
71 x = one / zero;
74 /* trip invalid operation */
75 static void
76 inv()
79 x = zero / zero;
82 /* trip overflow */
83 static void
84 ofl()
87 x = huge * huge;
90 /* trip underflow */
91 static void
92 ufl()
95 x = tiny * tiny;
98 static struct {
99 void (*op)(void);
100 fp_except mask;
101 int sicode;
102 } ops[] = {
103 { dz, FP_X_DZ, FPE_FLTDIV },
104 { inv, FP_X_INV, FPE_FLTINV },
105 { ofl, FP_X_OFL, FPE_FLTOVF },
106 { ufl, FP_X_UFL, FPE_FLTUND }
109 static sigjmp_buf b;
111 main()
113 struct sigaction sa;
114 fp_except ex1, ex2;
115 int i, r;
118 * check to make sure that all exceptions are masked and
119 * that the accumulated exception status is clear.
121 assert(fpgetmask() == 0);
122 assert(fpgetsticky() == 0);
124 /* set up signal handler */
125 sa.sa_sigaction = sigfpe;
126 sigemptyset(&sa.sa_mask);
127 sa.sa_flags = SA_SIGINFO;
128 sigaction(SIGFPE, &sa, 0);
129 signal_caught = 0;
132 * exceptions masked, check whether "sticky" bits are set correctly
134 for (i = 0; i < sizeof(ops)/sizeof(ops[0]); i++) {
135 (*ops[i].op)();
136 ex1 = fpgetsticky();
137 assert(ex1 & ops[i].mask);
138 assert(signal_caught == 0);
139 /* check correct fpsetsticky() behaviour */
140 ex2 = fpsetsticky(0);
141 assert(fpgetsticky() == 0);
142 assert(ex1 == ex2);
145 /* force delayed exceptions to be delivered */
146 #define BARRIER() fpsetmask(0); x = one * one
148 * exception unmasked, check SIGFPE delivery and correct siginfo
150 for (i = 0; i < sizeof(ops)/sizeof(ops[0]); i++) {
151 fpsetmask(ops[i].mask);
152 r = sigsetjmp(b, 1);
153 if (!r) {
154 (*ops[i].op)();
155 BARRIER();
157 assert(signal_caught == 1);
158 assert(sicode == ops[i].sicode);
159 signal_caught = 0;
162 exit(0);
165 void
166 sigfpe(int s, siginfo_t *si, void *c)
168 signal_caught = 1;
169 sicode = si->si_code;
170 siglongjmp(b, 1);