OSDN Git Service

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