OSDN Git Service

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