Build `mptypes.h' header file appropriately for the current
[u/mdw/catacomb] / mptypes.c
CommitLineData
5084155b 1/* -*-c-*-
2 *
3 * Program to find appropriate types for multiprecision integer stuff.
4 */
5
6#define _GNU_SOURCE
7#include <stdio.h>
8#include <limits.h>
9#if __STDC_VERSION__ >= 199900l
10# include <stdint.h>
11#endif
12
13/* --- Hack for GCC --- *
14 *
15 * WG14 in their infinite wisdom decided not to use the GCC constant name.
16 */
17
18#if defined(ULONG_LONG_MAX) && !defined(ULLONG_MAX)
19# define ULLONG_MAX ULONG_LONG_MAX
20#endif
21
22/* --- Choose the largest integer type --- */
23
24#if defined(UINTMAX_MAX)
25 typedef uintmax_t umax;
26# define P_UMAX PRIuMAX
27#elif defined(ULLONG_MAX)
28 typedef unsigned long long umax;
29# define P_UMAX "%llu"
30#else
31 typedef unsigned long umax;
32# define P_UMAX "%lu"
33#endif
34
35/* --- Table of interesting types --- *
36 *
37 * These are in preference order.
38 */
39
40enum {
41 f_stdint
42};
43
44struct itype {
45 const char *name;
46 umax max;
47 unsigned flags;
48 unsigned bits;
49} tytab[] = {
50 { "unsigned int", UINT_MAX, 0 },
51 { "unsigned short", USHRT_MAX, 0 },
52 { "unsigned long", ULONG_MAX, 0 },
53#ifdef ULLONG_MAX
54 { "unsigned long long", ULLONG_MAX, 0 },
55#endif
56#ifdef UINTMAX_MAX
57 { "uintmax_t", UINTMAX_MAX, f_stdint },
58#endif
59 { 0, 0 },
60};
61
62typedef struct itype itype;
63
64/* --- Main program --- */
65
66int main(int argc, char *argv[])
67{
68 itype *i;
69 itype *largest, *mpw, *mpd;
70
71 /* --- Find the bitcounts --- */
72
73 for (i = tytab; i->name; i++) {
74 unsigned bits;
75 umax u = i->max;
76 for (bits = 0; u; bits++)
77 u >>= 1;
78 i->bits = bits;
79 }
80
81 /* --- Now try to find the interesting types --- *
82 *
83 * The first thing to do is to find the largest type. Then I find the
84 * `best' type which is less than half that size, and then the `best' type
85 * which is twice as big as that one.
86 */
87
88 largest = tytab;
89 for (i = tytab; i->name; i++) {
90 if (i->bits > largest->bits)
91 largest = i;
92 }
93 for (mpw = 0, i = tytab; i->name; i++) {
94 if (i->bits * 2 <= largest->bits && (!mpw || i->bits > mpw->bits))
95 mpw = i;
96 }
97 if (!mpw)
98 mpw = tytab;
99 for (mpd = 0, i = tytab; i->name; i++) {
100 if (i->bits >= mpw->bits * 2 && (!mpd || i->bits < mpd->bits))
101 mpd = i;
102 }
103 if (!mpd) {
104 static itype w, d;
105 d = w = *mpw;
106 w.bits /= 2; w.max = ~(~((umax)0) << w.bits);
107 d.bits = w.bits * 2; d.max = ~(~((umax)0) << d.bits);
108 mpw = &w; mpd = &d;
109 }
110
111 /* --- Output time --- */
112
113 puts("\
114/* -*-c-*-\n\
115 *\n\
116 * mptypes.h [generated]\n\
117 */\n\
118\n\
119#ifndef MPTYPES_H\n\
120#define MPTYPES_H\n\
121");
122 if ((mpd->flags | mpw->flags) & f_stdint) {
123 puts("\
124#if __STDC_VERSION__ >= 199900l\n\
125# include <stdint.h>\n\
126#endif\n\
127");
128 }
129 printf("\
130typedef %s mpw;\n\
131#define MPW_BITS %u\n\
132#define MPW_MAX " P_UMAX "\n\
133\n\
134typedef %s mpd;\n\
135#define MPD_BITS %u\n\
136#define MPD_MAX " P_UMAX "\n\
137\n\
138#endif\n\
139",
140 mpw->name, mpw->bits, mpw->max,
141 mpd->name, mpd->bits, mpd->max);
142
143 return (0);
144}