math/gfreduce.[ch]: Fix out-of-bounds memory access.
[u/mdw/catacomb] / math / genlimits.c
CommitLineData
7eaaecf5
MW
1/* -*-c-*-
2 *
7eaaecf5
MW
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
91enum { NEG, POS, NSIGN };
92
93umax cmap[TABSZ];
94int gmap[TABSZ][NSIGN];
95struct { int g, s; } qmap[TABSZ];
96int dumpp = 0;
97
98static int n, q;
99
100static 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
119static 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
141found:
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
153static 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
163static void uemit(umax c, int *gg, int *qq) { doemit(c, POS, gg, qq); }
164
165struct {
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
192static 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
203static 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
229static 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\
246extern 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
262int 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 -------------------------------------------------*/