source: trunk/third/gcc/enquire.c @ 11288

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