xref: /minix3/lib/libc/gdtoa/arithchk.c (revision f14fb602092e015ff630df58e17c2a9cd57d29b3)
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