OSDN Git Service

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