Build `mptypes.h' header file appropriately for the current
[u/mdw/catacomb] / mptypes.c
1 /* -*-c-*-
2 *
3 * Program to find appropriate types for multiprecision integer stuff.
4 */
5
6 #define _GNU_SOURCE
7 #include <stdio.h>
8 #include <limits.h>
9 #if __STDC_VERSION__ >= 199900l
10 # include <stdint.h>
11 #endif
12
13 /* --- Hack for GCC --- *
14 *
15 * WG14 in their infinite wisdom decided not to use the GCC constant name.
16 */
17
18 #if defined(ULONG_LONG_MAX) && !defined(ULLONG_MAX)
19 # define ULLONG_MAX ULONG_LONG_MAX
20 #endif
21
22 /* --- Choose the largest integer type --- */
23
24 #if defined(UINTMAX_MAX)
25 typedef uintmax_t umax;
26 # define P_UMAX PRIuMAX
27 #elif defined(ULLONG_MAX)
28 typedef unsigned long long umax;
29 # define P_UMAX "%llu"
30 #else
31 typedef unsigned long umax;
32 # define P_UMAX "%lu"
33 #endif
34
35 /* --- Table of interesting types --- *
36 *
37 * These are in preference order.
38 */
39
40 enum {
41 f_stdint
42 };
43
44 struct itype {
45 const char *name;
46 umax max;
47 unsigned flags;
48 unsigned bits;
49 } tytab[] = {
50 { "unsigned int", UINT_MAX, 0 },
51 { "unsigned short", USHRT_MAX, 0 },
52 { "unsigned long", ULONG_MAX, 0 },
53 #ifdef ULLONG_MAX
54 { "unsigned long long", ULLONG_MAX, 0 },
55 #endif
56 #ifdef UINTMAX_MAX
57 { "uintmax_t", UINTMAX_MAX, f_stdint },
58 #endif
59 { 0, 0 },
60 };
61
62 typedef struct itype itype;
63
64 /* --- Main program --- */
65
66 int main(int argc, char *argv[])
67 {
68 itype *i;
69 itype *largest, *mpw, *mpd;
70
71 /* --- Find the bitcounts --- */
72
73 for (i = tytab; i->name; i++) {
74 unsigned bits;
75 umax u = i->max;
76 for (bits = 0; u; bits++)
77 u >>= 1;
78 i->bits = bits;
79 }
80
81 /* --- Now try to find the interesting types --- *
82 *
83 * The first thing to do is to find the largest type. Then I find the
84 * `best' type which is less than half that size, and then the `best' type
85 * which is twice as big as that one.
86 */
87
88 largest = tytab;
89 for (i = tytab; i->name; i++) {
90 if (i->bits > largest->bits)
91 largest = i;
92 }
93 for (mpw = 0, i = tytab; i->name; i++) {
94 if (i->bits * 2 <= largest->bits && (!mpw || i->bits > mpw->bits))
95 mpw = i;
96 }
97 if (!mpw)
98 mpw = tytab;
99 for (mpd = 0, i = tytab; i->name; i++) {
100 if (i->bits >= mpw->bits * 2 && (!mpd || i->bits < mpd->bits))
101 mpd = i;
102 }
103 if (!mpd) {
104 static itype w, d;
105 d = w = *mpw;
106 w.bits /= 2; w.max = ~(~((umax)0) << w.bits);
107 d.bits = w.bits * 2; d.max = ~(~((umax)0) << d.bits);
108 mpw = &w; mpd = &d;
109 }
110
111 /* --- Output time --- */
112
113 puts("\
114 /* -*-c-*-\n\
115 *\n\
116 * mptypes.h [generated]\n\
117 */\n\
118 \n\
119 #ifndef MPTYPES_H\n\
120 #define MPTYPES_H\n\
121 ");
122 if ((mpd->flags | mpw->flags) & f_stdint) {
123 puts("\
124 #if __STDC_VERSION__ >= 199900l\n\
125 # include <stdint.h>\n\
126 #endif\n\
127 ");
128 }
129 printf("\
130 typedef %s mpw;\n\
131 #define MPW_BITS %u\n\
132 #define MPW_MAX " P_UMAX "\n\
133 \n\
134 typedef %s mpd;\n\
135 #define MPD_BITS %u\n\
136 #define MPD_MAX " P_UMAX "\n\
137 \n\
138 #endif\n\
139 ",
140 mpw->name, mpw->bits, mpw->max,
141 mpd->name, mpd->bits, mpd->max);
142
143 return (0);
144 }