Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
LIMITS.cpp
Go to the documentation of this file.
1// computing numerical limits
2
3
25#include "config.h"
26
27#include <stdio.h> // for printf()
28
29#ifndef _RWSTD_NO_LIMITS_H
30 // avoid including broken <limits.h> (due to the use of #include_next)
31 // with EDG eccp on Linux
32# include <limits.h> // for MB_LEN_MAX
33#endif // _RWSTD_NO_LIMITS_H
34
35
36// establish a dependency on the test for long long
37// and #define the LONG_LONG macro used in "type.h"
38#ifndef _RWSTD_NO_LONG_LONG
39# define LONG_LONG long long
40#else // if defined (_RWSTD_NO_LONG_LONG)
41# if defined (_MSC_VER)
42# define LONG_LONG __int64
43# endif // _MSC_VER
44#endif // _RWSTD_NO_LONG_LONG
45
46#include "types.h" // for type_name()
47
48
49#ifndef _RWSTD_NO_HONOR_STD
50# ifdef _RWSTD_NO_STD_TERMINATE
51# include "terminate.h"
52# endif // _RWSTD_NO_STD_TERMINATE
53#endif // _RWSTD_NO_HONOR_STD
54
55
56// set to 1 if this is not a two's complement architecture
58
59// volatile to foil aggressive optimizers
60volatile int zero = 0;
61volatile int one = zero + 1;
62volatile int two = one + 1;
63volatile int zero_complement = ~zero;
64
65
66
67template<class T>
68void print_limit (T n, const char *pfx, const char *sfx,
69 bool is_max, const char *type)
70{
71 // prevents meaningless comparison warnings when T is unsigned
72 // e.g., for (n < 0)
73 /* not const */ T zero = T (0);
74
75 char nstr [64] = { 0 };
76
77 char* pnstr = nstr + sizeof nstr - 2;
78
79 const char digit [] = {
80 '0','1','2','3','4','5','6','7','8','9', 'a', 'b', 'c', 'd', 'e', 'f'
81 };
82
83 if (is_max || n >= zero) {
84
85 T tnstr = n;
86
87 *--pnstr = digit [tnstr % 16];
88 while (tnstr /= 16)
89 *--pnstr = digit [tnstr % 16];
90 }
91
92 *--pnstr = 'x';
93
94 if ( 'c' == type [0]
95 && 'h' == type [1]
96 && 'a' == type [2]
97 && 'r' == type [3]
98 && '\0' == type [4]) {
99
100 *--pnstr = '\\';
101 *--pnstr = '\'';
102 nstr [sizeof nstr - 2] = '\'';
103 }
104 else {
105 *--pnstr = '0';
106 }
107
108 char macro_name [64];
109 char macro_value [64];
110
111 if (is_max) {
112 sprintf (macro_name, "_RWSTD_%s_MAX", pfx);
113 sprintf (macro_value, "%s%s", pnstr, sfx);
114
115 }
116 else {
117 sprintf (macro_name, "_RWSTD_%s_MIN ", pfx);
118
119 if (n < zero) {
120 if (no_twos_complement) {
121 sprintf (macro_value, "-_RWSTD_%s_MAX", pfx);
122 }
123 else {
124 sprintf (macro_value, "(-_RWSTD_%s_MAX - 1%s)", pfx, sfx);
125 }
126 }
127 else {
128 sprintf (macro_value, "%s%s", pnstr, sfx);
129 }
130 }
131
132 printf ("#define %-18s %s\n", macro_name, macro_value);
133}
134
135
136template <class T>
138{
139 // prevents overzealous gcc optimizer from invoking
140 // undefined behavior on signed integer over/underflow
141 for (T tmp; ; --min) {
142 tmp = T (min - one);
143 if (tmp >= min)
144 break;
145 }
146
147 return min;
148}
149
150
151template <class T>
152const char* type_suffix (T) { return ""; }
153
154const char* type_suffix (short) { return ""; }
155const char* type_suffix (unsigned short) { return "U"; }
156const char* type_suffix (int) { return ""; }
157const char* type_suffix (unsigned int) { return "U"; }
158const char* type_suffix (long) { return "L"; }
159const char* type_suffix (unsigned long) { return "UL"; }
160
161#ifndef _RWSTD_NO_LONG_LONG
162const char* type_suffix (long long) { return "LL"; }
163const char* type_suffix (unsigned long long) { return "ULL"; }
164#else
165# if defined (_MSC_VER)
166const char* type_suffix (__int64) { return "L"; }
167const char* type_suffix (unsigned __int64) { return "UL"; }
168# endif // _MSC_VER
169#endif
170
171
172template <class T>
173T compute_limits (T *pval, const char *pfx, const char *sfx, const char *type)
174{
175 T min = T (-one);
176 T volatile max = T (one);
177
178 int is_signed = T (min - one) < T (zero);
179
180 if (!is_signed)
181 max = min;
182
183 // compute the maximum representable value
184 for (; T (max * two) > max; max *= two);
185 for (*pval = max / (two + two); *pval; ) {
186 if (T (max + *pval) < max) {
187 if (*pval > T (two))
188 *pval /= two;
189 else if (max < T (max + one))
190 *pval = one;
191 else
192 break;
193 }
194 else
195 max += *pval;
196 }
197
198 // print the maximum representable value
199 print_limit (max, pfx, sfx, true, type);
200
201 // compute the minimum representable value
202 for (min = -max; T (min * two) < min; min *= two);
203
204 // working around a gcc optimizer "feature" (PR #26211)
205 // signed integer overflow is undefined behavior
206 // for (; T (min - 1) < min; min -= 1);
207 min = compute_min (min);
208
209 print_limit (min, pfx, sfx, false, type);
210
211 return max;
212}
213
214
216{
217 unsigned bits = 0;
218
219 for (unsigned char c = '\01'; c; c <<= 1, ++bits);
220
221 printf ("#define _RWSTD_CHAR_BIT %2u\n", bits);
222
223 return bits;
224}
225
226
227// used to compute the size of a pointer to a member function
228struct EmptyStruct { };
229
230
231// to silence printf() format comaptibility warnings
232#define SIZEOF(T) unsigned (sizeof (T))
233
234
235int main ()
236{
237 // determine whether this is a two's complement architecture
238 // and set the no_twos_complement global variable to 1 if not
239 if (two + zero_complement != one)
241
242 // compute sizes of fundamental types
243
244#ifndef _RWSTD_NO_BOOL
245 printf ("#define _RWSTD_BOOL_SIZE %2u /* sizeof (bool) */\n",
246 SIZEOF (bool));
247#endif // _RWSTD_NO_BOOL
248
249 printf ("#define _RWSTD_CHAR_SIZE %2u /* sizeof (char) */\n",
250 SIZEOF (char));
251 printf ("#define _RWSTD_SHRT_SIZE %2u /* sizeof (short) */\n",
252 SIZEOF (short));
253 printf ("#define _RWSTD_INT_SIZE %2u /* sizeof (int) */\n",
254 SIZEOF (int));
255 printf ("#define _RWSTD_LONG_SIZE %2u /* sizeof (long) */\n",
256 SIZEOF (long));
257
258 printf ("#define _RWSTD_FLT_SIZE %2u /* sizeof (float) */\n",
259 SIZEOF (float));
260 printf ("#define _RWSTD_DBL_SIZE %2u /* sizeof (double) */\n",
261 SIZEOF (double));
262
263#ifndef _RWSTD_NO_LONG_DOUBLE
264 printf ("#define _RWSTD_LDBL_SIZE %2u /* sizeof (long double) */\n",
265 SIZEOF (long double));
266#endif // _RWSTD_NO_LONG_DOUBLE
267
268 // compute the sizes of data and function pointers
269 printf ("#define _RWSTD_PTR_SIZE %2u /* sizeof (void*) */\n",
270 SIZEOF (void*));
271
272 typedef void (*fun_ptr_t)();
273 printf ("#define _RWSTD_FUNPTR_SIZE %2u /* sizeof (void(*)()) */\n",
274 SIZEOF (fun_ptr_t));
275
276 typedef void (EmptyStruct::*memfun_ptr_t)();
277 printf ("#define _RWSTD_MEMPTR_SIZE %2u "
278 "/* sizeof (void (struct::*)()) */\n",
279 SIZEOF (memfun_ptr_t));
280
281 // compute integral limits
282
283 const unsigned char_bits = compute_char_bits ();
284
285#ifndef _RWSTD_NO_BOOL
286
287 printf ("#define _RWSTD_BOOL_MIN !!0\n");
288 printf ("#define _RWSTD_BOOL_MAX !0\n");
289
290#endif // _RWSTD_NO_BOOL
291
292 if (0 == no_twos_complement) {
293 // comment out the next #define (this is two's complement
294 // architecture)
295 printf ("%s", "// ");
296 }
297 printf ("#define _RWSTD_NO_TWOS_COMPLEMENT\n");
298
299#define MKLIMITS(T, pfx, sfx, type) \
300 do { \
301 T buf = 0; \
302 compute_limits (&buf, pfx, sfx, type); \
303 } while (0)
304
305 MKLIMITS (char, "CHAR", "", "char");
306 MKLIMITS (signed char, "SCHAR", "", "signed char");
307 MKLIMITS (unsigned char, "UCHAR", "U", "unsigned char");
308
309 MKLIMITS (short, "SHRT", "", "short");
310 MKLIMITS (unsigned short, "USHRT", "U", "unsigned short");
311
312 MKLIMITS (int, "INT", "", "int");
313 MKLIMITS (unsigned int, "UINT", "U", "unsigned int");
314
315 MKLIMITS (long, "LONG", "L", "long");
316 MKLIMITS (unsigned long, "ULONG", "UL", "unsigned long");
317
318#ifndef _RWSTD_NO_LONG_LONG
319
320# define LLong long long
321
322 printf ("#define _RWSTD_LLONG_SIZE %2u\n", SIZEOF (LLong));
323
324 const char llong_name[] = "long long";
325
326 MKLIMITS (LLong, "LLONG", "LL", "long long");
327 MKLIMITS (unsigned LLong, "ULLONG", "ULL", "unsigned long long");
328
329#else // if defined (_RWSTD_NO_LONG_LONG)
330
331# if defined (_MSC_VER)
332
333# define LLong __int64
334
335 printf ("#define _RWSTD_LLONG_SIZE %2u\n", SIZEOF (LLong));
336
337 const char llong_name[] = "__int64";
338
339 MKLIMITS (LLong, "LLONG", "L", "__int64");
340 MKLIMITS (unsigned LLong, "ULLONG", "UL", "unsigned __int64");
341
342# else
343
344# define LLong long
345
346 const char llong_name[] = "long";
347
348# endif // _MSC_VER
349
350#endif // _RWSTD_NO_LONG_LONG
351
352#ifndef _RWSTD_NO_WCHAR_T
353
354 printf ("#define _RWSTD_WCHAR_SIZE %2u /* sizeof (wchar_t) */\n",
355 SIZEOF (wchar_t));
356
357 const char *suffix = "U";
358 if ((wchar_t)~0 < (wchar_t)0)
359 suffix = "";
360
361 MKLIMITS (wchar_t, "WCHAR", suffix, "wchar_t");
362
363#endif // _RWSTD_NO_WCHAR_T
364
365#if defined (MB_LEN_MAX)
366
367 printf ("#define _RWSTD_MB_LEN_MAX %d /* libc value */\n",
368 MB_LEN_MAX);
369
370#else // if !defined (MB_LEN_MAX)
371
372# if defined (_AIX)
373 printf ("#define _RWSTD_MB_LEN_MAX %d /* known AIX libc value */\n", 4);
374# elif defined (__hpux)
375 printf ("#define _RWSTD_MB_LEN_MAX %d /* known HP-UX libc value */\n", 4);
376# elif defined (__sgi) || defined (sgi)
377 printf ("#define _RWSTD_MB_LEN_MAX %d /* known IRIX libc value */\n", 5);
378# elif defined (__GLIBC__) && __GLIBC_MINOR__ <= 1
379 printf ("#define _RWSTD_MB_LEN_MAX %d /* known glibc 2.1 value */\n", 6);
380# elif defined (__GLIBC__) && __GLIBC_MINOR__ >= 2
381 printf ("#define _RWSTD_MB_LEN_MAX %d /* known glibc 2.2 value */\n", 16);
382# elif defined (__sun__) || defined (__sun) || defined (__sun)
383 printf ("#define _RWSTD_MB_LEN_MAX %d /* known SunOS libc value */\n", 5);
384# elif defined (_WIN32)
385 printf ("#define _RWSTD_MB_LEN_MAX %d /* known WIN32 libc value */\n", 5);
386# else
387 printf ("#define _RWSTD_MB_LEN_MAX %d /* guess */\n", 8);
388# endif
389
390#endif // MB_LEN_MAX
391
393 // #define macros for exact and lest-width integer types
394
395 // width_bits will have the corresponding bit set for each exact-width
396 // type already processed (i.e., bit 0 for an 8-bit integer type, bit
397 // 1 for a 16-bit integer, etc)
398 int width_bits = 0;
399
400#define PRINT_SPECIFIC(width, least, type) \
401 do { \
402 /* avoid warnings about expression being constant */ \
403 const char* least_str = least; \
404 if (least_str && *least_str) \
405 printf ("#define _RWSTD_INT_LEAST%d_T %s _RWSTD_%s_T\n" \
406 "#define _RWSTD_UINT_LEAST%d_T %s _RWSTD_U%s_T\n", \
407 width, width < 10 ? " " : "", type, \
408 width, width < 10 ? " " : "", type); \
409 else \
410 printf ("#define _RWSTD_INT%d_T %s signed %s\n" \
411 "#define _RWSTD_UINT%d_T %s unsigned %s\n", \
412 width, width < 10 ? " " : "", type, \
413 width, width < 10 ? " " : "", type); \
414 } while (0)
415
416 if (8 == char_bits) {
417 width_bits |= 1;
418 PRINT_SPECIFIC (8, "", "char");
419 }
420 else if (16 == char_bits) {
421 width_bits |= 2;
422 PRINT_SPECIFIC (16, "", "char");
423 }
424 else if (32 == char_bits) {
425 width_bits |= 4;
426 PRINT_SPECIFIC (32, "", "char");
427 }
428 else if (64 == char_bits) {
429 width_bits |= 8;
430 PRINT_SPECIFIC (64, "", "char");
431 }
432
433 if (16 == char_bits * sizeof (short) && !(width_bits & 2)) {
434 width_bits |= 2;
435 PRINT_SPECIFIC (16, "", "short");
436 }
437 else if (32 == char_bits * sizeof (short) && !(width_bits & 4)) {
438 width_bits |= 4;
439 PRINT_SPECIFIC (32, "", "short");
440 }
441 else if (64 == char_bits * sizeof (short) && !(width_bits & 8)) {
442 width_bits |= 8;
443 PRINT_SPECIFIC (64, "", "short");
444 }
445 else if (128 == char_bits * sizeof (short) && !(width_bits & 16)) {
446 width_bits |= 16;
447 PRINT_SPECIFIC (128, "", "short");
448 }
449
450 if (32 == char_bits * sizeof (int) && !(width_bits & 4)) {
451 width_bits |= 4;
452 PRINT_SPECIFIC (32, "", "int");
453 }
454 else if (64 == char_bits * sizeof (int) && !(width_bits & 8)) {
455 width_bits |= 8;
456 PRINT_SPECIFIC (64, "", "int");
457 }
458 else if (128 == char_bits * sizeof (int) && !(width_bits & 16)) {
459 width_bits |= 16;
460 PRINT_SPECIFIC (128, "", "int");
461 }
462
463 if (32 == char_bits * sizeof (long) && !(width_bits & 4)) {
464 width_bits |= 4;
465 PRINT_SPECIFIC (32, "", "long");
466 }
467 else if (64 == char_bits * sizeof (long) && !(width_bits & 8)) {
468 width_bits |= 8;
469 PRINT_SPECIFIC (64, "", "long");
470 }
471 else if (128 == char_bits * sizeof (long) && !(width_bits & 16)) {
472 width_bits |= 16;
473 PRINT_SPECIFIC (128, "", "long");
474 }
475
476 if (32 == char_bits * sizeof (LLong) && !(width_bits & 4)) {
477 width_bits |= 4;
478 PRINT_SPECIFIC (32, "", llong_name);
479 }
480 else if (64 == char_bits * sizeof (LLong) && !(width_bits & 8)) {
481 width_bits |= 8;
482 PRINT_SPECIFIC (64, "", llong_name);
483
484 }
485 else if (128 == char_bits * sizeof (LLong) && !(width_bits & 16)) {
486 width_bits |= 16;
487 PRINT_SPECIFIC (128, "", llong_name);
488 }
489
491 // print the names of the width-specific least integer types
492 // i.e., INT_LEAST8_T, INT_LEAST16_T, INT_LEAST32_T, ...
493
494 if (width_bits & (1 << 0))
495 PRINT_SPECIFIC (8, "_LEAST", "INT8");
496 else if (width_bits & (1 << 1))
497 PRINT_SPECIFIC (8, "_LEAST", "INT16");
498 else if (width_bits & (1 << 2))
499 PRINT_SPECIFIC (8, "_LEAST", "INT32");
500 else if (width_bits & (1 << 3))
501 PRINT_SPECIFIC (8, "_LEAST", "INT64");
502 else if (width_bits & (1 << 4))
503 PRINT_SPECIFIC (8, "_LEAST", "INT128");
504
505 if (width_bits & (1 << 1))
506 PRINT_SPECIFIC (16, "_LEAST", "INT16");
507 else if (width_bits & (1 << 2))
508 PRINT_SPECIFIC (16, "_LEAST", "INT32");
509 else if (width_bits & (1 << 3))
510 PRINT_SPECIFIC (16, "_LEAST", "INT64");
511 else if (width_bits & (1 << 4))
512 PRINT_SPECIFIC (16, "_LEAST", "INT128");
513
514 if (width_bits & (1 << 2))
515 PRINT_SPECIFIC (32, "_LEAST", "INT32");
516 else if (width_bits & (1 << 3))
517 PRINT_SPECIFIC (32, "_LEAST", "INT64");
518 else if (width_bits & (1 << 4))
519 PRINT_SPECIFIC (32, "_LEAST", "INT128");
520
521 if (width_bits & (1 << 3))
522 PRINT_SPECIFIC (64, "_LEAST", "INT64");
523 else if (width_bits & (1 << 4))
524 PRINT_SPECIFIC (64, "_LEAST", "INT128");
525
526 if (width_bits & (1 << 4))
527 PRINT_SPECIFIC (128, "_LEAST", "INT128");
528
529 return 0;
530}
#define T
Definition 17.names.cpp:163
#define c
Definition 17.names.cpp:111
#define tmp
Definition 17.names.cpp:553
#define n
Definition 17.names.cpp:130
IMPORT_C SInt32 printf(const Char *,...)
#define MKLIMITS(T, pfx, sfx, type)
#define LLong
volatile int zero_complement
Definition LIMITS.cpp:63
const char * type_suffix(T)
Definition LIMITS.cpp:152
unsigned compute_char_bits()
Definition LIMITS.cpp:215
void print_limit(T n, const char *pfx, const char *sfx, bool is_max, const char *type)
Definition LIMITS.cpp:68
#define PRINT_SPECIFIC(width, least, type)
volatile int one
Definition LIMITS.cpp:61
int no_twos_complement
Definition LIMITS.cpp:57
#define SIZEOF(T)
Definition LIMITS.cpp:232
volatile int two
Definition LIMITS.cpp:62
volatile int zero
Definition LIMITS.cpp:60
T compute_min(T min)
Definition LIMITS.cpp:137
int main()
Definition LIMITS.cpp:235
T compute_limits(T *pval, const char *pfx, const char *sfx, const char *type)
Definition LIMITS.cpp:173
#define MB_LEN_MAX
Definition limits.h:100
#define min(a, b)
#define max(a, b)