OSDN Git Service

*** empty log message ***
[pf3gnuchains/gcc-fork.git] / gcc / enquire.c
1 /* Everything you wanted to know about your machine and C compiler,
2    but didn't know who to ask. */
3
4 #ifndef VERSION
5 #define VERSION "4.3"
6 #endif
7
8 /* Author: Steven Pemberton, CWI, Amsterdam; steven@cwi.nl
9    Bugfixes and upgrades gratefully received.
10
11    Copyright (c) 1988, 1989, 1990 Steven Pemberton, CWI, Amsterdam.
12    All rights reserved.
13
14    Undef CHAR_BIT, etc., if defined in stdio.h, Richard Stallman, Aug 90.
15    In EPROP, avoid a <= old if bad is set, Richard Stallman, May 91.
16    Use gstddef.h, not stddef.h, Richard Stallman, Nov 91.
17    Don't declare malloc, instead cast the value, Richard Stallman, Nov 91.
18    Include sys/types.h before signal.h, Apr 92.
19
20    COMPILING
21    With luck and a following wind, just the following will work:
22         cc enquire.c -o enquire
23    You may get some messages about unreachable code, which you can ignore.
24
25    If your compiler doesn't support:            add flag:
26         signed char (eg pcc)                    -DNO_SC
27         unsigned char                           -DNO_UC
28         unsigned short and long                 -DNO_UI
29         void                                    -DNO_VOID
30         signal(), or setjmp/longjmp()           -DNO_SIG
31
32    Try to compile first with no flags, and see if you get any errors -
33    you might be surprised. (Most non-ANSI compilers need -DNO_SC, though.)
34    Some compilers need a -f flag for floating point.
35
36    Don't use any optimisation flags: the program may not work if you do.
37    Though "while (a+1.0-a-1.0 == 0.0)" may look like "while(1)" to an
38    optimiser, to a floating-point unit there's a world of difference.
39
40    Some compilers offer various flags for different floating point
41    modes; it's worth trying all possible combinations of these.
42
43    Add -DID=\"name\" if you want the machine/flags identified in the output.
44
45    FAULTY COMPILERS
46    Because of bugs and/or inadequacies, some compilers need the following
47    defines:
48
49    If your C preprocessor doesn't have the predefined __FILE__ macro, and
50    you don't want to call this file enquire.c but, say, tell.c, add the
51    flag -DFILENAME=\"tell.c\" .
52
53    Some compilers won't accept the line "#include FILENAME".
54    Add flag -DNO_FILE. In that case, this file *must* be called enquire.c.
55
56    Some compilers can't cope with "#ifdef __FILE__". Use -DFILENAME=
57    or -DNO_FILE as above.
58
59    Some naughty compilers define __STDC__, but don't really support it.
60    Some define it as 0, in which case we treat it as undefined.
61    But if your compiler defines it, and isn't really ANSI C,
62    add flag -DNO_STDC. (To those compiler writers: for shame).
63
64    Some naughty compilers define __STDC__, but don't have the stddef.h
65    include file. Add flag -DNO_STDDEF.
66
67    Summary of naughty-compiler flags:
68    If your compiler doesn't support:             add flag:
69         __FILE__ (and you changed the filename) -DFILENAME=\"name.c\"
70         #ifdef __FILE__                         -DNO_FILE or -DFILENAME=...
71         #include FILENAME                       -DNO_FILE
72         __STDC__ (properly)                     -DNO_STDC
73         stddef.h                                -DNO_STDDEF
74
75    Some systems crash when you try to malloc all store. To save users of
76    such defective systems too much grief, they may compile with -DNO_MEM,
77    which ignores that bit of the code.
78
79    While it is not our policy to support defective compilers, pity has been
80    taken on people with compilers that can't produce object files bigger than
81    32k (especially since it was an easy addition). Compile the program
82    into separate parts like this:
83        cc -DSEP -DPASS0 -o p0.o <other flags> enquire.c
84        cc -DSEP -DPASS1 -o p1.o <other flags> enquire.c
85        cc -DSEP -DPASS2 -o p2.o <other flags> enquire.c
86        cc -DSEP -DPASS3 -o p3.o <other flags> enquire.c
87        cc -o enquire p0.o p1.o p2.o p3.o
88
89    SYSTEM DEPENDENCIES
90    You may possibly need to add some calls to signal() for other sorts of
91    exception on your machine than SIGFPE, and SIGOVER. See lines beginning
92    #ifdef SIGxxx in main() (and communicate the differences to me!).
93
94    OUTPUT
95    Run without argument to get the information as English text. If run
96    with argument -l (e.g. enquire -l), output is a series of #define's for
97    the ANSI standard limits.h include file, excluding MB_MAX_CHAR. If run
98    with argument -f, output is a series of #define's for the ANSI standard
99    float.h include file (according to ANSI C Draft of Dec 7, 1988).
100    Flag -v gives verbose output: output includes the English text above
101    as C comments. The program exit(0)'s if everything went ok, otherwise
102    it exits with a positive number, telling how many problems there were.
103
104    VERIFYING THE COMPILER
105    If, having produced the float.h and limits.h header files, you want to
106    verify that the compiler reads them back correctly (there are a lot of
107    boundary cases, of course, like minimum and maximum numbers), you can
108    recompile enquire.c with -DVERIFY set (plus the other flags that you used
109    when compiling the version that produced the header files). This then
110    recompiles the program so that it #includes "limits.h" and "float.h",
111    and checks that the constants it finds there are the same as the
112    constants it produces. Run the resulting program with enquire -fl.
113    Very few compilers have passed without error.
114    NB: You *must* recompile with the same compiler and flags, otherwise
115    you may get odd results.
116
117    You can also use this option if your compiler already has both files,
118    and you want to confirm that this program produces the right results.
119
120    TROUBLESHOOTING.
121    This program is now quite trustworthy, and suspicious and wrong output
122    may well be caused by bugs in the compiler, not in the program (however
123    of course, this is not guaranteed, and no responsibility can be
124    accepted, etc.)
125
126    The program only works if overflows are ignored by the C system or
127    are catchable with signal().
128
129    If the program fails to run to completion (often with the error message
130    "Unexpected signal at point x"), this often turns out to be a bug in the
131    C compiler's run-time system. Check what was about to be printed, and
132    try to narrow the problem down.
133
134    Another possible problem is that you have compiled the program to produce
135    loss-of-precision arithmetic traps. The program cannot cope with these,
136    and you should re-compile without them. (They should never be the default).
137
138    Make sure you compiled with optimisation turned off.
139
140    Output preceded by *** WARNING: identifies behaviour of the C system
141    deemed incorrect by the program. Likely problems are that printf or
142    scanf don't cope properly with certain boundary numbers: this program
143    goes to a lot of trouble to calculate its values, and these values
144    are mostly boundary numbers. Experience has shown that often printf
145    cannot cope with these values, and so in an attempt to increase
146    confidence in the output, for each float and double that is printed,
147    the printed value is checked by using sscanf to read it back.
148        Care is taken that numbers are printed with enough digits to uniquely
149    identify them, and therefore that they can be read back identically.
150    If the number read back is different, then there is probably a bug in
151    printf or sscanf, and the program prints the warning message.
152    If the two numbers in the warning look identical, then printf is more
153    than likely rounding the last digit(s) incorrectly. To put you at ease
154    that the two really are different, the bit patterns of the two numbers
155    are also printed. The difference is very likely in the last bit.
156        Many scanf's read the minimum double back as 0.0, and similarly cause
157    overflow when reading the maximum double. This program quite ruthlessly
158    declares all these behaviours faulty. The point is that if you get
159    one of these warnings, the output may be wrong, so you should check
160    the result carefully if you intend to use the results. Of course, printf
161    and sscanf may both be wrong, and cancel each other out, so you should
162    check the output carefully anyway.
163
164    The warning that "a cast didn't work" refers to cases like this:
165
166       float f;
167       #define C 1.234567890123456789
168       f= C;
169       if (f != (float) C) printf ("Wrong!");
170
171    A faulty compiler will widen f to double and ignore the cast to float,
172    and because there is more accuracy in a double than a float, fail to
173    recognise that they are the same. In the actual case in point, f and C
174    are passed as parameters to a function that discovers they are not equal,
175    so it's just possible that the error was in the parameter passing,
176    not in the cast (see function Validate()).
177    For ANSI C, which has float constants, the error message is "constant has
178    wrong precision".
179
180    REPORTING PROBLEMS
181    If the program doesn't work for you for any reason that can't be
182    narrowed down to a problem in the C compiler, or it has to be changed in
183    order to get it to compile, or it produces suspicious output (like a very
184    low maximum float, for instance), please mail the problem and an example
185    of the incorrect output to steven@cwi.nl or ..!hp4nl!cwi.nl!steven, so that
186    improvements can be worked into future versions; cwi.nl is the European
187    backbone, and is connected to uunet and other fine hosts.
188
189    The program tries to catch and diagnose bugs in the compiler/run-time
190    system. I would be especially pleased to have reports of failures so
191    that I can improve this service.
192
193    I apologise unreservedly for the contorted use of the preprocessor...
194
195    THE SMALL PRINT
196    You may copy and distribute verbatim copies of this source file.
197
198    You may modify this source file, and copy and distribute such
199    modified versions, provided that you leave the copyright notice
200    at the top of the file and also cause the modified file to carry
201    prominent notices stating that you changed the files and the date
202    of any change; and cause the whole of any work that you distribute
203    or publish, that in whole or in part contains or is a derivative of
204    this program or any part thereof, to be licensed at no charge to
205    all third parties on terms identical to those here.
206
207    If you do have a fix to any problem, please send it to me, so that
208    other people can have the benefits.
209
210    While every effort has been taken to make this program as reliable as
211    possible, no responsibility can be taken for the correctness of the
212    output, nor suitability for any particular use.
213
214    This program is an offshoot of a project funded by public funds.
215    If you use this program for research or commercial use (i.e. more
216    than just for the fun of knowing about your compiler) mailing a short
217    note of acknowledgement may help keep enquire.c supported.
218
219    ACKNOWLEDGEMENTS
220    Many people have given time and ideas to making this program what it is.
221    To all of them thanks, and apologies for not mentioning them by name.
222
223    HISTORY
224    Originally started as a program to generate configuration constants
225    for a large piece of software we were writing, which later took on
226    a life of its own...
227    1.0 Length 6658!; end 1984?
228        Unix only. Only printed a dozen maximum int/double values.
229    2.0 Length 10535; Spring 1985
230        Prints values as #defines (about 20 of them)
231        More extensive floating point, using Cody and Waite
232        Handles signals better
233        Programs around optimisations
234        Handles Cybers
235    3.0 Length 12648; Aug 1987; prints about 42 values
236        Added PASS stuff, so treats float as well as double
237    4.0 Length 33891; Feb 1989; prints around 85 values
238        First GNU version (for gcc, where they call it hard-params.c)
239        Generates float.h and limits.h files
240        Handles long double
241        Generates warnings for dubious output
242    4.1 Length 47738; April 1989
243        Added VERIFY and TEST
244    4.2 Length 63442; Feb 1990
245        Added SEP
246        Fixed eps/epsneg
247        Added check for pseudo-unsigned chars
248        Added description for each #define output
249        Added check for absence of defines during verify
250        Added prototypes
251        Added NO_STDC and NO_FILE
252        Fixed alignments output
253    4.3 Length 75000; Oct 1990; around 114 lines of output
254        Function xmalloc defined, Richard Stallman, June 89.
255        Alignments computed from member offsets rather than structure sizes,
256           Richard Stallman, Oct 89.
257        Print whether char* and int* pointers have the same format;
258           also char * and function *.
259        Update to Draft C version Dec 7, 1988
260           - types of constants produced in limits.h
261             (whether to put a U after unsigned shorts and chars and
262              whether to output -1024 as (-1023-1))
263           - values of SCHAR_MIN/MAX
264           - values of *_EPSILON (not the smallest but the effective smallest)
265        Added FILENAME, since standard C doesn't allow #define __FILE__
266        Renamed from config.c to enquire.c
267        Added size_t and ptrdiff_t enquiries
268        Added promotion enquiries
269        Added type checks of #defines
270        Added NO_STDDEF
271        Changed endian to allow for cases where not all bits are used
272        Sanity check for max integrals
273        Fixed definition of setjmp for -DNO_SIG
274        Moved #define ... 0.0L inside #ifdef STDC, in case some cpp's tokenize
275        Added NO_MEM
276 */
277
278 /* Set FILENAME to the name of this file */
279 #ifndef FILENAME
280 #ifdef NO_FILE
281 #define FILENAME "enquire.c"
282 #else
283 #ifdef __FILE__ /* It's a compiler bug if this fails. Compile with -DNO_FILE */
284 #define FILENAME __FILE__
285 #else
286 #define FILENAME "enquire.c"
287 #endif /* __FILE__ */
288 #endif /* NO_FILE */
289 #endif /* FILENAME */
290
291 /* If PASS isn't defined, then this is the first pass over this file. */
292 #ifndef PASS
293 #ifndef SEP
294 #define PASS 1
295 #define PASS0 1
296 #define PASS1 1
297 #endif /* SEP */
298
299 /* A description of the ANSI constants */
300 #define D_CHAR_BIT "Number of bits in a storage unit"
301 #define D_CHAR_MAX "Maximum char"
302 #define D_CHAR_MIN "Minimum char"
303 #define D_SCHAR_MAX "Maximum signed char"
304 #define D_SCHAR_MIN "Minimum signed char"
305 #define D_UCHAR_MAX "Maximum unsigned char (minimum is always 0)"
306
307 #define D_INT_MAX "Maximum %s"
308 #define D_INT_MIN "Minimum %s"
309 #define D_UINT_MAX "Maximum unsigned %s (minimum is always 0)"
310
311 #define D_FLT_ROUNDS "Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown"
312 #define D_FLT_RADIX "Radix of exponent representation"
313 #define D_MANT_DIG "Number of base-FLT_RADIX digits in the significand of a %s"
314 #define D_DIG "Number of decimal digits of precision in a %s"
315 #define D_MIN_EXP "Minimum int x such that FLT_RADIX**(x-1) is a normalised %s"
316 #define D_MIN_10_EXP "Minimum int x such that 10**x is a normalised %s"
317 #define D_MAX_EXP "Maximum int x such that FLT_RADIX**(x-1) is a representable %s"
318 #define D_MAX_10_EXP "Maximum int x such that 10**x is a representable %s"
319 #define D_MAX "Maximum %s"
320 #define D_EPSILON "Difference between 1.0 and the minimum %s greater than 1.0"
321 #define D_MIN "Minimum normalised %s"
322
323 /* Procedure just marks the functions that don't return a result */
324 #ifdef NO_VOID
325 #define Procedure int
326 #else
327 #define Procedure void
328 #endif
329
330 /* Some bad compilers define __STDC__, when they don't support it.
331    Compile with -DNO_STDC to get round this.
332 */
333 #ifndef NO_STDC
334 #ifdef __STDC__
335 #if __STDC__ /* If __STDC__ is 0, assume it isn't supported */
336 #define STDC
337 #endif
338 #endif
339 #endif
340
341 /* Stuff different for ANSI C, and old C:
342    ARGS and NOARGS are used for function prototypes.
343    Volatile is used to reduce the chance of optimisation,
344       and to prevent variables being put in registers (when setjmp/longjmp
345       wouldn't work as we want)
346    Long_double is the longest floating point type available.
347    stdc is used in tests like "if (stdc)", which is less ugly than #ifdef.
348    U is output after unsigned constants.
349  */
350 #ifdef STDC
351
352 #define ARGS(x) x
353 #define NOARGS (void)
354 #define Volatile volatile
355 #define Long_double long double
356 #define stdc 1
357 #define U "U"
358
359 #else /* Old style C */
360
361 #define ARGS(x) ()
362 #define NOARGS ()
363 #define Volatile static
364 #define Long_double double
365 #define stdc 0
366 #define U ""
367
368 #endif /* STDC */
369
370 /* include files */
371 #include <stdio.h>
372
373 #ifdef STDC
374 #ifndef NO_STDDEF
375 #include "gstddef.h" /* for size_t: if this fails, define NO_STDDEF */
376 #endif
377 #endif
378
379 #ifdef NO_SIG
380 #define jmp_buf int
381 #else
382 #include <sys/types.h>
383 #include <signal.h>
384 #include <setjmp.h>
385 #endif
386
387 /* Kludge around the possiblity that <stdio.h> includes <limits.h> */
388 #ifdef CHAR_BIT
389 #undef CHAR_BIT
390 #undef CHAR_MAX
391 #undef CHAR_MIN
392 #undef SCHAR_MAX
393 #undef SCHAR_MIN
394 #undef UCHAR_MAX
395 #undef UCHAR_MIN
396 #endif
397
398 #ifdef VERIFY
399 #include "limits.h"
400 #include "float.h"
401 #endif
402
403 #define Vprintf if (V) printf
404 #define Unexpected(place) if (setjmp(lab)!=0) croak(place)
405 #define fabs(x) (((x)<0.0)?(-x):(x))
406
407 #endif /* PASS */
408
409 #ifdef PASS0
410
411 /* Prototypes for what's to come: */
412
413 int false NOARGS;
414
415 #ifdef NO_STDDEF
416 char *malloc (); /* Old style prototype */
417 #else
418 char *malloc ARGS((size_t size));
419 #endif
420
421 Procedure exit ARGS((int status));
422
423 char *f_rep ARGS((int precision, Long_double val));
424
425 int maximum_int NOARGS;
426 int cprop NOARGS;
427 int basic NOARGS;
428 Procedure sprop NOARGS;
429 Procedure iprop NOARGS;
430 Procedure lprop NOARGS;
431 Procedure usprop NOARGS;
432 Procedure uiprop NOARGS;
433 Procedure ulprop NOARGS;
434 int fprop ARGS((int bits_per_byte));
435 int dprop ARGS((int bits_per_byte));
436 int ldprop ARGS((int bits_per_byte));
437 Procedure efprop ARGS((int fprec, int dprec, int lprec));
438 Procedure edprop ARGS((int fprec, int dprec, int lprec));
439 Procedure eldprop ARGS((int fprec, int dprec, int lprec));
440
441 int setmode ARGS((char *s));
442 Procedure farewell ARGS((int bugs));
443 Procedure describe ARGS((char *description, char *extra));
444 Procedure missing ARGS((char *s));
445 Procedure fmissing ARGS((char *s));
446 Procedure check_defines NOARGS;
447 Procedure bitpattern ARGS((char *p, unsigned int size));
448 int ceil_log ARGS((int base, Long_double x));
449 Procedure croak ARGS((int place));
450 Procedure eek_a_bug ARGS((char *problem));
451 Procedure endian ARGS((int bits_per_byte));
452 int exponent ARGS((Long_double x, double *fract, int *exp));
453 int floor_log ARGS((int base, Long_double x));
454 Procedure f_define ARGS((char *desc, char *extra, char *sort, char *name,
455                          int prec, Long_double val, char *mark));
456 Procedure i_define ARGS((char *desc, char *extra, char *sort, char *name,
457                          long val, long lim, long req, char *mark));
458 Procedure u_define ARGS((char *desc, char *extra, char *sort, char *name,
459                          unsigned long val, unsigned long req, char *mark));
460
461 #ifdef NO_SIG  /* There's no signal(), or setjmp/longjmp() */
462
463         /* Dummy routines instead */
464
465         int setjmp ARGS((int lab));
466
467         int lab=1;
468         int setjmp(lab) int lab; { return(0); }
469         Procedure signal(i, p) int i, (*p)(); {}
470
471 #else
472         jmp_buf lab;
473         Procedure overflow(sig) int sig; { /* what to do on over/underflow */
474                 signal(sig, overflow);
475                 longjmp(lab, 1);
476         }
477
478 #endif /*NO_SIG*/
479
480 int V= 0,       /* verbose */
481     L= 0,       /* produce limits.h */
482     F= 0,       /* produce float.h  */
483     bugs=0;     /* The number of (possible) bugs in the output */
484
485 char co[4], oc[4]; /* Comment starter and ender symbols */
486
487 int bits_per_byte; /* the number of bits per unit returned by sizeof() */
488 int flt_rounds;    /* The calculated value of FLT_ROUNDS */
489 int flt_radix;     /* The calculated value of FLT_RADIX */
490
491 #ifdef TEST
492 /* Set the fp modes on a SUN with 68881 chip, to check that different
493    rounding modes etc. get properly detected.
494    Compile with -f68881 for cc, -m68881 for gcc, and with additional flag
495    -DTEST. Run with additional parameter +hex-number, to set the 68881 mode
496    register to hex-number
497 */
498
499 /* Bits 0x30 = rounding mode */
500 #define ROUND_BITS      0x30
501 #define TO_NEAREST      0x00
502 #define TO_ZERO         0x10
503 #define TO_MINUS_INF    0x20
504 #define TO_PLUS_INF     0x30 /* The SUN FP user's guide seems to be wrong here */
505
506 /* Bits 0xc0 = extended rounding */
507 #define EXT_BITS        0xc0
508 #define ROUND_EXTENDED  0x00
509 #define ROUND_SINGLE    0x40
510 #define ROUND_DOUBLE    0x80
511
512 /* Enabled traps */
513 #define EXE_INEX1  0x100
514 #define EXE_INEX2  0x200
515 #define EXE_DZ     0x400
516 #define EXE_UNFL   0x800
517 #define EXE_OVFL  0x1000
518 #define EXE_OPERR 0x2000
519 #define EXE_SNAN  0x4000
520 #define EXE_BSUN  0x8000
521
522 /* Only used for testing, on a Sun with 68881 chip */
523 /* Print the FP mode */
524 printmode(new) unsigned new; {
525         fpmode_(&new);
526         printf("New fp mode:\n");
527         printf("  Round toward ");
528         switch (new & ROUND_BITS) {
529               case TO_NEAREST:   printf("nearest"); break;
530               case TO_ZERO:      printf("zero"); break;
531               case TO_MINUS_INF: printf("minus infinity"); break;
532               case TO_PLUS_INF:  printf("plus infinity"); break;
533               default: printf("???"); break;
534         }
535
536         printf("\n  Extended rounding precision: ");
537
538         switch (new & EXT_BITS) {
539               case ROUND_EXTENDED: printf("extended"); break;
540               case ROUND_SINGLE:   printf("single"); break;
541               case ROUND_DOUBLE:   printf("double"); break;
542               default: printf("???"); break;
543         }
544
545         printf("\n  Enabled exceptions:");
546         if (new & (unsigned) EXE_INEX1) printf(" inex1");
547         if (new & (unsigned) EXE_INEX2) printf(" inex2");
548         if (new & (unsigned) EXE_DZ)    printf(" dz");
549         if (new & (unsigned) EXE_UNFL)  printf(" unfl");
550         if (new & (unsigned) EXE_OVFL)  printf(" ovfl");
551         if (new & (unsigned) EXE_OPERR) printf(" operr");
552         if (new & (unsigned) EXE_SNAN)  printf(" snan");
553         if (new & (unsigned) EXE_BSUN)  printf(" bsun");
554         printf("\n");
555 }
556
557 /* Only used for testing, on a Sun with 68881 chip */
558 /* Set the FP mode */
559 int setmode(s) char *s; {
560         unsigned mode=0, dig;
561         char c;
562
563         while (*s) {
564                 c= *s++;
565                 if  (c>='0' && c<='9') dig= c-'0';
566                 else if (c>='a' && c<='f') dig= c-'a'+10;
567                 else if (c>='A' && c<='F') dig= c-'A'+10;
568                 else return 1;
569                 mode= mode<<4 | dig;
570         }
571         printmode(mode);
572         return 0;
573 }
574 #else
575 /* ARGSUSED */
576 int setmode(s) char *s; {
577         fprintf(stderr, "Can't set mode: not compiled with TEST\n");
578         return(1);
579 }
580 #endif
581
582 Procedure farewell(bugs) int bugs; {
583         if (bugs == 0) exit(0);
584         printf("\n%sFor hints on dealing with the ", co);
585         if (bugs == 1) printf("problem");
586         else printf("%d problems", bugs);
587         printf(" above\n   see the section 'TROUBLESHOOTING' in the file ");
588         printf("%s%s\n", FILENAME, oc);
589         exit(bugs);
590 }
591
592 /* The program has received a signal where it wasn't expecting one */
593 Procedure croak(place) int place; {
594         printf("*** Unexpected signal at point %d\n", place);
595         farewell(bugs+1); /* An exit isn't essential here, but avoids loops */
596 }
597
598 /* This is here in case alloca.c is used, which calls this. */
599 char *xmalloc(size) unsigned size; {
600         char *value = (char *)malloc(size);
601         if (value == 0) {
602                 fprintf(stderr, "Virtual memory exceeded\n");
603                 exit(bugs+1);
604         }
605         return value;
606 }
607
608 int maxint;
609
610 int maximum_int() {
611         /* Find the maximum integer */
612         Volatile int newi, int_max, two=2;
613
614         /* Calculate maxint ***********************************/
615         /* Calculate 2**n-1 until overflow - then use the previous value  */
616
617         newi=1; int_max=0;
618
619         if (setjmp(lab)==0) { /* Yields int_max */
620                 while(newi>int_max) {
621                         int_max=newi;
622                         newi=newi*two+1;
623                 }
624         }
625         Unexpected(0);
626         return int_max;
627 }
628
629 int main(argc, argv) int argc; char *argv[]; {
630         int dprec, fprec, lprec;
631         unsigned int size;
632         long total;
633         int i; char *s; int bad;
634
635 #ifdef SIGFPE
636         signal(SIGFPE, overflow);
637 #endif
638 #ifdef SIGOVER
639         signal(SIGOVER, overflow);
640 #endif
641 /* Add more calls as necessary */
642
643         Unexpected(1);
644
645         bad=0;
646         for (i=1; i < argc; i++) {
647                 s= argv[i];
648                 if (*s == '-') {
649                         s++;
650                         while (*s) {
651                                 switch (*(s++)) {
652                                       case 'v': V=1; break;
653                                       case 'l': L=1; break;
654                                       case 'f': F=1; break;
655                                       default: bad=1; break;
656                                 }
657                         }
658                 } else if (*s == '+') {
659                         s++;
660                         bad= setmode(s);
661                 } else bad= 1;
662         }
663         if (bad) {
664                 fprintf(stderr,
665                         "Usage: %s [-vlf]\n  v=Verbose l=Limits.h f=Float.h\n",
666                         argv[0]);
667                 exit(1);
668         }
669         if (L || F) {
670                 co[0]= '/'; oc[0]= ' ';
671                 co[1]= '*'; oc[1]= '*';
672                 co[2]= ' '; oc[2]= '/';
673                 co[3]= '\0'; oc[3]= '\0';
674         } else {
675                 co[0]= '\0'; oc[0]= '\0';
676                 V=1;
677         }
678
679         if (L) printf("%slimits.h%s\n", co, oc);
680         if (F) printf("%sfloat.h%s\n", co, oc);
681 #ifdef ID
682         printf("%sProduced on %s by enquire version %s, CWI, Amsterdam%s\n",
683                co, ID, VERSION, oc);
684 #else
685         printf("%sProduced by enquire version %s, CWI, Amsterdam%s\n",
686                co, VERSION, oc);
687 #endif
688
689 #ifdef VERIFY
690         printf("%sVerification phase%s\n", co, oc);
691 #endif
692
693 #ifdef NO_SIG
694         Vprintf("%sCompiled without signal(): %s%s\n",
695                 co,
696                 "there's nothing that can be done if overflow occurs",
697                 oc);
698 #endif
699 #ifdef NO_SC
700         Vprintf("%sCompiled without signed char%s\n", co, oc);
701 #endif
702 #ifdef NO_UC
703         Vprintf("%Compiled without unsigned char%s\n", co, oc);
704 #endif
705 #ifdef NO_UI
706         Vprintf("%Compiled without unsigned short or long%s\n", co, oc);
707 #endif
708 #ifdef __STDC__
709         Vprintf("%sCompiler claims to be ANSI C level %d%s\n",
710                 co, __STDC__, oc);
711 #else
712         Vprintf("%sCompiler does not claim to be ANSI C%s\n", co, oc);
713 #endif
714         printf("\n");
715         check_defines();
716
717         maxint= maximum_int();
718         bits_per_byte= basic();
719         Vprintf("\n");
720         if (F||V) {
721                 fprec= fprop(bits_per_byte);
722                 dprec= dprop(bits_per_byte);
723                 lprec= ldprop(bits_per_byte);
724                 efprop(fprec, dprec, lprec);
725                 edprop(fprec, dprec, lprec);
726                 eldprop(fprec, dprec, lprec);
727         }
728 #ifndef NO_MEM
729         if (V) {
730                 /* An extra goody: the approximate amount of data-space */
731                 /* Allocate store until no more available */
732                 /* Different implementations have a different argument type
733                    to malloc. Here we assume that it's the same type as
734                    that which sizeof() returns */
735                 size=1<<((bits_per_byte*sizeof(int))-2);
736                 total=0;
737                 while (size!=0) {
738                         while ( malloc((false()?sizeof(int):size)) !=
739                                 (char *)NULL
740                                ) {
741                                 total+=(size/2);
742                         }
743                         size/=2;
744                 }
745
746                 Vprintf("%sMemory mallocatable ~= %ld Kbytes%s\n",
747                         co, (total+511)/512, oc);
748         }
749 #endif
750         farewell(bugs);
751         return bugs; /* To keep compilers and lint happy */
752 }
753
754 Procedure eek_a_bug(problem) char *problem; {
755         /* The program has discovered a problem */
756         printf("\n%s*** WARNING: %s%s\n", co, problem, oc);
757         bugs++;
758 }
759
760 Procedure describe(description, extra) char *description, *extra; {
761         /* Produce the description for a #define */
762         printf("   %s", co);
763         printf(description, extra);
764         printf("%s\n", oc);
765 }
766
767 Procedure i_define(desc, extra, sort, name, val, lim, req, mark)
768      char *desc, *extra, *sort, *name; long val, lim, req; char *mark; {
769         /* Produce a #define for a signed int type */
770         describe(desc, extra);
771         if (val >= 0) {
772                 printf("#define %s%s %ld%s\n", sort, name, val, mark);
773         } else if (val + lim < 0) {
774                 /* We may not produce a constant like -1024 if the max
775                    allowable value is 1023. It has then to be output as
776                    -1023-1. lim is the max allowable value. */
777                 printf("#define %s%s (%ld%s%ld%s)\n",
778                        sort, name, -lim, mark, val+lim, mark);
779         } else {
780                 printf("#define %s%s (%ld%s)\n", sort, name, val, mark);
781         }
782         /* If VERIFY is not set, val and req are just the same value;
783            if it is set, val is the value as calculated, and req is
784            the #defined constant
785         */
786         if (val != req) {
787                 printf("%s*** Verify failed for above #define!\n", co);
788                 printf("       Compiler has %ld for value%s\n\n", req, oc);
789                 bugs++;
790         }
791         Vprintf("\n");
792 }
793
794 Procedure u_define(desc, extra, sort, name, val, req, mark)
795      char *desc, *extra, *sort, *name; unsigned long val, req; char *mark; {
796         /* Produce a #define for an unsigned value */
797         describe(desc, extra);
798         printf("#define %s%s %lu%s%s\n", sort, name, val, U, mark);
799         if (val != req) {
800                 printf("%s*** Verify failed for above #define!\n", co);
801                 printf("       Compiler has %lu for value%s\n\n", req, oc);
802                 bugs++;
803         }
804         Vprintf("\n");
805 }
806
807 Procedure f_define(desc, extra, sort, name, precision, val, mark)
808      char *desc, *extra, *sort, *name; int precision;
809      Long_double val; char *mark; {
810         /* Produce a #define for a float/double/long double */
811         describe(desc, extra);
812         if (stdc) {
813                 printf("#define %s%s %s%s\n",
814                        sort, name, f_rep(precision, val), mark);
815         } else if (*mark == 'F') {
816                 /* non-ANSI C has no float constants, so cast the constant */
817                 printf("#define %s%s ((float)%s)\n",
818                        sort, name, f_rep(precision, val));
819         } else {
820                 printf("#define %s%s %s\n", sort, name, f_rep(precision, val));
821         }
822         Vprintf("\n");
823 }
824
825 int floor_log(base, x) int base; Long_double x; {
826         /* return floor(log base(x)) */
827         int r=0;
828         while (x>=base) { r++; x/=base; }
829         return r;
830 }
831
832 int ceil_log(base, x) int base; Long_double x; {
833         int r=0;
834         while (x>1.0) { r++; x/=base; }
835         return r;
836 }
837
838 int exponent(x, fract, exp) Long_double x; double *fract; int *exp; {
839         /* Split x into a fraction and a power of ten;
840            returns 0 if x is unusable, 1 otherwise.
841            Only used for error messages about faulty output.
842         */
843         int r=0, neg=0;
844         Long_double old;
845         *fract=0.0; *exp=0;
846         if (x<0.0) {
847                 x= -x;
848                 neg= 1;
849         }
850         if (x==0.0) return 1;
851         if (x>=10.0) {
852                 while (x>=10.0) {
853                         old=x; r++; x/=10.0;
854                         if (old==x) return 0;
855                 }
856         } else {
857                 while (x<1.0) {
858                         old=x; r--; x*=10.0;
859                         if (old==x) return 0;
860                 }
861         }
862         if (neg) *fract= (double) -x;
863         else *fract=(double) x;
864         *exp=r;
865         return 1;
866 }
867
868 char *f_rep(precision, val) int precision; Long_double val; {
869         /* Return the floating representation of val */
870         static char buf[1024];
871         char *f1;
872         if (sizeof(double) == sizeof(Long_double)) {
873                 /* Assume they're the same, and use non-stdc format */
874                 /* This is for stdc compilers using non-stdc libraries */
875                 f1= "%.*e";
876         } else {
877                 /* It had better support Le then */
878                 f1= "%.*Le";
879         }
880         sprintf(buf, f1, precision, val);
881         return buf;
882 }
883
884 Procedure bitpattern(p, size) char *p; unsigned int size; {
885         /* Printf the bit-pattern of p */
886         char c;
887         int i, j;
888
889         for (i=1; i<=size; i++) {
890                 c= *p;
891                 p++;
892                 for (j=bits_per_byte-1; j>=0; j--)
893                         printf("%c", (c>>j)&1 ? '1' : '0');
894                 if (i!=size) printf(" ");
895         }
896 }
897
898 #define Order(x, px, mode)\
899    printf("%s%s ", co, mode); for (i=0; i<sizeof(x); i++) px[i]= ab[i]; \
900    for (i=1; i<=sizeof(x); i++) { c=((x>>(bits_per_byte*(sizeof(x)-i)))&mask);\
901       putchar(c==0 ? '?' : (char)c); }\
902    printf("%s\n", oc);
903
904 Procedure endian(bits_per_byte) int bits_per_byte; {
905         /* Printf the byte-order used on this machine */
906         /*unsigned*/ short s=0;
907         /*unsigned*/ int j=0;
908         /*unsigned*/ long l=0;
909
910         char *ps= (char *) &s,
911              *pj= (char *) &j,
912              *pl= (char *) &l,
913              *ab= "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
914         unsigned int mask, i, c;
915
916         mask=0;
917         for (i=1; i<=(unsigned)bits_per_byte; i++) mask= (mask<<1)|1;
918
919         if (V) {
920                 printf("%sCHARACTER ORDER%s\n", co, oc);
921                 Order(s, ps, "short:");
922                 Order(j, pj, "int:  ");
923                 Order(l, pl, "long: ");
924         }
925 }
926
927 Procedure missing(s) char *s; {
928         printf("%s*** #define %s missing from limits.h%s\n", co, s, oc);
929         bugs++;
930 }
931
932 Procedure fmissing(s) char *s; {
933         printf("%s*** #define %s missing from float.h%s\n", co, s, oc);
934         bugs++;
935 }
936
937 /* To try and fool optimisers */
938 int false() { return 0; }
939
940 #define Promoted(x) (false()?(x):(-1))
941 #define is_signed(x) (Promoted(x) < 0)
942 #define sign_of(x) ((x)?"signed":"unsigned")
943 #define Signed 1
944 #define Unsigned 0
945 #define sgn(x) ((is_signed(x))?Signed:Unsigned)
946
947 #define showtype(t, x) Vprintf("%s%s %s %s%s\n", co, t, sign_of(is_signed(x)), type_of(sizeof(x)), oc)
948
949 char *type_of(x) int x; {
950         if (x == sizeof(char)) {
951                 if (sizeof(char) == sizeof(int)) return "char/short/int";
952                 if (sizeof(char) == sizeof(short)) return "char/short";
953                 return "char";
954         }
955         if (x == sizeof(short)) {
956                 if (sizeof(short) == sizeof(int)) return "short/int";
957                 return "short";
958         }
959         if (x == sizeof(int)) {
960                 if (sizeof(int) == sizeof(long)) return "int/long";
961                 return "int";
962         }
963         if (x == sizeof(long)) return "long";
964         return "unknown-type";
965 }
966
967 char *ftype_of(x) int x; {
968         if (x == sizeof(float)) {
969                 return "float";
970         }
971         if (x == sizeof(double)) {
972                 if (sizeof(double) == sizeof(Long_double))
973                   return "(long)double";
974                 return "double";
975         }
976         if (x == sizeof(Long_double)) {
977                 return "long double";
978         }
979         return "unknown-type";
980 }
981
982 Procedure typerr(name, esign, esize, sign, size)
983   char *name; int esign, esize, sign, size;
984 {
985        Vprintf("*** %s has wrong type: expected %s %s, found %s %s\n",
986                name, sign_of(esign), type_of(esize),
987                sign_of(sign), type_of(size));
988 }
989
990 Procedure ftyperr(name, esize, size) char *name; int esize, size; {
991        Vprintf("*** %s has wrong type: expected %s, found %s\n",
992                name, ftype_of(esize), ftype_of(size));
993 }
994
995 promotions() {
996         int si; long sl;
997         unsigned int ui; unsigned long ul;
998         short ss; unsigned short us;
999
1000         Vprintf("\n%sPROMOTIONS%s\n", co, oc);
1001
1002         if (
1003             /* Possible warnings here; no problem */
1004             (sizeof(Promoted(si)) != sizeof(int)) ||
1005             (sizeof(Promoted(sl)) != sizeof(long)) ||
1006             (sizeof(Promoted(ss)) != sizeof(int)) ||
1007             (sizeof(Promoted(ui)) != sizeof(int)) ||
1008             (sizeof(Promoted(ul)) != sizeof(long)) ||
1009             (sizeof(Promoted(us)) != sizeof(int)) ||
1010             is_signed(ui) || is_signed(ul) ||
1011             !is_signed(si) || !is_signed(sl)
1012             )
1013           {
1014             eek_a_bug("promotions don't work properly in conditional expressions\n");
1015           }
1016
1017         showtype("unsigned short promotes to", Promoted((unsigned short)0));
1018         showtype("long+unsigned gives", sl+ui);
1019 }
1020
1021 #define checktype(x, n, s, t) if((sgn(x)!=s)||(sizeof(x)!=sizeof(t))) typerr(n, s, sizeof(t), sign_of(x), sizeof(x));
1022
1023 #define fchecktype(x, n, t) if (sizeof(x) != sizeof(t)) ftyperr(n, sizeof(x), sizeof(t));
1024
1025 Procedure check_defines() {
1026         /* ensure that all #defines are present and have the correct type */
1027 #ifdef VERIFY
1028         int usign;
1029
1030 #ifdef NO_UI
1031         usign= Signed;
1032 #else
1033         /* Implementations promote unsigned short differently */
1034         usign= is_signed((unsigned short)0);
1035 #endif
1036
1037         if (L) {
1038 #ifdef CHAR_BIT
1039         checktype(CHAR_BIT, "CHAR_BIT", Signed, int);
1040 #else
1041         missing("CHAR_BIT");
1042 #endif
1043 #ifdef CHAR_MAX
1044         checktype(CHAR_MAX, "CHAR_MAX", Signed, int);
1045 #else
1046         missing("CHAR_MAX");
1047 #endif
1048 #ifdef CHAR_MIN
1049         checktype(CHAR_MIN, "CHAR_MIN", Signed, int);
1050 #else
1051         missing("CHAR_MIN");
1052 #endif
1053 #ifdef SCHAR_MAX
1054         checktype(SCHAR_MAX, "SCHAR_MAX", Signed, int);
1055 #else
1056         missing("SCHAR_MAX");
1057 #endif
1058 #ifdef SCHAR_MIN
1059         checktype(SCHAR_MIN, "SCHAR_MIN", Signed, int);
1060 #else
1061         missing("SCHAR_MIN");
1062 #endif
1063 #ifdef UCHAR_MAX
1064         checktype(UCHAR_MAX, "UCHAR_MAX", Signed, int);
1065 #else
1066         missing("UCHAR_MAX");
1067 #endif
1068 #ifdef SHRT_MAX
1069         checktype(SHRT_MAX, "SHRT_MAX", Signed, int);
1070 #else
1071         missing("SHRT_MAX");
1072 #endif
1073 #ifdef SHRT_MIN
1074         checktype(SHRT_MIN, "SHRT_MIN", Signed, int);
1075 #else
1076         missing("SHRT_MIN");
1077 #endif
1078 #ifdef INT_MAX
1079         checktype(INT_MAX, "INT_MAX", Signed, int);
1080 #else
1081         missing("INT_MAX");
1082 #endif
1083 #ifdef INT_MIN
1084         checktype(INT_MIN, "INT_MIN", Signed, int);
1085 #else
1086         missing("INT_MIN");
1087 #endif
1088 #ifdef LONG_MAX
1089         checktype(LONG_MAX, "LONG_MAX", Signed, long);
1090 #else
1091         missing("LONG_MAX");
1092 #endif
1093 #ifdef LONG_MIN
1094         checktype(LONG_MIN, "LONG_MIN", Signed, long);
1095 #else
1096         missing("LONG_MIN");
1097 #endif
1098 #ifdef USHRT_MAX
1099         checktype(USHRT_MAX, "USHRT_MAX", usign, int);
1100 #else
1101         missing("USHRT_MAX");
1102 #endif
1103 #ifdef UINT_MAX
1104         checktype(UINT_MAX, "UINT_MAX", Unsigned, int);
1105 #else
1106         missing("UINT_MAX");
1107 #endif
1108 #ifdef ULONG_MAX
1109         checktype(ULONG_MAX, "ULONG_MAX", Unsigned, long);
1110 #else
1111         missing("ULONG_MAX");
1112 #endif
1113         } /* if (L) */
1114
1115         if (F) {
1116 #ifdef FLT_RADIX
1117         checktype(FLT_RADIX, "FLT_RADIX", Signed, int);
1118 #else
1119         fmissing("FLT_RADIX");
1120 #endif
1121 #ifdef FLT_MANT_DIG
1122         checktype(FLT_MANT_DIG, "FLT_MANT_DIG", Signed, int);
1123 #else
1124         fmissing("FLT_MANT_DIG");
1125 #endif
1126 #ifdef FLT_DIG
1127         checktype(FLT_DIG, "FLT_DIG", Signed, int);
1128 #else
1129         fmissing("FLT_DIG");
1130 #endif
1131 #ifdef FLT_ROUNDS
1132         checktype(FLT_ROUNDS, "FLT_ROUNDS", Signed, int);
1133 #else
1134         fmissing("FLT_ROUNDS");
1135 #endif
1136 #ifdef FLT_EPSILON
1137         fchecktype(FLT_EPSILON, "FLT_EPSILON", float);
1138 #else
1139         fmissing("FLT_EPSILON");
1140 #endif
1141 #ifdef FLT_MIN_EXP
1142         checktype(FLT_MIN_EXP, "FLT_MIN_EXP", Signed, int);
1143 #else
1144         fmissing("FLT_MIN_EXP");
1145 #endif
1146 #ifdef FLT_MIN
1147         fchecktype(FLT_MIN, "FLT_MIN", float);
1148 #else
1149         fmissing("FLT_MIN");
1150 #endif
1151 #ifdef FLT_MIN_10_EXP
1152         checktype(FLT_MIN_10_EXP, "FLT_MIN_10_EXP", Signed, int);
1153 #else
1154         fmissing("FLT_MIN_10_EXP");
1155 #endif
1156 #ifdef FLT_MAX_EXP
1157         checktype(FLT_MAX_EXP, "FLT_MAX_EXP", Signed, int);
1158 #else
1159         fmissing("FLT_MAX_EXP");
1160 #endif
1161 #ifdef FLT_MAX
1162         fchecktype(FLT_MAX, "FLT_MAX", float);
1163 #else
1164         fmissing("FLT_MAX");
1165 #endif
1166 #ifdef FLT_MAX_10_EXP
1167         checktype(FLT_MAX_10_EXP, "FLT_MAX_10_EXP", Signed, int);
1168 #else
1169         fmissing("FLT_MAX_10_EXP");
1170 #endif
1171 #ifdef DBL_MANT_DIG
1172         checktype(DBL_MANT_DIG, "DBL_MANT_DIG", Signed, int);
1173 #else
1174         fmissing("DBL_MANT_DIG");
1175 #endif
1176 #ifdef DBL_DIG
1177         checktype(DBL_DIG, "DBL_DIG", Signed, int);
1178 #else
1179         fmissing("DBL_DIG");
1180 #endif
1181 #ifdef DBL_EPSILON
1182         fchecktype(DBL_EPSILON, "DBL_EPSILON", double);
1183 #else
1184         fmissing("DBL_EPSILON");
1185 #endif
1186 #ifdef DBL_MIN_EXP
1187         checktype(DBL_MIN_EXP, "DBL_MIN_EXP", Signed, int);
1188 #else
1189         fmissing("DBL_MIN_EXP");
1190 #endif
1191 #ifdef DBL_MIN
1192         fchecktype(DBL_MIN, "DBL_MIN", double);
1193 #else
1194         fmissing("DBL_MIN");
1195 #endif
1196 #ifdef DBL_MIN_10_EXP
1197         checktype(DBL_MIN_10_EXP, "DBL_MIN_10_EXP", Signed, int);
1198 #else
1199         fmissing("DBL_MIN_10_EXP");
1200 #endif
1201 #ifdef DBL_MAX_EXP
1202         checktype(DBL_MAX_EXP, "DBL_MAX_EXP", Signed, int);
1203 #else
1204         fmissing("DBL_MAX_EXP");
1205 #endif
1206 #ifdef DBL_MAX
1207         fchecktype(DBL_MAX, "DBL_MAX", double);
1208 #else
1209         fmissing("DBL_MAX");
1210 #endif
1211 #ifdef DBL_MAX_10_EXP
1212         checktype(DBL_MAX_10_EXP, "DBL_MAX_10_EXP", Signed, int);
1213 #else
1214         fmissing("DBL_MAX_10_EXP");
1215 #endif
1216 #ifdef STDC
1217 #ifdef LDBL_MANT_DIG
1218         checktype(LDBL_MANT_DIG, "LDBL_MANT_DIG", Signed, int);
1219 #else
1220         fmissing("LDBL_MANT_DIG");
1221 #endif
1222 #ifdef LDBL_DIG
1223         checktype(LDBL_DIG, "LDBL_DIG", Signed, int);
1224 #else
1225         fmissing("LDBL_DIG");
1226 #endif
1227 #ifdef LDBL_EPSILON
1228         fchecktype(LDBL_EPSILON, "LDBL_EPSILON", long double);
1229 #else
1230         fmissing("LDBL_EPSILON");
1231 #endif
1232 #ifdef LDBL_MIN_EXP
1233         checktype(LDBL_MIN_EXP, "LDBL_MIN_EXP", Signed, int);
1234 #else
1235         fmissing("LDBL_MIN_EXP");
1236 #endif
1237 #ifdef LDBL_MIN
1238         fchecktype(LDBL_MIN, "LDBL_MIN", long double);
1239 #else
1240         fmissing("LDBL_MIN");
1241 #endif
1242 #ifdef LDBL_MIN_10_EXP
1243         checktype(LDBL_MIN_10_EXP, "LDBL_MIN_10_EXP", Signed, int);
1244 #else
1245         fmissing("LDBL_MIN_10_EXP");
1246 #endif
1247 #ifdef LDBL_MAX_EXP
1248         checktype(LDBL_MAX_EXP, "LDBL_MAX_EXP", Signed, int);
1249 #else
1250         fmissing("LDBL_MAX_EXP");
1251 #endif
1252 #ifdef LDBL_MAX
1253         fchecktype(LDBL_MAX, "LDBL_MAX", long double);
1254 #else
1255         fmissing("LDBL_MAX");
1256 #endif
1257 #ifdef LDBL_MAX_10_EXP
1258         checktype(LDBL_MAX_10_EXP, "LDBL_MAX_10_EXP", Signed, int);
1259 #else
1260         fmissing("LDBL_MAX_10_EXP");
1261 #endif
1262 #endif /* STDC */
1263         } /* if (F) */
1264 #endif /* VERIFY */
1265 }
1266
1267 #ifdef VERIFY
1268 #ifndef SCHAR_MAX
1269 #define SCHAR_MAX       char_max
1270 #endif
1271 #ifndef SCHAR_MIN
1272 #define SCHAR_MIN       char_min
1273 #endif
1274 #ifndef UCHAR_MAX
1275 #define UCHAR_MAX       char_max
1276 #endif
1277 #endif /* VERIFY */
1278
1279 #ifndef CHAR_BIT
1280 #define CHAR_BIT        char_bit
1281 #endif
1282 #ifndef CHAR_MAX
1283 #define CHAR_MAX        char_max
1284 #endif
1285 #ifndef CHAR_MIN
1286 #define CHAR_MIN        char_min
1287 #endif
1288 #ifndef SCHAR_MAX
1289 #define SCHAR_MAX       char_max
1290 #endif
1291 #ifndef SCHAR_MIN
1292 #define SCHAR_MIN       char_min
1293 #endif
1294 #ifndef UCHAR_MAX
1295 #define UCHAR_MAX       char_max
1296 #endif
1297
1298 int cprop() {
1299         /* Properties of type char */
1300         Volatile char c, char_max, char_min;
1301         Volatile int bits_per_byte, c_signed;
1302         long char_bit;
1303
1304         Unexpected(2);
1305
1306         /* Calculate number of bits per character *************************/
1307         c=1; bits_per_byte=0;
1308         do { c=c<<1; bits_per_byte++; } while(c!=0);
1309         c= (char)(-1);
1310         if (((int)c)<0) c_signed=1;
1311         else c_signed=0;
1312         Vprintf("%schar = %d bits, %ssigned%s\n",
1313                 co, (int)sizeof(c)*bits_per_byte, (c_signed?"":"un"), oc);
1314         char_bit=(long)(sizeof(c)*bits_per_byte);
1315         if (L) i_define(D_CHAR_BIT, "", "CHAR", "_BIT",
1316                         char_bit, 0L, (long) CHAR_BIT, "");
1317
1318         c=0; char_max=0;
1319         c++;
1320         if (setjmp(lab)==0) { /* Yields char_max */
1321                 while (c>char_max) {
1322                         char_max=c;
1323                         c++;
1324                 }
1325         } else {
1326                 Vprintf("%sCharacter overflow generates a trap!%s\n", co, oc);
1327         }
1328         c=0; char_min=0;
1329         c--;
1330         if (setjmp(lab)==0) { /* Yields char_min */
1331                 while (c<char_min) {
1332                         char_min=c;
1333                         c--;
1334                 }
1335         }
1336         if (c_signed && char_min == 0) {
1337                 Vprintf("%sBEWARE! Chars are pseudo-unsigned:%s\n", co, oc);
1338                 Vprintf("%s   %s%s%s\n",
1339                         "They contain only nonnegative values, ",
1340                         "but sign extend when used as integers.", co, oc);
1341         }
1342         Unexpected(3);
1343
1344         if (L) {
1345                 /* Because of the integer promotions, you must use a U after
1346                    the MAX_CHARS in the following cases */
1347                 if ((sizeof(char) == sizeof(int)) && !c_signed) {
1348                         u_define(D_CHAR_MAX, "", "CHAR", "_MAX",
1349                                  (long) char_max,
1350                                  (long) CHAR_MAX, "");
1351                 } else {
1352                         i_define(D_CHAR_MAX, "", "CHAR", "_MAX",
1353                                  (long) char_max, 0L,
1354                                  (long) CHAR_MAX, "");
1355                 }
1356                 i_define(D_CHAR_MIN, "", "CHAR", "_MIN",
1357                          (long) char_min, (long) maxint,
1358                          (long) CHAR_MIN, "");
1359                 if (c_signed) {
1360                         i_define(D_SCHAR_MAX, "", "SCHAR", "_MAX",
1361                                  (long) char_max, 0L,
1362                                  (long) SCHAR_MAX, "");
1363                         i_define(D_SCHAR_MIN, "", "SCHAR", "_MIN",
1364                                  (long) char_min, (long) maxint,
1365                                  (long) SCHAR_MIN, "");
1366                 } else {
1367                         if (sizeof(char) == sizeof(int)) {
1368                                 u_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
1369                                          (long) char_max,
1370                                          (long) UCHAR_MAX, "");
1371                         } else {
1372                                 i_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
1373                                          (long) char_max, 0L,
1374                                          (long) UCHAR_MAX, "");
1375                         }
1376                 }
1377
1378                 if (c_signed) {
1379 #ifndef NO_UC
1380                         Volatile unsigned char c, char_max;
1381                         c=0; char_max=0;
1382                         c++;
1383                         if (setjmp(lab)==0) { /* Yields char_max */
1384                                 while (c>char_max) {
1385                                         char_max=c;
1386                                         c++;
1387                                 }
1388                         }
1389                         Unexpected(4);
1390                         if (sizeof(char) == sizeof(int)) {
1391                                 u_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
1392                                          (long) char_max,
1393                                          (long) UCHAR_MAX, "");
1394                         } else {
1395                                 i_define(D_UCHAR_MAX, "", "UCHAR", "_MAX",
1396                                          (long) char_max, 0L,
1397                                          (long) UCHAR_MAX, "");
1398                         }
1399 #endif
1400                 } else {
1401 #ifndef NO_SC
1402 /* Define NO_SC if this gives a syntax error */ Volatile signed char c, char_max, char_min;
1403                         c=0; char_max=0;
1404                         c++;
1405                         if (setjmp(lab)==0) { /* Yields char_max */
1406                                 while (c>char_max) {
1407                                         char_max=c;
1408                                         c++;
1409                                 }
1410                         }
1411                         c=0; char_min=0;
1412                         c--;
1413                         if (setjmp(lab)==0) { /* Yields char_min */
1414                                 while (c<char_min) {
1415                                         char_min=c;
1416                                         c--;
1417                                 }
1418                         }
1419                         Unexpected(5);
1420                         i_define(D_SCHAR_MIN, "", "SCHAR", "_MIN",
1421                                  (long) char_min, (long) maxint,
1422                                  (long) SCHAR_MIN, "");
1423                         i_define(D_SCHAR_MAX, "", "SCHAR", "_MAX",
1424                                  (long) char_max, 0L,
1425                                  (long) SCHAR_MAX, "");
1426 #endif /* NO_SC */
1427                 }
1428         }
1429         return bits_per_byte;
1430 }
1431
1432 int basic() {
1433         /* The properties of the basic types.
1434            Returns number of bits per sizeof unit */
1435         Volatile int bits_per_byte;
1436         typedef int function ();
1437         int variable;
1438         int *p, *q;
1439
1440         Vprintf("%sSIZES%s\n", co, oc);
1441         bits_per_byte= cprop();
1442
1443         /* Shorts, ints and longs *****************************************/
1444         Vprintf("%sshort=%d int=%d long=%d float=%d double=%d bits %s\n",
1445                 co,
1446                 (int) sizeof(short)*bits_per_byte,
1447                 (int) sizeof(int)*bits_per_byte,
1448                 (int) sizeof(long)*bits_per_byte,
1449                 (int) sizeof(float)*bits_per_byte,
1450                 (int) sizeof(double)*bits_per_byte, oc);
1451         if (stdc) {
1452                 Vprintf("%slong double=%d bits%s\n",
1453                         co, (int) sizeof(Long_double)*bits_per_byte, oc);
1454         }
1455         Vprintf("%schar*=%d bits%s%s\n",
1456                 co, (int)sizeof(char *)*bits_per_byte,
1457                 sizeof(char *)>sizeof(int)?" BEWARE! larger than int!":"",
1458                 oc);
1459         Vprintf("%sint* =%d bits%s%s\n",
1460                 co, (int)sizeof(int *)*bits_per_byte,
1461                 sizeof(int *)>sizeof(int)?" BEWARE! larger than int!":"",
1462                 oc);
1463         Vprintf("%sfunc*=%d bits%s%s\n",
1464                 co, (int)sizeof(function *)*bits_per_byte,
1465                 sizeof(function *)>sizeof(int)?" BEWARE! larger than int!":"",
1466                 oc);
1467 if (V) printf ("%s%s %s %s%s\n", co, "Type size_t is",
1468                        ((((false()?( sizeof(int)):(-1))  < 0) )?
1469                         "signed":"unsigned") ,
1470                        type_of(sizeof(
1471                                       sizeof(int)+0
1472                                       )
1473                                ),
1474                oc);
1475         showtype("Type size_t is", sizeof(0));
1476
1477         /* Alignment constants ********************************************/
1478
1479 #define alignment(TYPE) \
1480         ((long)((char *)&((struct{char c; TYPE d;}*)0)->d - (char *)0))
1481
1482         Vprintf("\n%sALIGNMENTS%s\n", co, oc);
1483
1484         Vprintf("%schar=%ld short=%ld int=%ld long=%ld%s\n",
1485                 co,
1486                 alignment(char), alignment(short),
1487                 alignment(int), alignment(long),
1488                 oc);
1489
1490         Vprintf("%sfloat=%ld double=%ld%s\n",
1491                 co,
1492                 alignment(float), alignment(double),
1493                 oc);
1494
1495         if (stdc) {
1496                 Vprintf("%slong double=%ld%s\n",
1497                         co,
1498                         alignment(Long_double),
1499                         oc);
1500         }
1501         Vprintf("%schar*=%ld int*=%ld func*=%ld%s\n",
1502                 co,
1503                 alignment(char *), alignment(int *), alignment(function *),
1504                 oc);
1505
1506         Vprintf("\n");
1507
1508         /* Ten little endians *********************************************/
1509
1510         endian(bits_per_byte);
1511
1512         /* Pointers *******************************************************/
1513
1514         Vprintf("\n%sPROPERTIES OF POINTERS%s\n", co, oc);
1515
1516         if ((long) (char *) &variable == (long) (int *) &variable)
1517                 Vprintf("%sChar and int pointer formats seem identical%s\n",
1518                        co, oc);
1519         else
1520                 Vprintf("%sChar and int pointer formats are different%s\n",
1521                        co, oc);
1522         if ((long) (char *) &variable == (long) (function *) &variable)
1523                 Vprintf("%sChar and function pointer formats seem identical%s\n",
1524                        co, oc);
1525         else
1526                 Vprintf("%sChar and function pointer formats are different%s\n",
1527                        co, oc);
1528
1529         if (V) {
1530                 if ("abcd"=="abcd")
1531                         printf("%sStrings are shared%s\n", co, oc);
1532                 else printf("%sStrings are not shared%s\n", co, oc);
1533         }
1534
1535         p=0; q=0;
1536         showtype("Type ptrdiff_t is", p-q);
1537
1538         Vprintf("\n%sPROPERTIES OF INTEGRAL TYPES%s\n", co, oc);
1539
1540         sprop();
1541         iprop();
1542         lprop();
1543         usprop();
1544         uiprop();
1545         ulprop();
1546
1547         promotions();
1548
1549         Unexpected(6);
1550
1551         return bits_per_byte;
1552 }
1553
1554 #else /* not PASS0 */
1555
1556 #ifdef SEP
1557 extern jmp_buf lab;
1558 extern int V, L, F, bugs, bits_per_byte;
1559 extern char co[], oc[];
1560 extern char *f_rep();
1561 #endif /* SEP */
1562 #endif /* ifdef PASS0 */
1563
1564 /* As I said, I apologise for the contortions below. The functions are
1565    expanded by the preprocessor twice or three times (for float and double,
1566    and maybe for long double, and for short, int and long). That way,
1567    I never make a change to one that I forget to make to the other.
1568    You can look on it as C's fault for not supporting multi-line macro's.
1569    This whole file is read 3 times by the preprocessor, with PASSn set for
1570    n=1, 2 or 3, to decide which parts to reprocess.
1571 */
1572
1573 /* #undef on an already undefined thing is (wrongly) flagged as an error
1574    by some compilers, therefore the #ifdef that follows:
1575 */
1576 #ifdef Number
1577 #undef Number
1578 #undef THING
1579 #undef Thing
1580 #undef thing
1581 #undef FPROP
1582 #undef Fname
1583 #undef Store
1584 #undef Sum
1585 #undef Diff
1586 #undef Mul
1587 #undef Div
1588 #undef ZERO
1589 #undef HALF
1590 #undef ONE
1591 #undef TWO
1592 #undef THREE
1593 #undef FOUR
1594 #undef Self
1595 #undef F_check
1596 #undef Validate
1597 #undef EPROP
1598 #undef MARK
1599
1600 /* These are the float.h constants */
1601 #undef F_RADIX
1602 #undef F_MANT_DIG
1603 #undef F_DIG
1604 #undef F_ROUNDS
1605 #undef F_EPSILON
1606 #undef F_MIN_EXP
1607 #undef F_MIN
1608 #undef F_MIN_10_EXP
1609 #undef F_MAX_EXP
1610 #undef F_MAX
1611 #undef F_MAX_10_EXP
1612 #endif
1613
1614 #ifdef Integer
1615 #undef Integer
1616 #undef INT
1617 #undef IPROP
1618 #undef Iname
1619 #undef UPROP
1620 #undef Uname
1621 #undef OK_UI
1622 #undef IMARK
1623
1624 #undef I_MAX
1625 #undef I_MIN
1626 #undef U_MAX
1627 #endif
1628
1629 #ifdef PASS1
1630
1631 /* Define the things we're going to use this pass */
1632
1633 #define Number  float
1634 #define THING   "FLOAT"
1635 #define Thing   "Float"
1636 #define thing   "float"
1637 #define Fname   "FLT"
1638 #define FPROP   fprop
1639 #define Store   fStore
1640 #define Sum     fSum
1641 #define Diff    fDiff
1642 #define Mul     fMul
1643 #define Div     fDiv
1644 #define ZERO    0.0
1645 #define HALF    0.5
1646 #define ONE     1.0
1647 #define TWO     2.0
1648 #define THREE   3.0
1649 #define FOUR    4.0
1650 #define Self    fSelf
1651 #define F_check fCheck
1652 #define MARK    "F"
1653 #ifdef VERIFY
1654 #define Validate(prec, val, req, same) fValidate(prec, val, req, same)
1655 #endif
1656
1657 #define EPROP   efprop
1658
1659 #define Integer short
1660 #define INT     "short"
1661 #define IPROP   sprop
1662 #define Iname   "SHRT"
1663 #ifndef NO_UI
1664 #define OK_UI 1
1665 #endif
1666 #define IMARK   ""
1667
1668 #define UPROP   usprop
1669 #define Uname   "USHRT"
1670
1671 #ifdef VERIFY
1672 #ifdef SHRT_MAX
1673 #define I_MAX           SHRT_MAX
1674 #endif
1675 #ifdef SHRT_MIN
1676 #define I_MIN           SHRT_MIN
1677 #endif
1678 #ifdef USHRT_MAX
1679 #define U_MAX           USHRT_MAX
1680 #endif
1681
1682 #ifdef FLT_RADIX
1683 #define F_RADIX         FLT_RADIX
1684 #endif
1685 #ifdef FLT_MANT_DIG
1686 #define F_MANT_DIG      FLT_MANT_DIG
1687 #endif
1688 #ifdef FLT_DIG
1689 #define F_DIG           FLT_DIG
1690 #endif
1691 #ifdef FLT_ROUNDS
1692 #define F_ROUNDS        FLT_ROUNDS
1693 #endif
1694 #ifdef FLT_EPSILON
1695 #define F_EPSILON       FLT_EPSILON
1696 #endif
1697 #ifdef FLT_MIN_EXP
1698 #define F_MIN_EXP       FLT_MIN_EXP
1699 #endif
1700 #ifdef FLT_MIN
1701 #define F_MIN           FLT_MIN
1702 #endif
1703 #ifdef FLT_MIN_10_EXP
1704 #define F_MIN_10_EXP    FLT_MIN_10_EXP
1705 #endif
1706 #ifdef FLT_MAX_EXP
1707 #define F_MAX_EXP       FLT_MAX_EXP
1708 #endif
1709 #ifdef FLT_MAX
1710 #define F_MAX           FLT_MAX
1711 #endif
1712 #ifdef FLT_MAX_10_EXP
1713 #define F_MAX_10_EXP    FLT_MAX_10_EXP
1714 #endif
1715 #endif /* VERIFY */
1716
1717 #endif /* PASS1 */
1718
1719 #ifdef PASS2
1720
1721 #define Number  double
1722 #define THING   "DOUBLE"
1723 #define Thing   "Double"
1724 #define thing   "double"
1725 #define Fname   "DBL"
1726 #define FPROP   dprop
1727 #define Store   dStore
1728 #define Sum     dSum
1729 #define Diff    dDiff
1730 #define Mul     dMul
1731 #define Div     dDiv
1732 #define ZERO    0.0
1733 #define HALF    0.5
1734 #define ONE     1.0
1735 #define TWO     2.0
1736 #define THREE   3.0
1737 #define FOUR    4.0
1738 #define Self    dSelf
1739 #define F_check dCheck
1740 #define MARK    ""
1741 #ifdef VERIFY
1742 #define Validate(prec, val, req, same) dValidate(prec, val, req, same)
1743 #endif
1744
1745 #define EPROP   edprop
1746
1747 #define Integer int
1748 #define INT     "int"
1749 #define IPROP   iprop
1750 #define Iname   "INT"
1751 #define OK_UI   1 /* Unsigned int is always possible */
1752 #define IMARK   ""
1753
1754 #define UPROP   uiprop
1755 #define Uname   "UINT"
1756
1757 #ifdef VERIFY
1758 #ifdef INT_MAX
1759 #define I_MAX           INT_MAX
1760 #endif
1761 #ifdef INT_MIN
1762 #define I_MIN           INT_MIN
1763 #endif
1764 #ifdef UINT_MAX
1765 #define U_MAX           UINT_MAX
1766 #endif
1767
1768 #ifdef DBL_MANT_DIG
1769 #define F_MANT_DIG      DBL_MANT_DIG
1770 #endif
1771 #ifdef DBL_DIG
1772 #define F_DIG           DBL_DIG
1773 #endif
1774 #ifdef DBL_EPSILON
1775 #define F_EPSILON       DBL_EPSILON
1776 #endif
1777 #ifdef DBL_MIN_EXP
1778 #define F_MIN_EXP       DBL_MIN_EXP
1779 #endif
1780 #ifdef DBL_MIN
1781 #define F_MIN           DBL_MIN
1782 #endif
1783 #ifdef DBL_MIN_10_EXP
1784 #define F_MIN_10_EXP    DBL_MIN_10_EXP
1785 #endif
1786 #ifdef DBL_MAX_EXP
1787 #define F_MAX_EXP       DBL_MAX_EXP
1788 #endif
1789 #ifdef DBL_MAX
1790 #define F_MAX           DBL_MAX
1791 #endif
1792 #ifdef DBL_MAX_10_EXP
1793 #define F_MAX_10_EXP    DBL_MAX_10_EXP
1794 #endif
1795 #endif /* VERIFY */
1796
1797 #endif /* PASS2 */
1798
1799 #ifdef PASS3
1800
1801 #ifdef STDC
1802 #define Number  long double
1803
1804 #define ZERO    0.0L
1805 #define HALF    0.5L
1806 #define ONE     1.0L
1807 #define TWO     2.0L
1808 #define THREE   3.0L
1809 #define FOUR    4.0L
1810 #endif
1811
1812 #define THING   "LONG DOUBLE"
1813 #define Thing   "Long double"
1814 #define thing   "long double"
1815 #define Fname   "LDBL"
1816 #define FPROP   ldprop
1817 #define Store   ldStore
1818 #define Sum     ldSum
1819 #define Diff    ldDiff
1820 #define Mul     ldMul
1821 #define Div     ldDiv
1822 #define Self    ldSelf
1823 #define F_check ldCheck
1824 #define MARK    "L"
1825 #ifdef VERIFY
1826 #define Validate(prec, val, req, same) ldValidate(prec, val, req, same)
1827 #endif
1828
1829 #define EPROP   eldprop
1830
1831 #define Integer long
1832 #define INT     "long"
1833 #define IPROP   lprop
1834 #define Iname   "LONG"
1835 #ifndef NO_UI
1836 #define OK_UI   1
1837 #endif
1838 #define IMARK   "L"
1839
1840 #define UPROP   ulprop
1841 #define Uname   "ULONG"
1842
1843 #ifdef VERIFY
1844 #ifdef LONG_MAX
1845 #define I_MAX   LONG_MAX
1846 #endif
1847 #ifdef LONG_MIN
1848 #define I_MIN   LONG_MIN
1849 #endif
1850 #ifdef ULONG_MAX
1851 #define U_MAX   ULONG_MAX
1852 #endif
1853
1854 #ifdef LDBL_MANT_DIG
1855 #define F_MANT_DIG      LDBL_MANT_DIG
1856 #endif
1857 #ifdef LDBL_DIG
1858 #define F_DIG           LDBL_DIG
1859 #endif
1860 #ifdef LDBL_EPSILON
1861 #define F_EPSILON       LDBL_EPSILON
1862 #endif
1863 #ifdef LDBL_MIN_EXP
1864 #define F_MIN_EXP       LDBL_MIN_EXP
1865 #endif
1866 #ifdef LDBL_MIN
1867 #define F_MIN           LDBL_MIN
1868 #endif
1869 #ifdef LDBL_MIN_10_EXP
1870 #define F_MIN_10_EXP    LDBL_MIN_10_EXP
1871 #endif
1872 #ifdef LDBL_MAX_EXP
1873 #define F_MAX_EXP       LDBL_MAX_EXP
1874 #endif
1875 #ifdef LDBL_MAX
1876 #define F_MAX           LDBL_MAX
1877 #endif
1878 #ifdef LDBL_MAX_10_EXP
1879 #define F_MAX_10_EXP    LDBL_MAX_10_EXP
1880 #endif
1881 #endif /* VERIFY */
1882
1883 #endif /* PASS3 */
1884
1885 #ifndef I_MAX
1886 #define I_MAX   int_max
1887 #endif
1888 #ifndef I_MIN
1889 #define I_MIN   int_min
1890 #endif
1891 #ifndef U_MAX
1892 #define U_MAX   u_max
1893 #endif
1894
1895 #ifndef F_RADIX
1896 #define F_RADIX         f_radix
1897 #endif
1898 #ifndef F_MANT_DIG
1899 #define F_MANT_DIG      f_mant_dig
1900 #endif
1901 #ifndef F_DIG
1902 #define F_DIG           f_dig
1903 #endif
1904 #ifndef F_ROUNDS
1905 #define F_ROUNDS        f_rounds
1906 #endif
1907 #ifndef F_EPSILON
1908 #define F_EPSILON       f_epsilon
1909 #endif
1910 #ifndef F_MIN_EXP
1911 #define F_MIN_EXP       f_min_exp
1912 #endif
1913 #ifndef F_MIN
1914 #define F_MIN           f_min
1915 #endif
1916 #ifndef F_MIN_10_EXP
1917 #define F_MIN_10_EXP    f_min_10_exp
1918 #endif
1919 #ifndef F_MAX_EXP
1920 #define F_MAX_EXP       f_max_exp
1921 #endif
1922 #ifndef F_MAX
1923 #define F_MAX           f_max
1924 #endif
1925 #ifndef F_MAX_10_EXP
1926 #define F_MAX_10_EXP    f_max_10_exp
1927 #endif
1928
1929 #ifndef VERIFY
1930 #define Validate(prec, val, req, same) {;}
1931 #endif
1932
1933 #ifdef Integer
1934
1935 Procedure IPROP() {
1936         /* the properties of short, int, and long */
1937         Volatile Integer newi, int_max, maxeri, int_min, minneri;
1938         Volatile int ibits, ipower, two=2;
1939
1940         /* Calculate max short/int/long ***********************************/
1941         /* Calculate 2**n-1 until overflow - then use the previous value  */
1942
1943         newi=1; int_max=0;
1944
1945         if (setjmp(lab)==0) { /* Yields int_max */
1946                 for(ipower=0; newi>int_max; ipower++) {
1947                         int_max=newi;
1948                         newi=newi*two+1;
1949                 }
1950                 Vprintf("%sOverflow of a%s %s does not generate a trap%s\n",
1951                         co, INT[0]=='i'?"n":"", INT, oc);
1952         } else {
1953                 Vprintf("%sOverflow of a%s %s generates a trap%s\n",
1954                         co, INT[0]=='i'?"n":"", INT, oc);
1955         }
1956         Unexpected(7);
1957
1958         /* Minimum value: assume either two's or one's complement *********/
1959         int_min= -int_max;
1960         if (setjmp(lab)==0) { /* Yields int_min */
1961                 if (int_min-1 < int_min) int_min--;
1962         }
1963         Unexpected(8);
1964
1965         /* Now for those daft Cybers */
1966
1967         maxeri=0; newi=int_max;
1968
1969         if (setjmp(lab)==0) { /* Yields maxeri */
1970                 for(ibits=ipower; newi>maxeri; ibits++) {
1971                         maxeri=newi;
1972                         newi=newi+newi+1;
1973                 }
1974         }
1975         Unexpected(9);
1976
1977         minneri= -maxeri;
1978         if (setjmp(lab)==0) { /* Yields minneri */
1979                 if (minneri-1 < minneri) minneri--;
1980         }
1981         Unexpected(10);
1982
1983         Vprintf("%sMaximum %s = %ld (= 2**%d-1)%s\n",
1984                 co, INT, (long)int_max, ipower, oc);
1985         Vprintf("%sMinimum %s = %ld%s\n", co, INT, (long)int_min, oc);
1986
1987         if (L) i_define(D_INT_MAX, INT, Iname, "_MAX",
1988                         (long) int_max, 0L,
1989                         (long) I_MAX, IMARK);
1990         if (L) i_define(D_INT_MIN, INT, Iname, "_MIN",
1991                         (long) int_min, (long) (PASS==1?maxint:int_max),
1992                         (long) I_MIN, IMARK);
1993
1994         if(int_max < 0) { /* It has happened */
1995                 eek_a_bug("signed integral comparison faulty?");
1996         }
1997
1998         if (maxeri>int_max) {
1999                 Vprintf("%sThere is a larger %s, %ld (= 2**%d-1), %s %s%s\n",
2000                         co, INT, (long)maxeri, ibits,
2001                         "but only for addition, not multiplication",
2002                         "(I smell a Cyber!)",
2003                         oc);
2004         }
2005
2006         if (minneri<int_min) {
2007                 Vprintf("%sThere is a smaller %s, %ld, %s %s%s\n",
2008                         co, INT, (long)minneri,
2009                         "but only for addition, not multiplication",
2010                         "(I smell a Cyber!)",
2011                         oc);
2012         }
2013 }
2014
2015 Procedure UPROP () {
2016         /* The properties of unsigned short/int/long */
2017 #ifdef OK_UI
2018         Volatile unsigned Integer u_max, newi, two;
2019         newi=1; u_max=0; two=2;
2020
2021         if (setjmp(lab)==0) { /* Yields u_max */
2022                 while(newi>u_max) {
2023                         u_max=newi;
2024                         newi=newi*two+1;
2025                 }
2026         }
2027         Unexpected(11);
2028         Vprintf("%sMaximum unsigned %s = %lu%s\n",
2029                 co, INT, (unsigned long) u_max, oc);
2030
2031         /* Oh woe: new standard C defines value preserving promotions */
2032         if (L) {
2033                 if (PASS == 1 && sizeof(short) < sizeof(int)) {
2034                         /* Special only for short */
2035                         i_define(D_UINT_MAX, INT, Uname, "_MAX",
2036                                  (unsigned long) u_max, 0L,
2037                                  (unsigned long) U_MAX, IMARK);
2038                 } else {
2039                         u_define(D_UINT_MAX, INT, Uname, "_MAX",
2040                                  (unsigned long) u_max,
2041                                  (unsigned long) U_MAX, IMARK);
2042                 }
2043         }
2044 #endif
2045 }
2046
2047 #endif /* Integer */
2048
2049 #ifdef Number
2050
2051 /* The following routines are intended to defeat any attempt at optimisation
2052    or use of extended precision, and to defeat faulty narrowing casts.
2053    The weird prototypes are because of widening incompatibilities.
2054 */
2055 #ifdef STDC
2056 #define ARGS1(atype, a) (atype a)
2057 #define ARGS2(atype, a, btype, b) (atype a, btype b)
2058 #else
2059 #define ARGS1(atype, a) (a) atype a;
2060 #define ARGS2(atype, a, btype, b) (a, b) atype a; btype b;
2061 #endif
2062
2063 Procedure Store ARGS2(Number, a, Number *, b) { *b=a; }
2064 Number Sum ARGS2(Number, a, Number, b) {Number r; Store(a+b, &r); return (r); }
2065 Number Diff ARGS2(Number, a, Number, b){Number r; Store(a-b, &r); return (r); }
2066 Number Mul ARGS2(Number, a, Number, b) {Number r; Store(a*b, &r); return (r); }
2067 Number Div ARGS2(Number, a, Number, b) {Number r; Store(a/b, &r); return (r); }
2068 Number Self ARGS1(Number, a)           {Number r; Store(a,   &r); return (r); }
2069
2070 Procedure F_check ARGS((int precision, Long_double val1));
2071
2072 Procedure F_check(precision, val1) int precision; Long_double val1; {
2073         /* You don't think I'm going to go to all the trouble of writing
2074            a program that works out what all sorts of values are, only to
2075            have printf go and print the wrong values out, do you?
2076            No, you're right, so this function tries to see if printf
2077            has written the right value, by reading it back again.
2078            This introduces a new problem of course: suppose printf writes
2079            the correct value, and scanf reads it back wrong... oh well.
2080            But I'm adamant about this: the precision given is enough
2081            to uniquely identify the printed number, therefore I insist
2082            that sscanf read the number back identically. Harsh yes, but
2083            sometimes you've got to be cruel to be kind.
2084         */
2085         Long_double new1;
2086         Number val, new, diff;
2087         double rem;
2088         int e;
2089         char *rep;
2090         char *f2;
2091
2092         if (sizeof(double) == sizeof(Long_double)) {
2093                 /* Assume they're the same, and use non-stdc format */
2094                 /* This is for stdc compilers using non-stdc libraries */
2095                 f2= "%le";   /* Input */
2096         } else {
2097                 /* It had better support Le then */
2098                 f2= "%Le";
2099         }
2100         val= val1;
2101         rep= f_rep(precision, (Long_double) val);
2102         if (setjmp(lab)==0) {
2103                 sscanf(rep, f2, &new1);
2104         } else {
2105                 eek_a_bug("sscanf caused a trap");
2106                 printf("%s    scanning: %s format: %s%s\n\n", co, rep, f2, oc);
2107                 Unexpected(12);
2108                 return;
2109         }
2110
2111         if (setjmp(lab)==0) { /* See if new is usable */
2112                 new= new1;
2113                 if (new != 0.0) {
2114                         diff= val/new - 1.0;
2115                         if (diff < 0.1) diff= 1.0;
2116                         /* That should be enough to generate a trap */
2117                 }
2118         } else {
2119                 eek_a_bug("sscanf returned an unusable number");
2120                 printf("%s    scanning: %s with format: %s%s\n\n",
2121                        co, rep, f2, oc);
2122                 Unexpected(13);
2123                 return;
2124         }
2125
2126         Unexpected(14);
2127         if (new != val) {
2128                 eek_a_bug("Possibly bad output from printf above");
2129                 if (!exponent((Long_double)val, &rem, &e)) {
2130                         printf("%s    but value was an unusable number%s\n\n",
2131                                co, oc);
2132                         return;
2133                 }
2134                 printf("%s    expected value around %.*fe%d, bit pattern:\n    ",
2135                        co, precision, rem, e);
2136                 bitpattern((char *) &val, (unsigned)sizeof(val));
2137                 printf ("%s\n", oc);
2138                 printf("%s    sscanf gave           %s, bit pattern:\n    ",
2139                        co, f_rep(precision, (Long_double) new));
2140                 bitpattern((char *) &new, (unsigned)sizeof(new));
2141                 printf ("%s\n", oc);
2142                 if (setjmp(lab) == 0) {
2143                         diff= val-new;
2144                         printf("%s    difference= %s%s\n\n",
2145                                co, f_rep(precision, (Long_double) diff), oc);
2146                 } /* else forget it */
2147                 Unexpected(15);
2148         }
2149 }
2150
2151 #ifdef VERIFY
2152 Procedure Validate(prec, val, req, same) int prec, same; Long_double val, req; {
2153         /* Check that the compiler has read a #define value correctly */
2154         Unexpected(16);
2155         if (!same) {
2156                 printf("%s*** Verify failed for above #define!\n", co);
2157                 if (setjmp(lab) == 0) { /* for the case that req == nan */
2158                         printf("       Compiler has %s for value%s\n",
2159                                f_rep(prec, req), oc);
2160                 } else {
2161                         printf("       Compiler has %s for value%s\n",
2162                                "an unusable number", oc);
2163                 }
2164                 if (setjmp(lab) == 0) {
2165                         F_check(prec, (Long_double) req);
2166                 } /*else forget it*/
2167                 if (setjmp(lab) == 0) {
2168                         if (req > 0.0 && val > 0.0) {
2169                                 printf("%s    difference= %s%s\n",
2170                                        co, f_rep(prec, val-req), oc);
2171                         }
2172                 } /*else forget it*/
2173                 Unexpected(17);
2174                 printf("\n");
2175                 bugs++;
2176         } else if (val != req) {
2177                 if (stdc) eek_a_bug("constant has the wrong precision");
2178                 else eek_a_bug("the cast didn't work");
2179                 printf("\n");
2180         }
2181 }
2182 #endif /* VERIFY */
2183
2184 int FPROP(bits_per_byte) int bits_per_byte; {
2185         /* Properties of floating types, using algorithms by Cody and Waite
2186            from MA Malcolm, as modified by WM Gentleman and SB Marovich.
2187            Further extended by S Pemberton.
2188
2189            Returns the number of digits in the fraction.
2190         */
2191
2192         Volatile int
2193                 i, f_radix, iexp, irnd, mrnd, f_rounds, f_mant_dig,
2194                 iz, k, inf, machep, f_max_exp, f_min_exp, mx, negeps,
2195                 mantbits, digs, f_dig, trap,
2196                 hidden, normal, f_min_10_exp, f_max_10_exp;
2197         Volatile Number
2198                 a, b, base, basein, basem1, f_epsilon, epsneg,
2199                 eps, epsp1, etop, ebot,
2200                 f_max, newxmax, f_min, xminner, y, y1, z, z1, z2;
2201
2202         Unexpected(18);
2203
2204         Vprintf("%sPROPERTIES OF %s%s\n", co, THING, oc);
2205
2206         /* Base and size of significand **************************************/
2207         /* First repeatedly double until adding 1 has no effect.          */
2208         /* For instance, if base is 10, with 3 significant digits         */
2209         /* it will try 1, 2, 4, 8, ... 512, 1024, and stop there,         */
2210         /* since 1024 is only representable as 1020.                      */
2211         a=1.0;
2212         if (setjmp(lab)==0) { /* inexact trap? */
2213                 do { a=Sum(a, a); }
2214                 while (Diff(Diff(Sum(a, ONE), a), ONE) == ZERO);
2215         } else {
2216                 fprintf(stderr, "*** Program got loss-of-precision trap!\n");
2217                 /* And supporting those is just TOO much trouble! */
2218                 farewell(bugs+1);
2219         }
2220         Unexpected(19);
2221         /* Now double until you find a number that can be added to the    */
2222         /* above number. For 1020 this is 8 or 16, depending whether the  */
2223         /* result is rounded or truncated.                                */
2224         /* In either case the result is 1030. 1030-1020= the base, 10.    */
2225         b=1.0;
2226         do { b=Sum(b, b); } while ((base=Diff(Sum(a, b), a)) == ZERO);
2227         f_radix=base;
2228         Vprintf("%sBase = %d%s\n", co, f_radix, oc);
2229
2230         /* Sanity check; if base<2, I can't guarantee the rest will work  */
2231         if (f_radix < 2) {
2232                 eek_a_bug("Function return or parameter passing faulty? (This is a guess.)");
2233                 printf("\n");
2234                 return(0);
2235         }
2236
2237         if (PASS == 1) { /* only for FLT */
2238                 flt_radix= f_radix;
2239                 if (F) i_define(D_FLT_RADIX, "", "FLT", "_RADIX",
2240                                 (long) f_radix, 0L, (long) F_RADIX, "");
2241         } else if (f_radix != flt_radix) {
2242                 printf("\n%s*** WARNING: %s %s (%d) %s%s\n",
2243                        co, thing, "arithmetic has a different radix",
2244                        f_radix, "from float", oc);
2245                 bugs++;
2246         }
2247
2248         /* Now the number of digits precision */
2249         f_mant_dig=0; b=1.0;
2250         do { f_mant_dig++; b=Mul(b, base); }
2251         while (Diff(Diff(Sum(b, ONE), b), ONE) == ZERO);
2252         f_dig=floor_log(10, (Long_double)(b/base)) + (base==10?1:0);
2253         Vprintf("%sSignificant base digits = %d %s %d %s%s\n",
2254                 co, f_mant_dig, "(= at least", f_dig, "decimal digits)", oc);
2255         if (F) i_define(D_MANT_DIG, thing, Fname, "_MANT_DIG",
2256                         (long) f_mant_dig, 0L, (long) F_MANT_DIG, "");
2257         if (F) i_define(D_DIG, thing, Fname, "_DIG",
2258                         (long) f_dig, 0L, (long) F_DIG, "");
2259         digs= ceil_log(10, (Long_double)b); /* the number of digits to printf */
2260
2261         /* Rounding *******************************************************/
2262         basem1=Diff(base, HALF);
2263         if (Diff(Sum(a, basem1), a) != ZERO) {
2264                 if (f_radix == 2) basem1=0.375;
2265                 else basem1=1.0;
2266                 if (Diff(Sum(a, basem1), a) != ZERO) irnd=2; /* away from 0 */
2267                 else irnd=1; /* to nearest */
2268         } else irnd=0; /* towards 0 */
2269
2270         basem1=Diff(base, HALF);
2271
2272         if (Diff(Diff(-a, basem1), -a) != ZERO) {
2273                 if (f_radix == 2) basem1=0.375;
2274                 else basem1=1.0;
2275                 if (Diff(Diff(-a, basem1), -a) != ZERO) mrnd=2; /* away from 0*/
2276                 else mrnd=1; /* to nearest */
2277         } else mrnd=0; /* towards 0 */
2278
2279         f_rounds= -1; /* Unknown rounding */
2280         if (irnd==0 && mrnd==0) f_rounds=0; /* zero = chops */
2281         if (irnd==1 && mrnd==1) f_rounds=1; /* nearest */
2282         if (irnd==2 && mrnd==0) f_rounds=2; /* +inf */
2283         if (irnd==0 && mrnd==2) f_rounds=3; /* -inf */
2284
2285         if (f_rounds != -1) {
2286                 Vprintf("%sArithmetic rounds towards ", co);
2287                 switch (f_rounds) {
2288                       case 0: Vprintf("zero (i.e. it chops)"); break;
2289                       case 1: Vprintf("nearest"); break;
2290                       case 2: Vprintf("+infinity"); break;
2291                       case 3: Vprintf("-infinity"); break;
2292                       default: Vprintf("???"); break;
2293                 }
2294                 Vprintf("%s\n", oc);
2295         } else { /* Hmm, try to give some help here */
2296                 Vprintf("%sArithmetic rounds oddly: %s\n", co, oc);
2297                 Vprintf("%s    Negative numbers %s%s\n",
2298                         co, mrnd==0 ? "towards zero" :
2299                             mrnd==1 ? "to nearest" :
2300                                       "away from zero",
2301                         oc);
2302                 Vprintf("%s    Positive numbers %s%s\n",
2303                         co, irnd==0 ? "towards zero" :
2304                             irnd==1 ? "to nearest" :
2305                                       "away from zero",
2306                         oc);
2307         }
2308         /* An extra goody */
2309         if (f_radix == 2 && f_rounds == 1) {
2310                 if (Diff(Sum(a, ONE), a) != ZERO) {
2311                         Vprintf("%s   Tie breaking rounds up%s\n", co, oc);
2312                 } else if (Diff(Sum(a, THREE), a) == FOUR) {
2313                         Vprintf("%s   Tie breaking rounds to even%s\n", co, oc);
2314                 } else {
2315                         Vprintf("%s   Tie breaking rounds down%s\n", co, oc);
2316                 }
2317         }
2318         if (PASS == 1) { /* only for FLT */
2319                 flt_rounds= f_rounds;
2320                 if (F)
2321                   i_define(D_FLT_ROUNDS, "", "FLT", "_ROUNDS",
2322                            (long) f_rounds, 1L, (long) F_ROUNDS, "");
2323         } else if (f_rounds != flt_rounds) {
2324                 printf("\n%s*** WARNING: %s %s (%d) %s%s\n",
2325                        co, thing, "arithmetic rounds differently",
2326                        f_rounds, "from float", oc);
2327                 bugs++;
2328         }
2329
2330         /* Various flavours of epsilon ************************************/
2331         negeps=f_mant_dig+f_mant_dig;
2332         basein=1.0/base;
2333         a=1.0;
2334         for(i=1; i<=negeps; i++) a*=basein;
2335
2336         b=a;
2337         while (Diff(Diff(ONE, a), ONE) == ZERO) {
2338                 a*=base;
2339                 negeps--;
2340         }
2341         negeps= -negeps;
2342         Vprintf("%sSmallest x such that 1.0-base**x != 1.0 = %d%s\n",
2343                 co, negeps, oc);
2344
2345         etop = ONE;
2346         ebot = ZERO;
2347         eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
2348         /* find the smallest epsneg (1-epsneg != 1) by binary search.
2349            ebot and etop are the current bounds */
2350         while (eps != ebot && eps != etop) {
2351                 epsp1 = Diff(ONE, eps);
2352                 if (epsp1 < ONE) etop = eps;
2353                 else ebot = eps;
2354                 eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
2355         }
2356         eps= etop;
2357         /* Sanity check */
2358         if (Diff(ONE, etop) >= ONE || Diff(ONE, ebot) != ONE) {
2359                 eek_a_bug("internal error calculating epsneg");
2360         }
2361         Vprintf("%sSmallest x such that 1.0-x != 1.0 = %s%s\n",
2362                 co, f_rep(digs, (Long_double) eps), oc);
2363         if (V) F_check(digs, (Long_double) eps);
2364
2365         epsneg=a;
2366         if ((f_radix!=2) && irnd) {
2367         /*      a=(a*(1.0+a))/(1.0+1.0); => */
2368                 a=Div(Mul(a, Sum(ONE, a)), Sum(ONE, ONE));
2369         /*      if ((1.0-a)-1.0 != 0.0) epsneg=a; => */
2370                 if (Diff(Diff(ONE, a), ONE) != ZERO) epsneg=a;
2371         }
2372         /* epsneg is used later */
2373         Unexpected(20);
2374
2375         machep= -f_mant_dig-f_mant_dig;
2376         a=b;
2377         while (Diff(Sum(ONE, a), ONE) == ZERO) { a*=base; machep++; }
2378         Vprintf("%sSmallest x such that 1.0+base**x != 1.0 = %d%s\n",
2379                 co, machep, oc);
2380
2381         etop = ONE;
2382         ebot = ZERO;
2383         eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
2384         /* find the smallest eps (1+eps != 1) by binary search.
2385            ebot and etop are the current bounds */
2386         while (eps != ebot && eps != etop) {
2387                 epsp1 = Sum(ONE, eps);
2388                 if (epsp1 > ONE) etop = eps;
2389                 else ebot = eps;
2390                 eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
2391         }
2392         /* Sanity check */
2393         if (Sum(ONE, etop) <= ONE || Sum(ONE, ebot) != ONE) {
2394                 eek_a_bug("internal error calculating eps");
2395         }
2396         f_epsilon=etop;
2397
2398         Vprintf("%sSmallest x such that 1.0+x != 1.0 = %s%s\n",
2399                 co, f_rep(digs, (Long_double) f_epsilon), oc);
2400
2401         f_epsilon= Diff(Sum(ONE, f_epsilon), ONE); /* New C standard defn */
2402         Vprintf("%s(Above number + 1.0) - 1.0 = %s%s\n",
2403                 co, f_rep(digs, (Long_double) (f_epsilon)), oc);
2404
2405         /* Possible loss of precision warnings here from non-stdc compilers */
2406         if (F) f_define(D_EPSILON, thing,
2407                         Fname, "_EPSILON", digs, (Long_double) f_epsilon, MARK);
2408         if (V || F) F_check(digs, (Long_double) f_epsilon);
2409         Unexpected(21);
2410         if (F) Validate(digs, (Long_double) f_epsilon, (Long_double) F_EPSILON,
2411                         f_epsilon == Self(F_EPSILON));
2412         Unexpected(22);
2413
2414         /* Extra chop info *************************************************/
2415         if (f_rounds == 0) {
2416                 if (Diff(Mul(Sum(ONE,f_epsilon),ONE),ONE) !=  ZERO) {
2417                         Vprintf("%sAlthough arithmetic chops, it uses guard digits%s\n", co, oc);
2418                 }
2419         }
2420
2421         /* Size of and minimum normalised exponent ************************/
2422         y=0; i=0; k=1; z=basein; z1=(1.0+f_epsilon)/base;
2423
2424         /* Coarse search for the largest power of two */
2425         if (setjmp(lab)==0) { /* for underflow trap */ /* Yields i, k, y, y1 */
2426                 do {
2427                         y=z; y1=z1;
2428                         z=Mul(y,y); z1=Mul(z1, y);
2429                         a=Mul(z,ONE);
2430                         z2=Div(z1,y);
2431                         if (z2 != y1) break;
2432                         if ((Sum(a,a) == ZERO) || (fabs(z) >= y)) break;
2433                         i++;
2434                         k+=k;
2435                 } while(1);
2436         } else {
2437                 Vprintf("%s%s underflow generates a trap%s\n", co, Thing, oc);
2438         }
2439         Unexpected(23);
2440
2441         if (f_radix != 10) {
2442                 iexp=i+1; /* for the sign */
2443                 mx=k+k;
2444         } else {
2445                 iexp=2;
2446                 iz=f_radix;
2447                 while (k >= iz) { iz*=f_radix; iexp++; }
2448                 mx=iz+iz-1;
2449         }
2450
2451         /* Fine tune starting with y and y1 */
2452         if (setjmp(lab)==0) { /* for underflow trap */ /* Yields k, f_min */
2453                 do {
2454                         f_min=y; z1=y1;
2455                         y=Div(y,base); y1=Div(y1,base);
2456                         a=Mul(y,ONE);
2457                         z2=Mul(y1,base);
2458                         if (z2 != z1) break;
2459                         if ((Sum(a,a) == ZERO) || (fabs(y) >= f_min)) break;
2460                         k++;
2461                 } while (1);
2462         }
2463         Unexpected(24);
2464
2465         f_min_exp=(-k)+1;
2466
2467         if ((mx <= k+k-3) && (f_radix != 10)) { mx+=mx; iexp+=1; }
2468         Vprintf("%sNumber of bits used for exponent = %d%s\n", co, iexp, oc);
2469         Vprintf("%sMinimum normalised exponent = %d%s\n", co, f_min_exp-1, oc);
2470         if (F)
2471           i_define(D_MIN_EXP, thing, Fname, "_MIN_EXP",
2472                    (long) f_min_exp, (long) maxint, (long) F_MIN_EXP, "");
2473
2474         if (setjmp(lab)==0) {
2475                 Vprintf("%sMinimum normalised positive number = %s%s\n",
2476                         co, f_rep(digs, (Long_double) f_min), oc);
2477         } else {
2478                 eek_a_bug("printf can't print the smallest normalised number");
2479                 printf("\n");
2480         }
2481         Unexpected(25);
2482         /* Possible loss of precision warnings here from non-stdc compilers */
2483         if (setjmp(lab) == 0) {
2484                 if (F) f_define(D_MIN, thing,
2485                                 Fname, "_MIN", digs, (Long_double) f_min, MARK);
2486                 if (V || F) F_check(digs, (Long_double) f_min);
2487         } else {
2488                 eek_a_bug("xxx_MIN caused a trap");
2489                 printf("\n");
2490         }
2491
2492         if (setjmp(lab) == 0) {
2493                 if (F) Validate(digs, (Long_double) f_min, (Long_double) F_MIN,
2494                                 f_min == Self(F_MIN));
2495         } else {
2496                 printf("%s*** Verify failed for above #define!\n    %s %s\n\n",
2497                        co, "Compiler has an unusable number for value", oc);
2498                 bugs++;
2499         }
2500         Unexpected(26);
2501
2502         a=1.0; f_min_10_exp=0;
2503         while (a > f_min*10.0) { a/=10.0; f_min_10_exp--; }
2504         if (F) i_define(D_MIN_10_EXP, thing, Fname, "_MIN_10_EXP",
2505                         (long) f_min_10_exp, (long) maxint,
2506                         (long) F_MIN_10_EXP, "");
2507
2508         /* Minimum exponent ************************************************/
2509         if (setjmp(lab)==0) { /* for underflow trap */ /* Yields xminner */
2510                 do {
2511                         xminner=y;
2512                         y=Div(y,base);
2513                         a=Mul(y,ONE);
2514                         if ((Sum(a,a) == ZERO) || (fabs(y) >= xminner)) break;
2515                 } while (1);
2516         }
2517         Unexpected(27);
2518
2519         if (xminner != 0.0 && xminner != f_min) {
2520                 normal= 0;
2521                 Vprintf("%sThe smallest numbers are not kept normalised%s\n",
2522                         co, oc);
2523                 if (setjmp(lab)==0) {
2524                     Vprintf("%sSmallest unnormalised positive number = %s%s\n",
2525                             co, f_rep(digs, (Long_double) xminner), oc);
2526                     if (V) F_check(digs, (Long_double) xminner);
2527                 } else {
2528                         eek_a_bug("printf can't print the smallest unnormalised number.");
2529                         printf("\n");
2530                 }
2531                 Unexpected(28);
2532         } else {
2533                 normal= 1;
2534                 Vprintf("%sThe smallest numbers are normalised%s\n", co, oc);
2535         }
2536
2537         /* Maximum exponent ************************************************/
2538         f_max_exp=2; f_max=1.0; newxmax=base+1.0;
2539         inf=0; trap=0;
2540         while (f_max<newxmax) {
2541                 f_max=newxmax;
2542                 if (setjmp(lab) == 0) { /* Yields inf, f_max_exp */
2543                         newxmax=Mul(newxmax, base);
2544                 } else {
2545                         trap=1;
2546                         break;
2547                 }
2548                 if (Div(newxmax, base) != f_max) {
2549                         inf=1; /* ieee infinity */
2550                         break;
2551                 }
2552                 f_max_exp++;
2553         }
2554         Unexpected(29);
2555         if (trap) {
2556                 Vprintf("%s%s overflow generates a trap%s\n", co, Thing, oc);
2557         }
2558
2559         if (inf) Vprintf("%sThere is an 'infinite' value%s\n", co, oc);
2560         Vprintf("%sMaximum exponent = %d%s\n", co, f_max_exp, oc);
2561         if (F) i_define(D_MAX_EXP, thing, Fname, "_MAX_EXP",
2562                         (long) f_max_exp, 0L, (long) F_MAX_EXP, "");
2563
2564         /* Largest number ***************************************************/
2565         f_max=Diff(ONE, epsneg);
2566         if (Mul(f_max,ONE) != f_max) f_max=Diff(ONE, Mul(base,epsneg));
2567         for (i=1; i<=f_max_exp; i++) f_max=Mul(f_max, base);
2568
2569         if (setjmp(lab)==0) {
2570                 Vprintf("%sMaximum number = %s%s\n",
2571                         co, f_rep(digs, (Long_double) f_max), oc);
2572         } else {
2573                 eek_a_bug("printf can't print the largest double.");
2574                 printf("\n");
2575         }
2576         if (setjmp(lab)==0) {
2577         /* Possible loss of precision warnings here from non-stdc compilers */
2578                 if (F) f_define(D_MAX, thing,
2579                                 Fname, "_MAX", digs, (Long_double) f_max, MARK);
2580                 if (V || F) F_check(digs, (Long_double) f_max);
2581         } else {
2582                 eek_a_bug("xxx_MAX caused a trap");
2583                 printf("\n");
2584         }
2585         if (setjmp(lab)==0) {
2586                 if (F) Validate(digs, (Long_double) f_max, (Long_double) F_MAX,
2587                                 f_max == Self(F_MAX));
2588         } else {
2589                 printf("%s*** Verify failed for above #define!\n    %s %s\n\n",
2590                        co, "Compiler has an unusable number for value", oc);
2591                 bugs++;
2592         }
2593         Unexpected(30);
2594
2595         a=1.0; f_max_10_exp=0;
2596         while (a < f_max/10.0) { a*=10.0; f_max_10_exp++; }
2597         if (F) i_define(D_MAX_10_EXP, thing, Fname, "_MAX_10_EXP",
2598                         (long) f_max_10_exp, 0L, (long) F_MAX_10_EXP, "");
2599
2600         /* Hidden bit + sanity check ****************************************/
2601         if (f_radix != 10) {
2602                 hidden=0;
2603                 mantbits=floor_log(2, (Long_double)f_radix)*f_mant_dig;
2604                 if (mantbits+iexp == (int)sizeof(Number)*bits_per_byte) {
2605                         hidden=1;
2606                         Vprintf("%sArithmetic uses a hidden bit%s\n", co, oc);
2607                 } else if (mantbits+iexp+1 == (int)sizeof(Number)*bits_per_byte) {
2608                         Vprintf("%sArithmetic doesn't use a hidden bit%s\n",
2609                                 co, oc);
2610                 } else {
2611                         printf("\n%s%s\n    %s %s %s!%s\n\n",
2612                                co,
2613                                "*** Something fishy here!",
2614                                "Exponent size + significand size doesn't match",
2615                                "with the size of a", thing,
2616                                oc);
2617                 }
2618                 if (hidden && f_radix == 2 && f_max_exp+f_min_exp==3) {
2619                         Vprintf("%sIt looks like %s length IEEE format%s\n",
2620                                 co, f_mant_dig==24 ? "single" :
2621                                     f_mant_dig==53 ? "double" :
2622                                     f_mant_dig >53 ? "extended" :
2623                                                 "some", oc);
2624                         if (f_rounds != 1 || normal) {
2625                                 Vprintf("%s   though ", co);
2626                                 if (f_rounds != 1) {
2627                                         Vprintf("the rounding is unusual");
2628                                         if (normal) Vprintf(" and ");
2629                                 }
2630                                 if (normal) Vprintf("the normalisation is unusual");
2631                                 Vprintf("%s\n", oc);
2632                         }
2633                 } else {
2634                         Vprintf("%sIt doesn't look like IEEE format%s\n",
2635                                 co, oc);
2636                 }
2637         }
2638         printf("\n"); /* regardless of verbosity */
2639         return f_mant_dig;
2640 }
2641
2642 Procedure EPROP(fprec, dprec, lprec) int fprec, dprec, lprec; {
2643         /* See if expressions are evaluated in extended precision.
2644            Some compilers optimise even if you don't want it,
2645            and then this function fails to produce the right result.
2646            We try to diagnose this if it happens.
2647         */
2648         Volatile int eprec;
2649         Volatile double a, b, base, old;
2650         Volatile Number d, oldd, dbase, one, zero;
2651         Volatile int bad=0;
2652
2653         /* Size of significand **************************************/
2654         a=1.0;
2655         if (setjmp(lab) == 0) { /* Yields nothing */
2656                 do { old=a; a=a+a; }
2657                 while ((((a+1.0)-a)-1.0) == 0.0 && a>old);
2658         } else bad=1;
2659
2660         /* Avoid the comparison if bad is set,
2661            to avoid trouble on the convex.  */
2662         if (!bad && (a <= old)) bad=1;
2663
2664         if (!bad) {
2665                 b=1.0;
2666                 if (setjmp(lab) == 0) { /* Yields nothing */
2667                         do { old=b; b=b+b; }
2668                         while ((base=((a+b)-a)) == 0.0 && b>old);
2669                         if (b <= old) bad=1;
2670                 } else bad=1;
2671         }
2672
2673         if (!bad) {
2674                 eprec=0; d=1.0; dbase=base; one=1.0; zero=0.0;
2675                 if (setjmp(lab) == 0) { /* Yields nothing */
2676                         do { eprec++; oldd=d; d=d*dbase; }
2677                         while ((((d+one)-d)-one) == zero && d>oldd);
2678                         if (d <= oldd) bad=1;
2679                 } else bad=1;
2680         }
2681
2682         Unexpected(31);
2683
2684         if (bad) {
2685           Vprintf("%sCan't determine precision for %s expressions:\n%s%s\n",
2686                  co, thing, "   check that you compiled without optimisation!",
2687                  oc);
2688         } else if (eprec==dprec) {
2689           Vprintf("%s%s expressions are evaluated in double precision%s\n",
2690                   co, Thing, oc);
2691         } else if (eprec==fprec) {
2692           Vprintf("%s%s expressions are evaluated in float precision%s\n",
2693                   co, Thing, oc);
2694         } else if (eprec==lprec) {
2695           Vprintf("%s%s expressions are evaluated in long double precision%s\n",
2696                   co, Thing, oc);
2697         } else {
2698                 Vprintf("%s%s expressions are evaluated in a %s %s %d %s%s\n",
2699                         co, Thing, eprec>dprec ? "higher" : "lower",
2700                         "precision than double,\n   using",
2701                         eprec, "base digits",
2702                         oc);
2703         }
2704 }
2705
2706 #else /* not Number */
2707
2708 #ifdef FPROP /* Then create dummy routines for long double */
2709 /* ARGSUSED */
2710 int FPROP(bits_per_byte) int bits_per_byte; { return 0; }
2711 #endif
2712 #ifdef EPROP
2713 /* ARGSUSED */
2714 Procedure EPROP(fprec, dprec, lprec) int fprec, dprec, lprec; {}
2715 #endif
2716
2717 #endif /* ifdef Number */
2718
2719 /* Increment the pass number */
2720 #undef PASS
2721
2722 #ifdef PASS2
2723 #undef PASS2
2724 #define PASS 3
2725 #define PASS3 1
2726 #endif
2727
2728 #ifdef PASS1
2729 #undef PASS1
2730 #define PASS 2
2731 #define PASS2 1
2732 #endif
2733
2734 #ifdef PASS0
2735 #undef PASS0
2736 #endif
2737
2738 #ifdef PASS /* then rescan this file */
2739 #ifdef NO_FILE
2740 #include "enquire.c"
2741 #else
2742 #include FILENAME  /* if this line fails to compile, define NO_FILE */
2743 #endif
2744 #endif /* PASS */
2745