OSDN Git Service

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