1 /* $NetBSD: arithchk.c,v 1.4 2012/06/24 15:26:03 christos Exp $ */
2 
3 /****************************************************************
4 Copyright (C) 1997, 1998 Lucent Technologies
5 All Rights Reserved
6 
7 Permission to use, copy, modify, and distribute this software and
8 its documentation for any purpose and without fee is hereby
9 granted, provided that the above copyright notice appear in all
10 copies and that both that the copyright notice and this
11 permission notice and warranty disclaimer appear in supporting
12 documentation, and that the name of Lucent or any of its entities
13 not be used in advertising or publicity pertaining to
14 distribution of the software without specific, written prior
15 permission.
16 
17 LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
19 IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
20 SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
21 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
22 IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
23 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
24 THIS SOFTWARE.
25 ****************************************************************/
26 
27 /* Try to deduce arith.h from arithmetic properties. */
28 
29 #include <stdio.h>
30 
31 static int dalign;
32 typedef struct
33 Akind {
34           char *name;
35           int   kind;
36           } Akind;
37 
38 static Akind
39 IEEE_LITTLE_ENDIAN  = { "IEEE_LITTLE_ENDIAN", 1 },
40 IEEE_BIG_ENDIAN               = { "IEEE_BIG_ENDIAN", 2 },
41 IBM                           = { "IBM", 3 },
42 VAX                           = { "VAX", 4 },
43 CRAY                          = { "CRAY", 5};
44 
45 static Akind *
Lcheck(void)46 Lcheck(void)
47 {
48           union {
49                     double d;
50                     long L[2];
51                     } u;
52           struct {
53                     double d;
54                     long L;
55                     } x[2];
56 
57           if (sizeof(x) > 2*(sizeof(double) + sizeof(long)))
58                     dalign = 1;
59           u.L[0] = u.L[1] = 0;
60           u.d = 1e13;
61           if (u.L[0] == 1117925532 && u.L[1] == -448790528)
62                     return &IEEE_BIG_ENDIAN;
63           if (u.L[1] == 1117925532 && u.L[0] == -448790528)
64                     return &IEEE_LITTLE_ENDIAN;
65           if (u.L[0] == -2065213935 && u.L[1] == 10752)
66                     return &VAX;
67           if (u.L[0] == 1267827943 && u.L[1] == 704643072)
68                     return &IBM;
69           return 0;
70           }
71 
72 static Akind *
icheck(void)73 icheck(void)
74 {
75           union {
76                     double d;
77                     int L[2];
78                     } u;
79           struct {
80                     double d;
81                     int L;
82                     } x[2];
83 
84           if (sizeof(x) > 2*(sizeof(double) + sizeof(int)))
85                     dalign = 1;
86           u.L[0] = u.L[1] = 0;
87           u.d = 1e13;
88           if (u.L[0] == 1117925532 && u.L[1] == -448790528)
89                     return &IEEE_BIG_ENDIAN;
90           if (u.L[1] == 1117925532 && u.L[0] == -448790528)
91                     return &IEEE_LITTLE_ENDIAN;
92           if (u.L[0] == -2065213935 && u.L[1] == 10752)
93                     return &VAX;
94           if (u.L[0] == 1267827943 && u.L[1] == 704643072)
95                     return &IBM;
96           return 0;
97           }
98 
99 char *emptyfmt = "";          /* avoid possible warning message with printf("") */
100 
101 static Akind *
ccheck(void)102 ccheck(void)
103 {
104           union {
105                     double d;
106                     long L;
107                     } u;
108           long Cray1;
109 
110           /* Cray1 = 4617762693716115456 -- without overflow on non-Crays */
111           Cray1 = printf(emptyfmt) < 0 ? 0 : 4617762;
112           if (printf(emptyfmt, Cray1) >= 0)
113                     Cray1 = 1000000*Cray1 + 693716;
114           if (printf(emptyfmt, Cray1) >= 0)
115                     Cray1 = 1000000*Cray1 + 115456;
116           u.d = 1e13;
117           if (u.L == Cray1)
118                     return &CRAY;
119           return 0;
120           }
121 
122 static int
fzcheck(void)123 fzcheck(void)
124 {
125           double a, b;
126           int i;
127 
128           a = 1.;
129           b = .1;
130           for(i = 155;; b *= b, i >>= 1) {
131                     if (i & 1) {
132                               a *= b;
133                               if (i == 1)
134                                         break;
135                               }
136                     }
137           b = a * a;
138           return b == 0.;
139           }
140 
141 int
main(void)142 main(void)
143 {
144           Akind *a = 0;
145           int Ldef = 0;
146           FILE *f;
147 
148 #ifdef WRITE_ARITH_H          /* for Symantec's buggy "make" */
149           f = fopen("arith.h", "w");
150           if (!f) {
151                     printf("Cannot open arith.h\n");
152                     return 1;
153                     }
154 #else
155           f = stdout;
156 #endif
157 
158           if (sizeof(double) == 2*sizeof(long))
159                     a = Lcheck();
160           else if (sizeof(double) == 2*sizeof(int)) {
161                     Ldef = 1;
162                     a = icheck();
163                     }
164           else if (sizeof(double) == sizeof(long))
165                     a = ccheck();
166           if (a) {
167                     fprintf(f, "#define %s\n#define Arith_Kind_ASL %d\n",
168                               a->name, a->kind);
169                     if (Ldef)
170                               fprintf(f, "#define Long int\n#define Intcast (int)(long)\n");
171                     if (dalign)
172                               fprintf(f, "#define Double_Align\n");
173                     if (sizeof(char*) == 8)
174                               fprintf(f, "#define X64_bit_pointers\n");
175 #ifndef NO_LONG_LONG
176                     if (sizeof(long long) < 8)
177 #endif
178                               fprintf(f, "#define NO_LONG_LONG\n");
179                     if (a->kind <= 2 && fzcheck())
180                               fprintf(f, "#define Sudden_Underflow\n");
181 #ifdef WRITE_ARITH_H
182                     fclose(f);
183 #endif
184                     return 0;
185                     }
186           fprintf(f, "/* Unknown arithmetic */\n");
187 #ifdef WRITE_ARITH_H
188           fclose(f);
189 #endif
190           return 1;
191           }
192