OSDN Git Service

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