OSDN Git Service

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