Build `mptypes.h' header file appropriately for the current
authormdw <mdw>
Thu, 11 Nov 1999 17:39:58 +0000 (17:39 +0000)
committermdw <mdw>
Thu, 11 Nov 1999 17:39:58 +0000 (17:39 +0000)
architecture.

mptypes.c [new file with mode: 0644]

diff --git a/mptypes.c b/mptypes.c
new file mode 100644 (file)
index 0000000..8751e2e
--- /dev/null
+++ b/mptypes.c
@@ -0,0 +1,144 @@
+/* -*-c-*-
+ *
+ * Program to find appropriate types for multiprecision integer stuff.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <limits.h>
+#if __STDC_VERSION__ >= 199900l
+#  include <stdint.h>
+#endif
+
+/* --- Hack for GCC --- *
+ *
+ * WG14 in their infinite wisdom decided not to use the GCC constant name.
+ */
+
+#if defined(ULONG_LONG_MAX) && !defined(ULLONG_MAX)
+#  define ULLONG_MAX ULONG_LONG_MAX
+#endif
+
+/* --- Choose the largest integer type --- */
+
+#if defined(UINTMAX_MAX)
+  typedef uintmax_t umax;
+# define P_UMAX PRIuMAX
+#elif defined(ULLONG_MAX)
+  typedef unsigned long long umax;
+# define P_UMAX "%llu"
+#else
+  typedef unsigned long umax;
+# define P_UMAX "%lu"
+#endif
+
+/* --- Table of interesting types --- *
+ *
+ * These are in preference order.
+ */
+
+enum {
+  f_stdint
+};
+
+struct itype {
+  const char *name;
+  umax max;
+  unsigned flags;
+  unsigned bits;
+} tytab[] = {
+  { "unsigned int",            UINT_MAX,       0 },
+  { "unsigned short",          USHRT_MAX,      0 },
+  { "unsigned long",           ULONG_MAX,      0 },
+#ifdef ULLONG_MAX
+  { "unsigned long long",      ULLONG_MAX,     0 },
+#endif
+#ifdef UINTMAX_MAX
+  { "uintmax_t",               UINTMAX_MAX,    f_stdint },
+#endif
+  { 0,                         0 },
+};
+
+typedef struct itype itype;
+
+/* --- Main program --- */
+
+int main(int argc, char *argv[])
+{
+  itype *i;
+  itype *largest, *mpw, *mpd;
+
+  /* --- Find the bitcounts --- */
+
+  for (i = tytab; i->name; i++) {
+    unsigned bits;
+    umax u = i->max;
+    for (bits = 0; u; bits++)
+      u >>= 1;
+    i->bits = bits;
+  }
+
+  /* --- Now try to find the interesting types --- *
+   *
+   * The first thing to do is to find the largest type.  Then I find the
+   * `best' type which is less than half that size, and then the `best' type
+   * which is twice as big as that one.
+   */
+
+  largest = tytab;
+  for (i = tytab; i->name; i++) {
+    if (i->bits > largest->bits)
+      largest = i;
+  }
+  for (mpw = 0, i = tytab; i->name; i++) {
+    if (i->bits * 2 <= largest->bits && (!mpw || i->bits > mpw->bits))
+      mpw = i;
+  }
+  if (!mpw)
+    mpw = tytab;
+  for (mpd = 0, i = tytab; i->name; i++) {
+    if (i->bits >= mpw->bits * 2 && (!mpd || i->bits < mpd->bits))
+      mpd = i;
+  }
+  if (!mpd) {
+    static itype w, d;
+    d = w = *mpw;
+    w.bits /= 2; w.max = ~(~((umax)0) << w.bits);
+    d.bits = w.bits * 2; d.max = ~(~((umax)0) << d.bits);
+    mpw = &w; mpd = &d;
+  }    
+
+  /* --- Output time --- */
+
+  puts("\
+/* -*-c-*-\n\
+ *\n\
+ * mptypes.h [generated]\n\
+ */\n\
+\n\
+#ifndef MPTYPES_H\n\
+#define MPTYPES_H\n\
+");
+  if ((mpd->flags | mpw->flags) & f_stdint) {
+    puts("\
+#if __STDC_VERSION__ >= 199900l\n\
+#  include <stdint.h>\n\
+#endif\n\
+");
+  }
+  printf("\
+typedef %s mpw;\n\
+#define MPW_BITS %u\n\
+#define MPW_MAX " P_UMAX "\n\
+\n\
+typedef %s mpd;\n\
+#define MPD_BITS %u\n\
+#define MPD_MAX " P_UMAX "\n\
+\n\
+#endif\n\
+",
+  mpw->name, mpw->bits, mpw->max,
+  mpd->name, mpd->bits, mpd->max);
+
+  return (0);
+}