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