Use new tail-calling mechanism on ARM.
[official-gcc.git] / gcc / enquire.c
blob8b4bdda3d52e8f51c69e6f2fd9cdcedf1e582d7d
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.
37 Change by Manfred Hollstein, installed Mar 98:
38 (bitpattern): Change type of variable i to unsigned int.
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.
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
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.
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.
62 Some compilers offer various flags for different floating point
63 modes; it's worth trying all possible combinations of these.
65 Add -DID=\"name\" if you want the machine/flags identified in the output.
67 FAULTY COMPILERS
68 Because of bugs and/or inadequacies, some compilers need the following
69 defines:
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\" .
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.
78 Some compilers can't cope with "#ifdef __FILE__". Use -DFILENAME=
79 or -DNO_FILE as above.
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).
86 Some naughty compilers define __STDC__, but don't have the stddef.h
87 include file. Add flag -DNO_STDDEF.
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
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.
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
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!).
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.
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.
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.
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.)
148 The program only works if overflows are ignored by the C system or
149 are catchable with signal().
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.
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).
160 Make sure you compiled with optimisation turned off.
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.
186 The warning that "a cast didn't work" refers to cases like this:
188 float f;
189 #define C 1.234567890123456789
190 f= C;
191 if (f != (float) C) printf ("Wrong!");
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".
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.
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.
215 I apologise unreservedly for the contorted use of the preprocessor...
217 THE SMALL PRINT
218 You may copy and distribute verbatim copies of this source file.
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.
229 If you do have a fix to any problem, please send it to me, so that
230 other people can have the benefits.
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.
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.
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.
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
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 */
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 */
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)"
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)"
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"
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
352 /* Some bad compilers define __STDC__, when they don't support it.
353 Compile with -DNO_STDC to get round this.
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
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.
372 #ifdef STDC
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"
381 #else /* Old style C */
383 #define ARGS(x) ()
384 #define NOARGS ()
385 #define Volatile static
386 #define Long_double double
387 #define stdc 0
388 #define U ""
390 #endif /* STDC */
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>
400 #ifdef STDC
401 #ifndef NO_STDDEF
402 #include <stddef.h> /* for size_t: if this fails, define NO_STDDEF */
403 #endif
404 #endif
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
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
425 #ifdef VERIFY
426 #include "limits.h"
427 #endif
429 #ifndef SYS_FLOAT_H_WRAP
430 #define SYS_FLOAT_H_WRAP 0
431 #endif
433 #if SYS_FLOAT_H_WRAP || defined VERIFY
434 #include "float.h"
435 #endif
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))
441 #endif /* PASS */
443 #ifdef PASS0
445 /* Prototypes for what's to come: */
447 int false NOARGS;
449 #ifdef NO_STDDEF
450 char *malloc (); /* Old style prototype */
451 #else
452 char *malloc ARGS((size_t size));
453 #endif
455 Procedure exit ARGS((int status));
457 char *f_rep ARGS((int precision, Long_double val));
458 char *fake_f_rep ARGS((char *type, Long_double val));
460 int maximum_int NOARGS;
461 int cprop NOARGS;
462 int basic NOARGS;
463 Procedure sprop NOARGS;
464 Procedure iprop NOARGS;
465 Procedure lprop NOARGS;
466 Procedure usprop NOARGS;
467 Procedure uiprop NOARGS;
468 Procedure ulprop NOARGS;
469 int fprop ARGS((int bits_per_byte));
470 int dprop ARGS((int bits_per_byte));
471 int ldprop ARGS((int bits_per_byte));
472 Procedure efprop ARGS((int fprec, int dprec, int lprec));
473 Procedure edprop ARGS((int fprec, int dprec, int lprec));
474 Procedure eldprop ARGS((int fprec, int dprec, int lprec));
476 int setmode ARGS((char *s));
477 Procedure farewell ARGS((int bugs));
478 Procedure describe ARGS((char *description, char *extra));
479 Procedure missing ARGS((char *s));
480 Procedure fmissing ARGS((char *s));
481 Procedure check_defines NOARGS;
482 Procedure bitpattern ARGS((char *p, unsigned int size));
483 int ceil_log ARGS((int base, Long_double x));
484 Procedure croak ARGS((int place));
485 Procedure eek_a_bug ARGS((char *problem));
486 Procedure endian ARGS((int bits_per_byte));
487 int exponent ARGS((Long_double x, double *fract, int *exp));
488 int floor_log ARGS((int base, Long_double x));
489 Procedure f_define ARGS((char *desc, char *extra, char *sort, char *name,
490 int prec, Long_double val, Long_double req,
491 char *mark));
492 Procedure i_define ARGS((char *desc, char *extra, char *sort, char *name,
493 long val, long lim, long req, char *mark));
494 Procedure u_define ARGS((char *desc, char *extra, char *sort, char *name,
495 unsigned long val, unsigned long req, char *mark));
497 #ifdef NO_SIG /* There's no signal(), or setjmp/longjmp() */
499 /* Dummy routines instead */
501 int setjmp ARGS((int lab));
503 int lab=1;
504 int setjmp(lab) int lab; { return(0); }
505 Procedure signal(i, p) int i, (*p)(); {}
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);
514 #endif /*NO_SIG*/
516 int 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 */
521 char co[4], oc[4]; /* Comment starter and ender symbols */
523 int bits_per_byte; /* the number of bits per unit returned by sizeof() */
524 int flt_rounds; /* The calculated value of FLT_ROUNDS */
525 int flt_radix; /* The calculated value of FLT_RADIX */
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
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 */
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
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
558 /* Only used for testing, on a Sun with 68881 chip */
559 /* Print the FP mode */
560 printmode(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;
572 printf("\n Extended rounding precision: ");
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;
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");
593 /* Only used for testing, on a Sun with 68881 chip */
594 /* Set the FP mode */
595 int setmode(s) char *s; {
596 unsigned mode=0, dig;
597 char c;
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;
607 printmode(mode);
608 return 0;
610 #else
611 /* ARGSUSED */
612 int setmode(s) char *s; {
613 fprintf(stderr, "Can't set mode: not compiled with TEST\n");
614 return(1);
616 #endif
618 Procedure 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);
628 /* The program has received a signal where it wasn't expecting one */
629 Procedure 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 */
634 /* This is here in case alloca.c is used, which calls this. */
635 char *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);
641 return value;
644 int maxint;
646 int maximum_int() {
647 /* Find the maximum integer */
648 Volatile int newi, int_max, two=2;
650 /* Calculate maxint ***********************************/
651 /* Calculate 2**n-1 until overflow - then use the previous value */
653 newi=1; int_max=0;
655 if (setjmp(lab)==0) { /* Yields int_max */
656 while(newi>int_max) {
657 int_max=newi;
658 newi=newi*two+1;
661 Unexpected(0);
662 return int_max;
665 int main(argc, argv) int argc; char *argv[]; {
666 int dprec, fprec, lprec;
667 int i; char *s; int bad;
669 #ifdef SIGFPE
670 signal(SIGFPE, overflow);
671 #endif
672 #ifdef SIGOVER
673 signal(SIGOVER, overflow);
674 #endif
675 /* Add more calls as necessary */
677 Unexpected(1);
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;
692 } else if (*s == '+') {
693 s++;
694 bad= setmode(s);
695 } else bad= 1;
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);
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;
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");
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
729 #ifdef VERIFY
730 printf("%sVerification phase%s\n", co, oc);
731 #endif
733 #ifdef NO_SIG
734 Vprintf("%sCompiled without signal(): %s%s\n",
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();
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);
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
783 total+=(size/2);
785 size/=2;
788 Vprintf("%sMemory allocable ~= %ld Kbytes%s\n",
789 co, (total+511)/512, oc);
791 #endif
792 if (F) {
793 printf ("#endif %s _FLOAT_H___%s\n", co, oc);
795 farewell(bugs);
796 return bugs; /* To keep compilers and lint happy */
799 Procedure 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++;
805 Procedure 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);
812 Procedure 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);
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++;
836 #endif
837 Vprintf("\n");
840 Procedure 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++;
852 #endif
853 Vprintf("\n");
856 Procedure 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;
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);
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));
896 Vprintf("\n");
899 int 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;
906 int ceil_log(base, x) int base; Long_double x; {
907 int r=0;
908 while (x>1.0) { r++; x/=base; }
909 return r;
912 int 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.
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;
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;
930 } else {
931 while (x<1.0) {
932 old=x; r--; x*=10.0;
933 if (old==x) return 0;
936 if (neg) *fract= (double) -x;
937 else *fract=(double) x;
938 *exp=r;
939 return 1;
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. */
947 char *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;
957 char *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
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);
974 return buf;
977 Procedure 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;
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(" ");
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);
998 Procedure 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;
1004 char *ps= (char *) &s,
1005 *pj= (char *) &j,
1006 *pl= (char *) &l,
1007 *ab= "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1008 unsigned int mask, i, c;
1010 mask=0;
1011 for (i=1; i<=(unsigned)bits_per_byte; i++) mask= (mask<<1)|1;
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: ");
1021 Procedure missing(s) char *s; {
1022 printf("%s*** #define %s missing from limits.h%s\n", co, s, oc);
1023 bugs++;
1026 Procedure fmissing(s) char *s; {
1027 printf("%s*** #define %s missing from float.h%s\n", co, s, oc);
1028 bugs++;
1031 /* To try and fool optimisers */
1032 int false() { return 0; }
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)
1041 #define showtype(t, x) Vprintf("%s%s %s %s%s\n", co, t, sign_of(is_signed(x)), type_of(sizeof(x)), oc)
1043 char *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";
1049 if (x == sizeof(short)) {
1050 if (sizeof(short) == sizeof(int)) return "short/int";
1051 return "short";
1053 if (x == sizeof(int)) {
1054 if (sizeof(int) == sizeof(long)) return "int/long";
1055 return "int";
1057 if (x == sizeof(long)) return "long";
1058 return "unknown-type";
1061 char *ftype_of(x) int x; {
1062 if (x == sizeof(float)) {
1063 return "float";
1065 if (x == sizeof(double)) {
1066 if (sizeof(double) == sizeof(Long_double))
1067 return "(long)double";
1068 return "double";
1070 if (x == sizeof(Long_double)) {
1071 return "long double";
1073 return "unknown-type";
1076 Procedure typerr(name, esign, esize, sign, size)
1077 char *name; int esign, esize, sign, size;
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));
1084 Procedure 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));
1089 int promotions() {
1090 int si = 0; long sl = 0;
1091 unsigned int ui; unsigned long ul;
1092 short ss; unsigned short us;
1094 Vprintf("\n%sPROMOTIONS%s\n", co, oc);
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)
1108 eek_a_bug("promotions don't work properly in conditional expressions\n");
1111 showtype("unsigned short promotes to", Promoted((unsigned short) 0));
1112 showtype("long+unsigned gives", sl+ui);
1113 return 0;
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));
1118 #define fchecktype(x, n, t) if (sizeof(x) != sizeof(t)) ftyperr(n, sizeof(x), sizeof(t));
1120 Procedure check_defines() {
1121 /* ensure that all #defines are present and have the correct type */
1122 #ifdef VERIFY
1123 int usign;
1125 #ifdef NO_UI
1126 usign= Signed;
1127 #else
1128 /* Implementations promote unsigned short differently */
1129 usign= is_signed((unsigned short) 0);
1130 #endif
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) */
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 */
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 */
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
1393 int 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;
1399 Unexpected(2);
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, "");
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++;
1421 } else {
1422 Vprintf("%sCharacter overflow generates a trap!%s\n",
1423 co, oc);
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--;
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;
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);
1458 Unexpected(3);
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, "");
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, "");
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++;
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, "");
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++;
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--;
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 */
1545 return bits_per_byte;
1548 int 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;
1556 Vprintf("%sSIZES%s\n", co, oc);
1557 bits_per_byte= cprop();
1559 /* Shorts, ints and longs *****************************************/
1560 Vprintf("%sshort=%d int=%d long=%d float=%d double=%d bits %s\n",
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);
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);
1583 if (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
1590 oc);
1591 showtype("Type size_t is", sizeof(0));
1593 /* Alignment constants ********************************************/
1595 #define alignment(TYPE) \
1596 ((long)((char *)&((struct{char c; TYPE d;}*)0)->d - (char *) 0))
1598 Vprintf("\n%sALIGNMENTS%s\n", co, oc);
1600 Vprintf("%schar=%ld short=%ld int=%ld long=%ld%s\n",
1602 alignment(char), alignment(short),
1603 alignment(int), alignment(long),
1604 oc);
1606 Vprintf("%sfloat=%ld double=%ld%s\n",
1608 alignment(float), alignment(double),
1609 oc);
1611 if (stdc) {
1612 Vprintf("%slong double=%ld%s\n",
1614 alignment(Long_double),
1615 oc);
1617 Vprintf("%schar*=%ld int*=%ld func*=%ld%s\n",
1619 alignment(char *), alignment(int *), alignment(function *),
1620 oc);
1622 Vprintf("\n");
1624 /* Ten little endians *********************************************/
1626 endian(bits_per_byte);
1628 /* Pointers *******************************************************/
1630 Vprintf("\n%sPROPERTIES OF POINTERS%s\n", co, oc);
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);
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);
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);
1653 p=0; q=0;
1654 showtype("Type ptrdiff_t is", p-q);
1656 Vprintf("\n%sPROPERTIES OF INTEGRAL TYPES%s\n", co, oc);
1658 sprop();
1659 iprop();
1660 lprop();
1661 usprop();
1662 uiprop();
1663 ulprop();
1665 promotions();
1667 Unexpected(6);
1669 return bits_per_byte;
1672 #else /* not PASS0 */
1674 #ifdef SEP
1675 extern jmp_buf lab;
1676 extern int V, L, F, bugs, bits_per_byte;
1677 extern char co[], oc[];
1678 extern char *f_rep();
1679 #endif /* SEP */
1680 #endif /* ifdef PASS0 */
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.
1691 /* #undef on an already undefined thing is (wrongly) flagged as an error
1692 by some compilers, therefore the #ifdef that follows:
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
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
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
1742 #undef I_MAX
1743 #undef I_MIN
1744 #undef U_MAX
1745 #endif
1747 #ifdef PASS1
1749 /* Define the things we're going to use this pass */
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
1775 #define EPROP efprop
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 ""
1786 #define UPROP usprop
1787 #define Uname "USHRT"
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
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
1833 #endif /* PASS1 */
1835 #ifdef PASS2
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
1861 #define EPROP edprop
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 ""
1870 #define UPROP uiprop
1871 #define Uname "UINT"
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
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
1911 #endif /* PASS2 */
1913 #ifdef PASS3
1915 #ifdef STDC
1916 #define Number long double
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
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
1943 #define EPROP eldprop
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"
1954 #define UPROP ulprop
1955 #define Uname "ULONG"
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
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
1995 #endif /* PASS3 */
1997 #define UNDEFINED (-2)
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
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
2043 #ifndef VERIFY
2044 #define Validate(prec, val, req, same) {;}
2045 #endif
2047 #ifdef Integer
2049 Procedure 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;
2054 /* Calculate max short/int/long ***********************************/
2055 /* Calculate 2**n-1 until overflow - then use the previous value */
2057 newi=1; int_max=0;
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;
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);
2070 Unexpected(7);
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--;
2077 Unexpected(8);
2079 /* Now for those daft Cybers */
2081 maxeri=0; newi=int_max;
2083 if (setjmp(lab)==0) { /* Yields maxeri */
2084 for(ibits=ipower; newi>maxeri; ibits++) {
2085 maxeri=newi;
2086 newi=newi+newi+1;
2089 Unexpected(9);
2091 minneri= -maxeri;
2092 if (setjmp(lab)==0) { /* Yields minneri */
2093 if (minneri-1 < minneri) minneri--;
2095 Unexpected(10);
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);
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);
2108 if(int_max < 0) { /* It has happened */
2109 eek_a_bug("signed integral comparison faulty?");
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);
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);
2129 Procedure 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;
2135 if (setjmp(lab)==0) { /* Yields u_max */
2136 while(newi>u_max) {
2137 u_max=newi;
2138 newi=newi*two+1;
2141 Unexpected(11);
2142 Vprintf("%sMaximum unsigned %s = %lu%s\n",
2143 co, INT, (unsigned long) u_max, oc);
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);
2158 #endif
2161 #endif /* Integer */
2163 #ifdef Number
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.
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
2177 Procedure Store ARGS2(Number, a, Number *, b) { *b=a; }
2178 Number Sum ARGS2(Number, a, Number, b) {Number r; Store(a+b, &r); return (r); }
2179 Number Diff ARGS2(Number, a, Number, b){Number r; Store(a-b, &r); return (r); }
2180 Number Mul ARGS2(Number, a, Number, b) {Number r; Store(a*b, &r); return (r); }
2181 Number Div ARGS2(Number, a, Number, b) {Number r; Store(a/b, &r); return (r); }
2182 Number Self ARGS1(Number, a) {Number r; Store(a, &r); return (r); }
2184 Procedure F_check ARGS((int precision, Long_double val1));
2186 Procedure 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.
2199 Number val, new, diff;
2200 double rem;
2201 int e;
2202 char *rep;
2203 char *f2;
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";
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;
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 */
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;
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;
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);
2276 #ifdef VERIFY
2277 Procedure 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);
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);
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");
2307 #endif /* VERIFY */
2309 int 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.
2314 Returns the number of digits in the fraction.
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;
2327 Unexpected(18);
2329 Vprintf("%sPROPERTIES OF %s%s\n", co, THING, oc);
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);
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);
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);
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++;
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 */
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 */
2395 basem1=Diff(base, HALF);
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 */
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 */
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;
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);
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);
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++;
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;
2463 b=a;
2464 while (Diff(Diff(ONE, a), ONE) == ZERO) {
2465 a*=base;
2466 negeps--;
2468 negeps= -negeps;
2469 Vprintf("%sSmallest x such that 1.0-base**x != 1.0 = %d%s\n",
2470 co, negeps, oc);
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));
2483 eps= etop;
2484 /* Sanity check */
2485 if (Diff(ONE, etop) >= ONE || Diff(ONE, ebot) != ONE) {
2486 eek_a_bug("internal error calculating epsneg");
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);
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;
2499 /* epsneg is used later */
2500 Unexpected(20);
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);
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));
2519 /* Sanity check */
2520 if (Sum(ONE, etop) <= ONE || Sum(ONE, ebot) != ONE) {
2521 eek_a_bug("internal error calculating eps");
2523 f_epsilon=etop;
2525 Vprintf("%sSmallest x such that 1.0+x != 1.0 = %s%s\n",
2526 co, f_rep(digs, (Long_double) f_epsilon), oc);
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);
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);
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);
2550 /* Size of and minimum normalised exponent ************************/
2551 y=0; i=0; k=1; z=basein; z1=(1.0+f_epsilon)/base;
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);
2568 Unexpected(23);
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;
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);
2592 Unexpected(24);
2594 f_min_exp=(-k)+1;
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, "");
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");
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");
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++;
2631 Unexpected(26);
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, "");
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);
2648 Unexpected(27);
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");
2662 Unexpected(28);
2663 } else {
2664 normal= 1;
2665 Vprintf("%sThe smallest numbers are normalised%s\n", co, oc);
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;
2679 if (Div(newxmax, base) != f_max) {
2680 inf=1; /* ieee infinity */
2681 break;
2683 f_max_exp++;
2685 Unexpected(29);
2686 if (trap) {
2687 Vprintf("%s%s overflow generates a trap%s\n", co, Thing, oc);
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, "");
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);
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");
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");
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++;
2726 Unexpected(30);
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, "");
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;
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",
2754 "*** Something fishy here!",
2755 "Exponent size + significand size doesn't match",
2756 "with the size of a", thing,
2757 oc);
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);
2765 is_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 ");
2772 if (normal) Vprintf("the normalisation is unusual");
2773 Vprintf("%s\n", oc);
2775 } else {
2776 Vprintf("%sIt doesn't look like IEEE format%s\n",
2777 co, oc);
2780 printf("\n"); /* regardless of verbosity */
2781 return f_mant_dig;
2784 Procedure 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.
2790 Volatile int eprec;
2791 Volatile double a, b, base, old;
2792 Volatile Number d, oldd, dbase, one, zero;
2793 Volatile int bad=0;
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;
2802 /* Avoid the comparison if bad is set,
2803 to avoid trouble on the convex. */
2804 if (!bad && (a <= old)) bad=1;
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;
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;
2824 Unexpected(31);
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);
2848 #else /* not Number */
2850 #ifdef FPROP /* Then create dummy routines for long double */
2851 /* ARGSUSED */
2852 int FPROP(bits_per_byte) int bits_per_byte; { return 0; }
2853 #endif
2854 #ifdef EPROP
2855 /* ARGSUSED */
2856 Procedure EPROP(fprec, dprec, lprec) int fprec, dprec, lprec; {}
2857 #endif
2859 #endif /* ifdef Number */
2861 /* Increment the pass number */
2862 #undef PASS
2864 #ifdef PASS2
2865 #undef PASS2
2866 #define PASS 3
2867 #define PASS3 1
2868 #endif
2870 #ifdef PASS1
2871 #undef PASS1
2872 #define PASS 2
2873 #define PASS2 1
2874 #endif
2876 #ifdef PASS0
2877 #undef PASS0
2878 #endif
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 */