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