OSDN Git Service

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