OSDN Git Service

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