Commit | Line | Data |
---|---|---|
7eaaecf5 | 1 | /* -*-c-*- |
7eaaecf5 MW |
2 | * |
3 | * Generate limit MPs for C types | |
4 | * | |
5 | * (c) 2006 Straylight/Edgeware | |
6 | */ | |
7 | ||
45c0fd36 | 8 | /*----- Licensing notice --------------------------------------------------* |
7eaaecf5 MW |
9 | * |
10 | * This file is part of Catacomb. | |
11 | * | |
12 | * Catacomb is free software; you can redistribute it and/or modify | |
13 | * it under the terms of the GNU Library General Public License as | |
14 | * published by the Free Software Foundation; either version 2 of the | |
15 | * License, or (at your option) any later version. | |
45c0fd36 | 16 | * |
7eaaecf5 MW |
17 | * Catacomb is distributed in the hope that it will be useful, |
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 | * GNU Library General Public License for more details. | |
45c0fd36 | 21 | * |
7eaaecf5 MW |
22 | * You should have received a copy of the GNU Library General Public |
23 | * License along with Catacomb; if not, write to the Free | |
24 | * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, | |
25 | * MA 02111-1307, USA. | |
26 | */ | |
27 | ||
28 | /*----- Header files ------------------------------------------------------*/ | |
29 | ||
30 | #define _GNU_SOURCE | |
31 | #include <errno.h> | |
32 | #include <limits.h> | |
33 | #include <stdio.h> | |
34 | #include <string.h> | |
35 | ||
36 | #if __STDC_VERSION__ >= 199900l | |
37 | # include <stdint.h> | |
38 | # include <inttypes.h> | |
39 | #endif | |
40 | ||
41 | #include "mp.h" | |
42 | #include "mpint.h" | |
43 | ||
44 | /*----- Data types --------------------------------------------------------*/ | |
45 | ||
46 | /* --- Hack for GCC --- * | |
47 | * | |
48 | * WG14 in their infinite wisdom decided not to use the GCC constant name. | |
49 | */ | |
50 | ||
51 | #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 91) | |
52 | # define EXT __extension__ | |
53 | #else | |
54 | # define EXT | |
55 | #endif | |
56 | ||
57 | #if defined(LONG_LONG_MIN) && !defined(LLONG_MIN) | |
58 | # define LLONG_MIN EXT LONG_LONG_MIN | |
59 | #endif | |
60 | ||
61 | #if defined(LONG_LONG_MAX) && !defined(LLONG_MAX) | |
62 | # define LLONG_MAX EXT LONG_LONG_MAX | |
63 | #endif | |
64 | ||
65 | #if defined(ULONG_LONG_MAX) && !defined(ULLONG_MAX) | |
66 | # define ULLONG_MAX EXT ULONG_LONG_MAX | |
67 | #endif | |
68 | ||
69 | /* --- Choose the largest integer type --- */ | |
70 | ||
71 | #if defined(INTMAX_MAX) | |
72 | typedef intmax_t imax; | |
73 | #elif defined(LLONG_MAX) | |
74 | EXT typedef long long imax; | |
75 | #else | |
76 | typedef long imax; | |
77 | #endif | |
78 | ||
79 | #if defined(UINTMAX_MAX) | |
80 | typedef uintmax_t umax; | |
81 | #elif defined(ULLONG_MAX) | |
82 | EXT typedef unsigned long long umax; | |
83 | #else | |
84 | typedef unsigned long umax; | |
85 | #endif | |
86 | ||
87 | /*----- Main code ---------------------------------------------------------*/ | |
88 | ||
89 | #define TABSZ 64 | |
90 | ||
91 | enum { NEG, POS, NSIGN }; | |
92 | ||
93 | umax cmap[TABSZ]; | |
94 | int gmap[TABSZ][NSIGN]; | |
95 | struct { int g, s; } qmap[TABSZ]; | |
96 | int dumpp = 0; | |
97 | ||
98 | static int n, q; | |
99 | ||
100 | static void dump(mp *x) | |
101 | { | |
102 | int i, w, n; | |
103 | ||
104 | fputs(" ", stdout); | |
105 | w = (MPW_BITS + 3)/4; | |
106 | n = 1; | |
107 | while (2 + 2 * n * (4 + w) < 72) n <<= 1; | |
108 | i = 0; | |
109 | for (;;) { | |
110 | printf("0x%0*x", w, x->v[i]); | |
111 | i++; | |
112 | if (i >= MP_LEN(x)) break; | |
113 | fputs(",", stdout); | |
114 | if (i % n) fputs(" ", stdout); else fputs("\n ", stdout); | |
115 | } | |
116 | fputs("\n", stdout); | |
117 | } | |
118 | ||
119 | static void doemit(umax c, int s, int *gg, int *qq) | |
120 | { | |
121 | int i; | |
122 | mp *x = MP_NEW; | |
123 | ||
124 | for (i = 0; i < n; i++) { | |
125 | if (cmap[i] == c) | |
126 | goto found; | |
127 | } | |
128 | ||
129 | assert(i < TABSZ); | |
130 | n = i + 1; | |
131 | cmap[i] = c; | |
132 | gmap[i][POS] = gmap[i][NEG] = -1; | |
133 | if (dumpp) { | |
134 | MP_FROMINT(x, umax, c); | |
135 | printf("static mpw guts_%d[] = {\n", q); | |
136 | dump(x); | |
137 | fputs("};\n\n", stdout); | |
138 | MP_DROP(x); | |
139 | } | |
140 | ||
141 | found: | |
142 | *gg = i; | |
143 | if (gmap[i][s] < 0) { | |
144 | assert(q < TABSZ); | |
145 | gmap[i][s] = q; | |
146 | qmap[q].g = i; | |
147 | qmap[q].s = s; | |
148 | q++; | |
149 | } | |
150 | *qq = gmap[i][s]; | |
151 | } | |
152 | ||
153 | static void emit(imax c, int *gg, int *qq) | |
154 | { | |
155 | umax uc; | |
156 | int s; | |
157 | ||
158 | if (c >= 0) { uc = c; s = POS; } | |
159 | else { uc = -c; s = NEG; } | |
160 | doemit(uc, s, gg, qq); | |
161 | } | |
162 | ||
163 | static void uemit(umax c, int *gg, int *qq) { doemit(c, POS, gg, qq); } | |
164 | ||
165 | struct { | |
166 | const char *name; | |
167 | imax min; | |
168 | umax max; | |
169 | int gmin, gmax; | |
170 | int qmin, qmax; | |
171 | } tab[] = { | |
172 | { "SCHAR", SCHAR_MIN, SCHAR_MAX }, | |
173 | { "CHAR", CHAR_MIN, CHAR_MAX }, | |
174 | { "UCHAR", 0, UCHAR_MAX }, | |
175 | { "UINT8", 0, 0xff }, | |
176 | { "SHRT", SHRT_MIN, SHRT_MAX }, | |
177 | { "USHRT", 0, USHRT_MAX }, | |
178 | { "UINT16", 0, 0xffff }, | |
179 | { "INT", INT_MIN, INT_MAX }, | |
180 | { "UINT", 0, UINT_MAX }, | |
181 | { "LONG", LONG_MIN, LONG_MAX }, | |
182 | { "ULONG", 0, ULONG_MAX }, | |
183 | { "UINT32", 0, 0xffffffff }, | |
184 | #ifdef LLONG_MAX | |
185 | { "LLONG", LLONG_MIN, LLONG_MAX }, | |
186 | { "ULLONG", 0, ULLONG_MAX }, | |
187 | #endif | |
188 | { "SIZET", 0, ~(size_t)0 }, | |
189 | { 0 } | |
190 | }; | |
191 | ||
192 | static void dogen(void) | |
193 | { | |
194 | int i; | |
195 | ||
196 | for (i = 0; tab[i].name; i++) { | |
197 | if (tab[i].min) | |
198 | emit(tab[i].min, &tab[i].gmin, &tab[i].qmin); | |
199 | uemit(tab[i].max, &tab[i].gmax, &tab[i].qmax); | |
200 | } | |
201 | } | |
202 | ||
203 | static void cgen(void) | |
204 | { | |
205 | int i; | |
206 | ||
207 | fputs("\ | |
208 | /* -*-c-*-\n\ | |
209 | *\n\ | |
210 | * C integer limits [generated]\n\ | |
211 | */\n\ | |
212 | \n\ | |
213 | #include \"mplimits.h\"\n\ | |
214 | \n\ | |
215 | #define N(x) (sizeof(x)/sizeof(*x))\n\ | |
216 | #define MPpos(x) { x, x + N(x), N(x), 0, MP_CONST, 0 }\n\ | |
217 | #define MPneg(x) { x, x + N(x), N(x), 0, MP_CONST|MP_NEG, 0 }\n\ | |
218 | \n", | |
219 | stdout); | |
220 | dumpp = 1; | |
221 | dogen(); | |
222 | ||
223 | fputs("mp mp_limits[] = {\n", stdout); | |
224 | for (i = 0; i < q; i++) | |
225 | printf(" MP%s(guts_%d),\n", qmap[i].s ? "pos" : "neg", qmap[i].g); | |
226 | fputs("};\n", stdout); | |
227 | } | |
228 | ||
229 | static void hgen(void) | |
230 | { | |
231 | int i; | |
232 | ||
233 | fputs("\ | |
234 | /* -*-c-*-\n\ | |
235 | *\n\ | |
236 | * C integer limits [generated]\n\ | |
237 | */\n\ | |
238 | \n\ | |
239 | #ifndef CATACOMB_MPLIMITS_H\n\ | |
240 | #define CATACOMB_MPLIMITS_H\n\ | |
241 | \n\ | |
242 | #ifndef CATACOMB_MP_H\n\ | |
243 | # include \"mp.h\"\n\ | |
244 | #endif\n\ | |
245 | \n\ | |
246 | extern mp mp_limits[];\n\ | |
247 | \n", | |
248 | stdout); | |
249 | dogen(); | |
45c0fd36 | 250 | |
7eaaecf5 MW |
251 | for (i = 0; tab[i].name; i++) { |
252 | if (tab[i].min) { | |
253 | printf("#define MP_%s_MIN (&mp_limits[%d])\n", | |
254 | tab[i].name, gmap[tab[i].qmin][NEG]); | |
255 | } | |
256 | printf("#define MP_%s_MAX (&mp_limits[%d])\n", | |
257 | tab[i].name, gmap[tab[i].qmax][POS]); | |
258 | } | |
259 | fputs("\n#endif\n", stdout); | |
260 | } | |
261 | ||
262 | int main(int argc, char *argv[]) | |
263 | { | |
264 | const char *what = argc == 2 ? argv[1] : "<bogus>"; | |
265 | ||
266 | switch (what[0]) { | |
267 | case 'c': cgen(); break; | |
268 | case 'h': hgen(); break; | |
269 | default: | |
270 | fprintf(stderr, "unknown action `%s'\n", what); | |
271 | exit(1); | |
272 | } | |
273 | if (fflush(stdout) || fclose(stdout)) { | |
274 | fprintf(stderr, "error writing output: %s\n", strerror(errno)); | |
275 | exit(1); | |
276 | } | |
277 | return (0); | |
278 | } | |
279 | ||
280 | /*----- That's all, folks -------------------------------------------------*/ |