-/* -*-c-*-
- *
- * Generate limit MPs for C types
- *
- * (c) 2006 Straylight/Edgeware
- */
-
-/*----- Licensing notice --------------------------------------------------*
- *
- * This file is part of Catacomb.
- *
- * Catacomb is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Library General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * Catacomb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with Catacomb; if not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#define _GNU_SOURCE
-#include <errno.h>
-#include <limits.h>
-#include <stdio.h>
-#include <string.h>
-
-#if __STDC_VERSION__ >= 199900l
-# include <stdint.h>
-# include <inttypes.h>
-#endif
-
-#include "mp.h"
-#include "mpint.h"
-
-/*----- Data types --------------------------------------------------------*/
-
-/* --- Hack for GCC --- *
- *
- * WG14 in their infinite wisdom decided not to use the GCC constant name.
- */
-
-#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 91)
-# define EXT __extension__
-#else
-# define EXT
-#endif
-
-#if defined(LONG_LONG_MIN) && !defined(LLONG_MIN)
-# define LLONG_MIN EXT LONG_LONG_MIN
-#endif
-
-#if defined(LONG_LONG_MAX) && !defined(LLONG_MAX)
-# define LLONG_MAX EXT LONG_LONG_MAX
-#endif
-
-#if defined(ULONG_LONG_MAX) && !defined(ULLONG_MAX)
-# define ULLONG_MAX EXT ULONG_LONG_MAX
-#endif
-
-/* --- Choose the largest integer type --- */
-
-#if defined(INTMAX_MAX)
- typedef intmax_t imax;
-#elif defined(LLONG_MAX)
- EXT typedef long long imax;
-#else
- typedef long imax;
-#endif
-
-#if defined(UINTMAX_MAX)
- typedef uintmax_t umax;
-#elif defined(ULLONG_MAX)
- EXT typedef unsigned long long umax;
-#else
- typedef unsigned long umax;
-#endif
-
-/*----- Main code ---------------------------------------------------------*/
-
-#define TABSZ 64
-
-enum { NEG, POS, NSIGN };
-
-umax cmap[TABSZ];
-int gmap[TABSZ][NSIGN];
-struct { int g, s; } qmap[TABSZ];
-int dumpp = 0;
-
-static int n, q;
-
-static void dump(mp *x)
-{
- int i, w, n;
-
- fputs(" ", stdout);
- w = (MPW_BITS + 3)/4;
- n = 1;
- while (2 + 2 * n * (4 + w) < 72) n <<= 1;
- i = 0;
- for (;;) {
- printf("0x%0*x", w, x->v[i]);
- i++;
- if (i >= MP_LEN(x)) break;
- fputs(",", stdout);
- if (i % n) fputs(" ", stdout); else fputs("\n ", stdout);
- }
- fputs("\n", stdout);
-}
-
-static void doemit(umax c, int s, int *gg, int *qq)
-{
- int i;
- mp *x = MP_NEW;
-
- for (i = 0; i < n; i++) {
- if (cmap[i] == c)
- goto found;
- }
-
- assert(i < TABSZ);
- n = i + 1;
- cmap[i] = c;
- gmap[i][POS] = gmap[i][NEG] = -1;
- if (dumpp) {
- MP_FROMINT(x, umax, c);
- printf("static mpw guts_%d[] = {\n", q);
- dump(x);
- fputs("};\n\n", stdout);
- MP_DROP(x);
- }
-
-found:
- *gg = i;
- if (gmap[i][s] < 0) {
- assert(q < TABSZ);
- gmap[i][s] = q;
- qmap[q].g = i;
- qmap[q].s = s;
- q++;
- }
- *qq = gmap[i][s];
-}
-
-static void emit(imax c, int *gg, int *qq)
-{
- umax uc;
- int s;
-
- if (c >= 0) { uc = c; s = POS; }
- else { uc = -c; s = NEG; }
- doemit(uc, s, gg, qq);
-}
-
-static void uemit(umax c, int *gg, int *qq) { doemit(c, POS, gg, qq); }
-
-struct {
- const char *name;
- imax min;
- umax max;
- int gmin, gmax;
- int qmin, qmax;
-} tab[] = {
- { "SCHAR", SCHAR_MIN, SCHAR_MAX },
- { "CHAR", CHAR_MIN, CHAR_MAX },
- { "UCHAR", 0, UCHAR_MAX },
- { "UINT8", 0, 0xff },
- { "SHRT", SHRT_MIN, SHRT_MAX },
- { "USHRT", 0, USHRT_MAX },
- { "UINT16", 0, 0xffff },
- { "INT", INT_MIN, INT_MAX },
- { "UINT", 0, UINT_MAX },
- { "LONG", LONG_MIN, LONG_MAX },
- { "ULONG", 0, ULONG_MAX },
- { "UINT32", 0, 0xffffffff },
-#ifdef LLONG_MAX
- { "LLONG", LLONG_MIN, LLONG_MAX },
- { "ULLONG", 0, ULLONG_MAX },
-#endif
- { "SIZET", 0, ~(size_t)0 },
- { 0 }
-};
-
-static void dogen(void)
-{
- int i;
-
- for (i = 0; tab[i].name; i++) {
- if (tab[i].min)
- emit(tab[i].min, &tab[i].gmin, &tab[i].qmin);
- uemit(tab[i].max, &tab[i].gmax, &tab[i].qmax);
- }
-}
-
-static void cgen(void)
-{
- int i;
-
- fputs("\
-/* -*-c-*-\n\
- *\n\
- * C integer limits [generated]\n\
- */\n\
-\n\
-#include \"mplimits.h\"\n\
-\n\
-#define N(x) (sizeof(x)/sizeof(*x))\n\
-#define MPpos(x) { x, x + N(x), N(x), 0, MP_CONST, 0 }\n\
-#define MPneg(x) { x, x + N(x), N(x), 0, MP_CONST|MP_NEG, 0 }\n\
-\n",
- stdout);
- dumpp = 1;
- dogen();
-
- fputs("mp mp_limits[] = {\n", stdout);
- for (i = 0; i < q; i++)
- printf(" MP%s(guts_%d),\n", qmap[i].s ? "pos" : "neg", qmap[i].g);
- fputs("};\n", stdout);
-}
-
-static void hgen(void)
-{
- int i;
-
- fputs("\
-/* -*-c-*-\n\
- *\n\
- * C integer limits [generated]\n\
- */\n\
-\n\
-#ifndef CATACOMB_MPLIMITS_H\n\
-#define CATACOMB_MPLIMITS_H\n\
-\n\
-#ifndef CATACOMB_MP_H\n\
-# include \"mp.h\"\n\
-#endif\n\
-\n\
-extern mp mp_limits[];\n\
-\n",
- stdout);
- dogen();
-
- for (i = 0; tab[i].name; i++) {
- if (tab[i].min) {
- printf("#define MP_%s_MIN (&mp_limits[%d])\n",
- tab[i].name, gmap[tab[i].qmin][NEG]);
- }
- printf("#define MP_%s_MAX (&mp_limits[%d])\n",
- tab[i].name, gmap[tab[i].qmax][POS]);
- }
- fputs("\n#endif\n", stdout);
-}
-
-int main(int argc, char *argv[])
-{
- const char *what = argc == 2 ? argv[1] : "<bogus>";
-
- switch (what[0]) {
- case 'c': cgen(); break;
- case 'h': hgen(); break;
- default:
- fprintf(stderr, "unknown action `%s'\n", what);
- exit(1);
- }
- if (fflush(stdout) || fclose(stdout)) {
- fprintf(stderr, "error writing output: %s\n", strerror(errno));
- exit(1);
- }
- return (0);
-}
-
-/*----- That's all, folks -------------------------------------------------*/