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