1 /* Copyright (C) 2001-2006 Artifex Software, Inc.
2    All Rights Reserved.
3 
4    This software is provided AS-IS with no warranty, either express or
5    implied.
6 
7    This software is distributed under license and may not be copied, modified
8    or distributed except as expressly authorized under the terms of that
9    license.  Refer to licensing information at http://www.artifex.com/
10    or contact Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134,
11    San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
12 */
13 
14 /* $Id: genarch.c 8488 2008-01-17 13:37:19Z leonardo $ */
15 /*
16  * Generate a header file (arch.h) with parameters
17  * reflecting the machine architecture and compiler characteristics.
18  */
19 
20 #include "stdpre.h"
21 #include <ctype.h>
22 #include <stdio.h>
23 /*
24  * In theory, not all systems provide <string.h> or declare memset
25  * there, but at this point we don't think we care about any that don't.
26  */
27 #include <string.h>
28 #include <time.h>
29 
30 /* We provide a _SIZEOF_ macro for GX_COLOR_INDEX_TYPE
31    fallback to a generic int if no such type is defined.
32    This default must be kept in sync with the one in gxcindex.h
33    or ARCH_SIZEOF_GX_COLOR_INDEX will be incorrect for such builds. */
34 #ifndef GX_COLOR_INDEX_TYPE
35 #define GX_COLOR_INDEX_TYPE ulong
36 #endif
37 
38 /* We should write the result on stdout, but the original Turbo C 'make' */
39 /* can't handle output redirection (sigh). */
40 
41 static void
section(FILE * f,const char * str)42 section(FILE * f, const char *str)
43 {
44     fprintf(f, "\n\t /* ---------------- %s ---------------- */\n\n", str);
45 }
46 
47 static void
define(FILE * f,const char * str)48 define(FILE *f, const char *str)
49 {
50     fprintf(f, "#define %s ", str);
51 }
52 
53 static void
define_int(FILE * f,const char * str,int value)54 define_int(FILE *f, const char *str, int value)
55 {
56     fprintf(f, "#define %s %d\n", str, value);
57 }
58 
59 static void
print_ffs(FILE * f,int nbytes)60 print_ffs(FILE *f, int nbytes)
61 {
62     int i;
63 
64     for (i = 0; i < nbytes; ++i)
65 	fprintf(f, "ff");
66 }
67 
68 static int
ilog2(int n)69 ilog2(int n)
70 {
71     int i = 0, m = n;
72 
73     while (m > 1)
74 	++i, m = (m + 1) >> 1;
75     return i;
76 }
77 
78 int
main(int argc,char * argv[])79 main(int argc, char *argv[])
80 {
81     char *fname = argv[1];
82     long one = 1;
83     struct {
84 	char c;
85 	short s;
86     } ss;
87     struct {
88 	char c;
89 	int i;
90     } si;
91     struct {
92 	char c;
93 	long l;
94     } sl;
95     struct {
96 	char c;
97 	char *p;
98     } sp;
99     struct {
100 	char c;
101 	float f;
102     } sf;
103     struct {
104 	char c;
105 	double d;
106     } sd;
107     long lm1 = -1;
108     long lr1 = lm1 >> 1, lr2 = lm1 >> 2;
109     int im1 = -1;
110     int ir1 = im1 >> 1, ir2 = im1 >> 2;
111     union {
112 	long l;
113 	char *p;
114     } pl0, pl1;
115     int ars;
116     union {
117 	float f;
118 	int i;
119 	long l;
120     } f0, f1, fm1;
121     int floats_are_IEEE;
122     FILE *f = fopen(fname, "w");
123 
124     if (f == NULL) {
125 	fprintf(stderr, "genarch.c: can't open %s for writing\n", fname);
126 	return exit_FAILED;
127     }
128     fprintf(f, "/* Parameters derived from machine and compiler architecture. */\n");
129     fprintf(f, "/* This file is generated mechanically by genarch.c. */\n");
130 
131     /* We have to test the size dynamically here, */
132     /* because the preprocessor can't evaluate sizeof. */
133     f0.f = 0.0, f1.f = 1.0, fm1.f = -1.0;
134     floats_are_IEEE =
135 	(size_of(float) == size_of(int) ?
136 	 f0.i == 0 && f1.i == (int)0x3f800000 && fm1.i == (int)0xbf800000 :
137 	 f0.l == 0 && f1.l == 0x3f800000L && fm1.l == 0xbf800000L);
138 
139     section(f, "Scalar alignments");
140 
141 #define OFFSET_IN(s, e) (int)((char *)&s.e - (char *)&s)
142     define_int(f, "ARCH_ALIGN_SHORT_MOD", OFFSET_IN(ss, s));
143     define_int(f, "ARCH_ALIGN_INT_MOD", OFFSET_IN(si, i));
144     define_int(f, "ARCH_ALIGN_LONG_MOD", OFFSET_IN(sl, l));
145     define_int(f, "ARCH_ALIGN_PTR_MOD", OFFSET_IN(sp, p));
146     define_int(f, "ARCH_ALIGN_FLOAT_MOD", OFFSET_IN(sf, f));
147     define_int(f, "ARCH_ALIGN_DOUBLE_MOD", OFFSET_IN(sd, d));
148 #undef OFFSET_IN
149 
150     /* Some architectures have special alignment requirements for   */
151     /* jmp_buf, and we used to provide ALIGN_STRUCT_MOD for that.   */
152     /* We've now dropped that in favor of aligning jmp_buf by hand. */
153     /* See setjmp_.h for the implementation of this.                */
154 
155     section(f, "Scalar sizes");
156 
157     define_int(f, "ARCH_LOG2_SIZEOF_CHAR", ilog2(size_of(char)));
158     define_int(f, "ARCH_LOG2_SIZEOF_SHORT", ilog2(size_of(short)));
159     define_int(f, "ARCH_LOG2_SIZEOF_INT", ilog2(size_of(int)));
160     define_int(f, "ARCH_LOG2_SIZEOF_LONG", ilog2(size_of(long)));
161 #if !defined(_MSC_VER) && ! (defined(__BORLANDC__) && defined(__WIN32__))
162     /* MSVC does not provide 'long long' but we need this on some archs
163        to define a 64 bit type. A corresponding #ifdef in stdint_.h handles
164        that case for MSVC. Most other platforms do support long long if
165        they have a 64 bit type at all */
166     define_int(f, "ARCH_LOG2_SIZEOF_LONG_LONG", ilog2(size_of(long long)));
167 #endif
168     define_int(f, "ARCH_SIZEOF_GX_COLOR_INDEX", sizeof(GX_COLOR_INDEX_TYPE));
169     define_int(f, "ARCH_SIZEOF_PTR", size_of(char *));
170     define_int(f, "ARCH_SIZEOF_FLOAT", size_of(float));
171     define_int(f, "ARCH_SIZEOF_DOUBLE", size_of(double));
172     if (floats_are_IEEE) {
173 	define_int(f, "ARCH_FLOAT_MANTISSA_BITS", 24);
174 	define_int(f, "ARCH_DOUBLE_MANTISSA_BITS", 53);
175     } else {
176 	/*
177 	 * There isn't any general way to compute the number of mantissa
178 	 * bits accurately, especially if the machine uses hex rather
179 	 * than binary exponents.  Use conservative values, assuming
180 	 * the exponent is stored in a 16-bit word of its own.
181 	 */
182 	define_int(f, "ARCH_FLOAT_MANTISSA_BITS", sizeof(float) * 8 - 17);
183 	define_int(f, "ARCH_DOUBLE_MANTISSA_BITS", sizeof(double) * 8 - 17);
184     }
185 
186     section(f, "Unsigned max values");
187 
188     /*
189      * We can't use fprintf with a numeric value for PRINT_MAX, because
190      * too many compilers produce warnings or do the wrong thing for
191      * complementing or widening unsigned types.
192      */
193 #define PRINT_MAX(str, typ, tstr, l)\
194   BEGIN\
195     define(f, str);\
196     fprintf(f, "((%s)0x", tstr);\
197     print_ffs(f, sizeof(typ));\
198     fprintf(f, "%s + (%s)0)\n", l, tstr);\
199   END
200     PRINT_MAX("ARCH_MAX_UCHAR", unsigned char, "unsigned char", "");
201     PRINT_MAX("ARCH_MAX_USHORT", unsigned short, "unsigned short", "");
202     /*
203      * For uint and ulong, a different approach is required to keep gcc
204      * with -Wtraditional from spewing out pointless warnings.
205      */
206     define(f, "ARCH_MAX_UINT");
207     fprintf(f, "((unsigned int)~0 + (unsigned int)0)\n");
208     define(f, "ARCH_MAX_ULONG");
209     fprintf(f, "((unsigned long)~0L + (unsigned long)0)\n");
210 #undef PRINT_MAX
211 
212     section(f, "Miscellaneous");
213 
214     define_int(f, "ARCH_IS_BIG_ENDIAN", 1 - *(char *)&one);
215     pl0.l = 0;
216     pl1.l = -1;
217     define_int(f, "ARCH_PTRS_ARE_SIGNED", (pl1.p < pl0.p));
218     define_int(f, "ARCH_FLOATS_ARE_IEEE", (floats_are_IEEE ? 1 : 0));
219 
220     /*
221      * There are three cases for arithmetic right shift:
222      * always correct, correct except for right-shifting a long by 1
223      * (a bug in some versions of the Turbo C compiler), and
224      * never correct.
225      */
226     ars = (lr2 != -1 || ir1 != -1 || ir2 != -1 ? 0 :
227 	   lr1 != -1 ? 1 :	/* Turbo C problem */
228 	   2);
229     define_int(f, "ARCH_ARITH_RSHIFT", ars);
230     /*
231      * Determine whether dividing a negative integer by a positive one
232      * takes the floor or truncates toward zero.
233      */
234     define_int(f, "ARCH_DIV_NEG_POS_TRUNCATES", im1 / 2 == 0);
235 
236 /* ---------------- Done. ---------------- */
237 
238     fclose(f);
239     return exit_OK;
240 }
241