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