2 Every thing you wanted to know about your compiler but didn't know whom to ask.
4 COPYRIGHT(c) 1993-9 Steven Pemberton, CWI. All rights reserved.
5 Steven Pemberton, CWI, Amsterdam; "Steven.Pemberton@cwi.nl"
8 Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
9 This program and the accompanying materials
10 are licensed and made available under the terms and conditions of the BSD License
11 which accompanies this distribution. The full text of the license may be found at
12 http://opensource.org/licenses/bsd-license.
14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
15 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #if defined(_MSC_VER) /* Handle Microsoft VC++ compiler specifics. */
18 #pragma warning ( disable : 4018 )
19 #pragma warning ( disable : 4055 )
20 #pragma warning ( disable : 4116 )
21 #pragma warning ( disable : 4130 )
22 #pragma warning ( disable : 4189 )
23 #pragma warning ( disable : 4244 )
24 #pragma warning ( disable : 4723 )
25 #endif /* defined(_MSC_VER) */
27 //#define NO_SC 1 // Compiler doesn't support signed char
28 //#define NO_UC 1 // Compiler doesn't support unsigned char
29 //#define NO_UI 1 // Compiler doesn't support unsigned short and long
30 //#define NO_VOID 1 // Compiler doesn't support void
31 //#define NO_SIG 1 // Compiler doesn't support signal() or setjmp/longjmp()
33 /* Some compilers can't cope with "#ifdef __FILE__". Use
34 either the FILENAME or BAD_CPP macro as described below.
36 /* If your C preprocessor doesn't have the predefined __FILE__
37 macro, and you don't want to call this file enquire.c but, say,
38 tell.c, uncomment the following and change enquire.c to tell.c.
40 //#define FILENAME "enquire.c"
42 /* Some compilers won't accept the line "#include FILENAME". Uncomment
43 the following macro. In that case, this file *must* be called enquire.c.
47 /* Some naughty compilers define __STDC__, but don't really
48 support it. Some define it as 0, in which case we ignore it.
49 But if your compiler defines it, and isn't really ANSI C,
50 uncomment the BAD_STDC macro. (To those compiler writers: for shame).
54 /* Some naughty compilers define __STDC__, but don't have the
55 stddef.h include file. Uncomment the BAD_STDDEF macro. (Gcc needs this on
56 some machines, due to clashes between stddef.h and other include files.)
58 //#define BAD_STDDEF 1
60 /* Some systems crash when you try to malloc all store. To save users of such
61 defective systems too much grief, they may uncomment the BAD_MALLOC macro,
62 which ignores that bit of the code.
64 //#define BAD_MALLOC 1
69 #define PROGRAM enquire.c
70 #define VERSION "5.1a"
71 #define PURPOSE Everything you wanted to know about your machine and C compiler
72 #define BUT didnt know who to ask
73 #define FOR Any OS, any C compiler
74 #define AUTHOR Steven Pemberton, CWI, Amsterdam; "Steven.Pemberton@cwi.nl"
75 #define COPYRIGHT(c) 1993-9 Steven Pemberton, CWI. All rights reserved.
76 #define NOTE Improvements gratefully received. Please mention the version.
77 #define COMPILE On Unix compile with: "sh enquire.c"; see below for details
78 #define WEB "http://www.cwi.nl/~steven/enquire.html"
81 #ifdef NOTDEFINED /* This is how you compile it; see below for details */
84 sh
) echo
'Use "sh enquire.c", not "sh < enquire.c"' >&2; exit
1;;
85 *) echo
'Filename must end in ".c"' >&2; exit
1;;
88 then echo Would overwrite test
.c
- try it somewhere safer
>&2; exit
1
91 echo Testing
for needed CFLAGS
...
92 echo
"main(){char c; c=0;}" > test
.c
93 if $
{CC
=cc
} $
{1+"$@"} -o enquire test
.c $LIBS
96 echo
'*** "'$CC $
{1+"$@"} -o enquire test
.c $LIBS
'" failed'
101 echo
"main(){signed char c; c=0;}" > test
.c
102 if $CC $
{1+"$@"} -o enquire test
.c $LIBS
2>/dev
/null
103 then echo
" Signed char ok"
106 echo
" Signed char not accepted; using $CFLAGS"
108 echo
"main(){unsigned char c; c=0;}" > test
.c
109 if $CC $
{1+"$@"} -o enquire test
.c $LIBS
2>/dev
/null
110 then echo
" Unsigned char ok"
112 CFLAGS
="$CFLAGS -DNO_UC"
113 echo
" Unsigned char not accepted; using $CFLAGS"
115 echo
"main(){unsigned short s;unsigned long l;s=0;l=0;}" > test
.c
116 if $CC $
{1+"$@"} -o enquire test
.c $LIBS
2>/dev
/null
117 then echo
" Unsigned short and long ok"
119 CFLAGS
="$CFLAGS -DNO_UI"
120 echo
" Unsigned short or long not accepted; using $CFLAGS"
122 echo
"void foo(){} main(){foo();}" > test
.c
123 if $CC $
{1+"$@"} -o enquire test
.c $LIBS
2>/dev
/null
126 CFLAGS
="$CFLAGS -DNO_VOID"
127 echo
" Void not accepted; using $CFLAGS"
129 /bin
/rm
-f test
.c a
.out
131 echo Compiling $
0 ...
133 0) : check bug in interpreting
"$@" in some shells
, if no parameters
134 case `echo
1 "$@" 2` in
135 "1 2") echo
' *** There is a bug in your shell expanding "$@"!'
136 echo
' *** Taking remedial action' ;;
141 "") echo
" $CC" $CFLAGS
"$@" $
0 -o enquire $LIBS
142 $CC $CFLAGS $
{1+"$@"} $
0 -o enquire $LIBS
||
143 { echo
'***' Try setting some CFLAGS
; exit
1; }
145 *) echo
" $CC" $CFLAGS
"$@" -DID
="\"$ID\"" $
0 -o enquire $LIBS
146 $CC $CFLAGS $
{1+"$@"} -DID
="\"$ID\"" $
0 -o enquire $LIBS
||
147 { echo
'***' Try setting some CFLAGS
; exit
1; }
149 echo
"Producing enquire.out limits.h and float.h ..."
150 echo
" enquire > enquire.out"
151 ./enquire
> enquire
.out
|| echo
' *** Some problems: see enquire.out'
152 echo
" enquire -l > limits.h"
153 ./enquire
-l
> limits
.h
|| echo
' *** Some problems: see limits.h'
154 echo
" enquire -f > float.h"
155 ./enquire
-f
> float.h
|| echo
' *** Some problems: see float.h'
156 echo
"Verifying the contents of limits.h and float.h ..."
157 echo
" $CC" -DVERIFY $CFLAGS
"$@" $
0 -o verify $LIBS
158 $CC
-DVERIFY $CFLAGS $
{@
+"$@"} $
0 -o verify $LIBS
||
159 { echo
'***' Failed
; exit
1; }
160 echo
" verify -fl > verify.out"
161 ./verify
-fl
> verify
.out
||
162 echo
' *** Some problems: see verify.out'
169 This is a program that determines many properties of the C
170 compiler and machine that it is run on, such as minimum and
171 maximum [un]signed char/int/long, many properties of float/ [long]
174 As an option it produces the ANSI C float.h and limits.h files.
176 As a further option, it even checks that the compiler reads the
177 header files correctly.
179 It is a good test-case for compilers, since it exercises them with
180 many limiting values, such as the minimum and maximum floating-point
183 COMPILING AND RUNNING ON UNIX MACHINES
184 With luck and a following wind, on Unix systems just the following
186 sh enquire.c (or whatever filename you chose).
187 Any parameters are passed to the C compiler, so if the compilation
188 fails for any reason curable as explained below, you can do the following:
189 sh enquire.c -DBAD_CPP
191 If you do get compilation errors, check the line in question.
192 Very often there is a comment attached saying which define to set.
194 You can use a different C compiler than the default cc by setting CC:
195 CC=gcc sh enquire.c -ansi
196 You can load extra libraries by setting LIBS:
197 CC=gcc LIBS=-lflong sh enquire.c -ansi
198 Add ID="string" for the string to be added to the output; for instance:
199 ID="`hostname` cc -ansi" sh enquire.c -ansi
201 Compiling may give messages about unreachable code. These you can ignore.
203 Some compilers offer various flags for different floating point
204 modes; it's worth trying all possible combinations of these.
206 Don't say I haven't tried to make life easy for you...
208 COMPILING AND RUNNING ON NON-UNIX SYSTEMS
209 On non-Unix systems, you must say (the equivalent of):
210 cc enquire.c -o enquire
211 enquire > enquire.out
212 enquire -l > limits.h
214 cc -DVERIFY enquire.c -o verify #this includes limits.h and float.h
215 verify -fl > verify.out
217 If your compiler doesn't support: add flag:
218 signed char (eg pcc) -DNO_SC
219 unsigned char -DNO_UC
220 unsigned short and long -DNO_UI
222 signal(), or setjmp/longjmp() -DNO_SIG
224 Try to compile first with no flags, and see if you get any errors
225 - you might be surprised. (Most non-ANSI compilers need -DNO_SC,
226 though.) Some compilers need a -f flag for floating point.
228 Don't use any optimisation flags: the program may not work if you
229 do. Though "while (a+1.0-a-1.0 == 0.0)" may look like "while(1)"
230 to an optimiser, to a floating-point unit there's a world of difference.
232 Compiling may give messages about unreachable code. These you can ignore.
234 Some compilers offer various flags for different floating point
235 modes; it's worth trying all possible combinations of these.
238 Because of bugs and/or inadequacies, some compilers need the following
241 - If your C preprocessor doesn't have the predefined __FILE__
242 macro, and you don't want to call this file enquire.c but, say,
243 tell.c, add the flag -DFILENAME=\"tell.c\" .
245 - Some compilers won't accept the line "#include FILENAME". Add
246 flag -DBAD_CPP. In that case, this file *must* be called
249 - Some compilers can't cope with "#ifdef __FILE__". Use
250 -DFILENAME= or -DBAD_CPP as above.
252 - Some naughty compilers define __STDC__, but don't really
253 support it. Some define it as 0, in which case we ignore it.
254 But if your compiler defines it, and isn't really ANSI C, add
255 flag -DBAD_STDC. (To those compiler writers: for shame).
257 - Some naughty compilers define __STDC__, but don't have the
258 stddef.h include file. Add flag -DBAD_STDDEF. (Gcc needs this
259 on some machines, due to clashes between stddef.h and other
262 - Some systems crash when you try to malloc all store. To save
263 users of such defective systems too much grief, they may
264 compile with -DBAD_MALLOC, which ignores that bit of the code.
266 Summary of naughty-compiler flags:
267 If your compiler doesn't support: add flag:
268 __FILE__ (and you changed the filename) -DFILENAME=\"name.c\"
269 #ifdef __FILE__ -DBAD_CPP or -DFILENAME=...
270 #include FILENAME -DBAD_CPP
271 __STDC__ (properly) -DBAD_STDC
272 stddef.h -DBAD_STDDEF
273 malloc(LOTS) == NULL -DBAD_MALLOC
275 While it is not our policy to support defective compilers, pity has been
276 taken on people with compilers that can't produce object files bigger than
277 32k (especially since it was an easy addition). Compile the program
278 into separate parts like this:
279 cc -c -DSEP -DPASS0 -o p0.o <other flags> enquire.c
280 cc -c -DSEP -DPASS1 -o p1.o <other flags> enquire.c
281 cc -c -DSEP -DPASS2 -o p2.o <other flags> enquire.c
282 cc -c -DSEP -DPASS3 -o p3.o <other flags> enquire.c
283 cc -o enquire p0.o p1.o p2.o p3.o
286 You may possibly need to add some calls to signal() for other sorts of
287 exception on your machine than SIGFPE, SIGOVER, SIGBUS, and SIGSEGV.
288 See lines beginning #ifdef SIGxxx (and communicate the differences to me!).
291 Running without argument gives the information as English text. If run
292 with argument -l (e.g. enquire -l), output is a series of #define's for
293 the ANSI standard limits.h include file, excluding MB_MAX_CHAR. If run
294 with argument -f, output is a series of #define's for the ANSI standard
295 float.h include file (according to ANSI C Draft of Dec 7, 1988).
296 Flag -v gives verbose output: output includes the English text above
297 as C comments. The program exit(0)'s if everything went ok, otherwise
298 it exits with a positive number, telling how many problems there were.
300 VERIFYING THE COMPILER
301 If, having produced the float.h and limits.h header files, you want to
302 verify that the compiler reads them back correctly (there are a lot of
303 boundary cases, of course, like minimum and maximum numbers), you can
304 recompile enquire.c with -DVERIFY set (plus the other flags that you used
305 when compiling the version that produced the header files). This then
306 recompiles the program so that it #includes "limits.h" and "float.h",
307 and checks that the constants it finds there are the same as the
308 constants it produces. Run the resulting program with enquire -fl.
309 Many compilers fail this test.
310 NB: You *must* recompile with the same compiler and flags, otherwise
311 you may get odd results.
313 You can also use this option if your compiler already has both files,
314 and you want to confirm that this program produces the right results.
317 This program is now quite trustworthy, and suspicious and wrong output
318 may well be caused by bugs in the compiler, not in the program (however
319 of course, this is not guaranteed, and no responsibility can be
322 The program only works if overflows are ignored by the C system or
323 are catchable with signal().
325 If the program fails to run to completion (often with the error message
326 "Unexpected signal at point x"), this often turns out to be a bug in the
327 C compiler's run-time system. Check what was about to be printed, and
328 try to narrow the problem down.
330 Another possible problem is that you have compiled the program to produce
331 loss-of-precision arithmetic traps. The program cannot cope with these,
332 and you should re-compile without them. (They should never be the default).
334 Make sure you compiled with optimisation turned off.
336 Output preceded by *** WARNING: identifies behaviour of the C system
337 deemed incorrect by the program. Likely problems are that printf or
338 scanf don't cope properly with certain boundary numbers: this program
339 goes to a lot of trouble to calculate its values, and these values
340 are mostly boundary numbers. Experience has shown that often printf
341 cannot cope with these values, and so in an attempt to increase
342 confidence in the output, for each float and double that is printed,
343 the printed value is checked by using sscanf to read it back.
344 Care is taken that numbers are printed with enough digits to uniquely
345 identify them, and therefore that they can be read back identically.
346 If the number read back is different, then there is probably a bug in
347 printf or sscanf, and the program prints the warning message.
348 If the two numbers in the warning look identical, then printf is more
349 than likely rounding the last digit(s) incorrectly. To put you at ease
350 that the two really are different, the bit patterns of the two numbers
351 are also printed. The difference is very likely in the last bit.
352 Many scanf's read the minimum double back as 0.0, and similarly cause
353 overflow when reading the maximum double. This program quite ruthlessly
354 declares all these behaviours faulty. The point is that if you get
355 one of these warnings, the output may be wrong, so you should check
356 the result carefully if you intend to use the results. Of course, printf
357 and sscanf may both be wrong, and cancel each other out, so you should
358 check the output carefully anyway.
360 The warning that "a cast didn't work" refers to cases like this:
363 #define C 1.234567890123456789
365 if (f != (float) C) printf ("Wrong!");
367 A faulty compiler will widen f to double and ignore the cast to float,
368 and because there is more accuracy in a double than a float, fail to
369 recognise that they are the same. In the actual case in point, f and C
370 are passed as parameters to a function that discovers they are not equal,
371 so it's just possible that the error was in the parameter passing,
372 not in the cast (see function Verify()).
373 For ANSI C, which has float constants, the error message is "constant has
377 If the program doesn't work for you for any reason that can't be
378 narrowed down to a problem in the C compiler, or it has to be
379 changed in order to get it to compile, or it produces suspicious
380 output (like a very low maximum float, for instance), please mail
381 the problem and an example of the incorrect output to
382 Steven.Pemberton@cwi.nl so that improvements can be worked into
383 future versions. Try to give as much information as possible;
384 DON'T FORGET TO MENTION THE VERSION NUMBER!
386 The program tries to catch and diagnose bugs in the compiler/run-time
387 system. I would be especially pleased to have reports of failures so
388 that I can improve this service.
390 I apologise unreservedly for the contorted use of the preprocessor...
394 Worried that you may not have the latest version? Ftp to
395 ftp.cwi.nl, and look in directory pub/steven/enquire
396 for file enquireXX.c; XX is the version number. Or look at
397 http://www.cwi.nl/~steven/enquire.html
399 HOW DOES ENQUIRE WORK?
400 There is an article that explains a lot of the workings: The
401 Ergonomics of Portability; available from the above addresses as file
405 This is not a public domain program; nor is any other program that
406 carries a copyright notice. It is however freely copyable under the
407 following conditions:
409 You may copy and distribute verbatim copies of this source file.
410 You may modify this source file, and copy and distribute such
411 modified versions, provided that you leave the copyright notice
412 at the top of the file and also cause the modified file to carry
413 prominent notices stating that you changed the files and the
414 date of any change; and cause the whole of any work that you
415 distribute or publish, that in whole or in part contains or is a
416 derivative of this program or any part thereof, to be licensed
417 at no charge to all third parties on terms identical to those
420 While every effort has been taken to make this program as reliable as
421 possible, no responsibility can be taken for the correctness of the
422 output, nor suitability for any particular use.
424 If you do have a fix to any problem, please send it to me, so that
425 other people can have the benefits.
427 This program is an offshoot of a project funded by public funds.
428 If you use this program for research or commercial use (i.e. more
429 than just for the fun of knowing about your compiler) mailing a short
430 note of acknowledgement may help keep enquire.c supported.
433 Many people have given time and ideas to making this program what it is.
434 To all of them thanks, and apologies for not mentioning them by name.
437 Originally started as a program to generate configuration constants
438 for a large piece of software we were writing, which later took on
440 1.0 Length 6658!; end 1984?
441 Unix only. Only printed a dozen maximum int/double values.
442 2.0 Length 10535; Spring 1985
443 Prints values as #defines (about 20 of them)
444 More extensive floating point, using Cody and Waite
445 Handles signals better
446 Programs around optimisations
448 3.0 Length 12648; Aug 1987; prints about 42 values
449 Added PASS stuff, so treats float as well as double
450 4.0 Length 33891; Feb 1989; prints around 85 values
451 First GNU version (for gcc, where they called it hard-params.c)
452 Generates float.h and limits.h files
454 Generates warnings for dubious output
455 4.1 Length 47738; April 1989
456 Added VERIFY and TEST
457 4.2 Length 63442; Feb 1990
460 Added check for pseudo-unsigned chars
461 Added description for each #define output
462 Added check for absence of defines during verify
464 Added BAD_STDC and BAD_CPP
465 Fixed alignments output
466 4.3 Length 75000; Oct 1990; around 114 lines of output
467 Function xmalloc defined, Richard Stallman, June 89.
468 Alignments computed from member offsets rather than structure sizes,
469 Richard Stallman, Oct 89
470 Print whether char* and int* pointers have the same format;
471 also char * and function *
472 Update to Draft C version Dec 7, 1988
473 - types of constants produced in limits.h
474 (whether to put a U after unsigned shorts and chars and
475 whether to output -1024 as (-1023-1))
476 - values of SCHAR_MIN/MAX
477 - values of *_EPSILON (not the smallest but the effective smallest)
478 Added FILENAME, since ANSI C doesn't allow #define __FILE__
479 Renamed from config.c to enquire.c
480 Added size_t and ptrdiff_t enquiries
481 Added promotion enquiries
482 Added type checks of #defines
484 Changed endian to allow for cases where not all bits are used
485 Sanity check for max integrals
486 Fixed definition of setjmp for -DNO_SIG
487 Moved #define ... 0.0L inside #ifdef STDC, in case some cpp's tokenize
489 5.0 Length 88228; February 1993; around 120 lines of output
490 (depends on what you count)
491 Added the 'sh enquire.c' horror/delight: thanks David Mankins@think
492 Added checks for long names: thanks Steve Simon@leeds-poly
493 Added FPE signal checks: thanks Leonid A. Broukhis
494 Added check for dereferencing NULL
496 Added LIBS, fixed showtype: thanks Rainer Orth@TechFak.Uni-Bielefeld.DE
497 Added a free(): thanks nickc@perihelion.co.uk
498 Added signal catching to the malloc part
499 Renamed naughty-compiler defines to BAD_*
500 Renamed and altered Verify() to better check faulty compilers
501 Shut some compilers up from giving incorrect warnings.
502 Fixed sign_of(): thanks Hugh Redelmeier@redvax
503 Fixed USHRT_MAX for sizeof(short)=sizeof(int) but INT_MAX > SHRT_MAX
505 Fixed -DSEP: thanks Mike Black@seismo
506 Fixed the case where stdio.h includes limits.h: thanks rms@gnu
507 Fixed exponent(): thanks Christophe BINOT
508 <chb%hpvpta.france.hp.com@hplb.hpl.hp.com>
510 Made handling of ID= easier
511 Improved the reporting of use of bits in Floating values.
512 5.1 Length 88739; Sep 1998
513 Fixed detection of infinity for machines with no overflow trap
514 Speeded up search for max char (first 32 bit char machine turned up...)
515 5.1a Length 88832; Feb 1999
516 Changed identification message
517 5.1b Length 88926; Oct 2002
518 Fixed a missing \n in an output line; thanks Leonid Broukhis again
521 /* Set FILENAME to the name of this file */
524 #define FILENAME "enquire.c"
526 #ifdef __FILE__ /* It's a compiler bug if this fails. Define BAD_CPP */
527 #define FILENAME __FILE__
529 #define FILENAME "enquire.c"
530 #endif /* __FILE__ */
532 #endif /* FILENAME */
534 /* This file is read three times (it #includes itself), to generate
535 otherwise identical code for each of short+float, int+double,
536 long+long double. If PASS isn't defined, then this is the first pass.
537 Code bracketed by 'PASS0' is for stuff independent of all three,
538 but is read during the first pass.
541 #ifdef SEP /* so we're only interested if this is pass 1 or not */
547 #else /* no SEP, so this is the first pass */
553 /* Void just marks the functions that don't return a result */
560 /* Set STDC to whether this is *really* an ANSI C compiler.
561 Some bad compilers define __STDC__, when they don't support it.
562 Compile with -DBAD_STDC to get round this.
566 #if __STDC__ /* If __STDC__ is 0, assume it isn't supported */
572 /* Stuff different for ANSI C, and old C:
573 ARGS and NOARGS are used for function prototypes.
574 Volatile is used to reduce the chance of optimisation,
575 and to prevent variables being put in registers (when setjmp/longjmp
576 wouldn't work as we want)
577 Long_double is the longest floating point type available.
578 stdc is used in tests like "if (stdc)", which is less ugly than #ifdef.
579 U is output after unsigned constants.
584 #define NOARGS (void)
585 #define Volatile volatile
586 #define Long_double long double
590 #else /* Old style C */
594 #define Volatile static
595 #define Long_double double
607 #include <stddef.h> /* for size_t: if this fails, define BAD_STDDEF */
614 #include <signal.h> /* if this fails, define NO_SIG */
615 #include <setjmp.h> /* if this fails, define NO_SIG */
618 //#include <signal.h> /* if this fails, define NO_SIG */
619 //#include <setjmp.h> /* if this fails, define NO_SIG */
622 /* Kludge around the possiblity that <stdio.h> includes <limits.h> */
638 /* The largest unsigned type */
640 #define ulong unsigned int
642 #define ulong unsigned long
645 /* Some shorthands */
646 #define Vprintf if (V) printf
647 #define Unexpected(place) if (setjmp(lab)!=0) croak(place)
648 #define fabs(x) (((x)<0.0)?(-x):(x))
652 /* A description of the ANSI constants */
653 #define D_CHAR_BIT "Number of bits in a storage unit"
654 #define D_CHAR_MAX "Maximum char"
655 #define D_CHAR_MIN "Minimum char"
656 #define D_SCHAR_MAX "Maximum signed char"
657 #define D_SCHAR_MIN "Minimum signed char"
658 #define D_UCHAR_MAX "Maximum unsigned char (minimum is always 0)"
660 #define D_INT_MAX "Maximum %s"
661 #define D_INT_MIN "Minimum %s"
662 #define D_UINT_MAX "Maximum unsigned %s (minimum is always 0)"
664 #define D_FLT_ROUNDS "Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown"
665 #define D_FLT_RADIX "Radix of exponent representation"
666 #define D_MANT_DIG "Number of base-FLT_RADIX digits in the significand of a %s"
667 #define D_DIG "Number of decimal digits of precision in a %s"
668 #define D_MIN_EXP "Minimum int x such that FLT_RADIX**(x-1) is a normalised %s"
669 #define D_MIN_10_EXP "Minimum int x such that 10**x is a normalised %s"
670 #define D_MAX_EXP "Maximum int x such that FLT_RADIX**(x-1) is a representable %s"
671 #define D_MAX_10_EXP "Maximum int x such that 10**x is a representable %s"
672 #define D_MAX "Maximum %s"
673 #define D_EPSILON "Difference between 1.0 and the minimum %s greater than 1.0"
674 #define D_MIN "Minimum normalised %s"
678 /* Prototypes for what's to come: */
683 char *malloc (); /* Old style prototype, since we don't know what size_t is */
685 char *malloc
ARGS((size_t size
));
687 Void free
ARGS((char *p
)); /* Syntax error here? Try -DNO_VOID */
689 Void exit
ARGS((int status
));
691 char *f_rep
ARGS((int precision
, Long_double val
));
693 int maximum_int NOARGS
;
702 int fprop
ARGS((int byte_size
));
703 int dprop
ARGS((int byte_size
));
704 int ldprop
ARGS((int byte_size
));
705 Void efprop
ARGS((int fprec
, int dprec
, int lprec
));
706 Void edprop
ARGS((int fprec
, int dprec
, int lprec
));
707 Void eldprop
ARGS((int fprec
, int dprec
, int lprec
));
709 int setmode
ARGS((char *s
));
710 Void farewell
ARGS((int bugs
));
711 Void describe
ARGS((char *description
, char *extra
));
712 Void missing
ARGS((char *s
));
713 Void fmissing
ARGS((char *s
));
714 Void check_defines NOARGS
;
715 Void bitpattern
ARGS((char *p
, unsigned int size
));
716 int ceil_log
ARGS((int base
, Long_double x
));
717 Void croak
ARGS((int place
));
718 Void trap1
ARGS((int sig
));
719 Void eek_a_bug
ARGS((char *problem
));
720 Void endian
ARGS((int byte_size
));
721 int exponent
ARGS((Long_double x
, Long_double
*fract
, int *exp
));
722 int floor_log
ARGS((int base
, Long_double x
));
723 Void f_define
ARGS((char *desc
, char *extra
, char *sort
, char *name
,
724 int prec
, Long_double val
, char *mark
));
725 Void i_define
ARGS((char *desc
, char *extra
, char *sort
, char *name
,
726 long val
, long lim
, long req
, char *mark
));
727 Void u_define
ARGS((char *desc
, char *extra
, char *sort
, char *name
,
728 ulong val
, ulong req
, char *mark
));
730 #ifdef NO_SIG /* There's no signal(), or setjmp/longjmp() */
732 /* Dummy routines instead */
735 int setjmp
ARGS((jmp_buf lab
));
738 int setjmp(jmp_buf lab
) { return(0); }
739 void longjmp(jmp_buf lab
, int val
) { return; }
741 Void
signal(int i
, void (*p
)()) {}
745 Void
overflow(int sig
)
746 { /* what to do on over/underflow */
747 signal(sig
, overflow
);
751 Void
address(int sig
)
752 { /* what to do on an address error */
753 signal(sig
, address
);
759 int V
= 0, /* verbose */
760 L
= 0, /* produce limits.h */
761 F
= 0, /* produce float.h */
762 bugs
=0; /* The number of (possible) bugs in the output */
764 char co
[4], oc
[4]; /* Comment starter and ender symbols */
766 int bits_per_byte
; /* the number of bits per unit returned by sizeof() */
767 int flt_rounds
; /* The calculated value of FLT_ROUNDS */
768 int flt_radix
; /* The calculated value of FLT_RADIX */
769 Volatile
int trapped
; /* For testing FPE traps */
772 /* Set the fp modes on a SUN with 68881 chip, to check that different
773 rounding modes etc. get properly detected.
774 Compile with -f68881 for cc, -m68881 for gcc, and with additional flag
775 -DTEST. Run with additional parameter +hex-number, to set the 68881 mode
776 register to hex-number
779 /* Bits 0x30 = rounding mode */
780 #define ROUND_BITS 0x30
781 #define TO_NEAREST 0x00
783 #define TO_MINUS_INF 0x20
784 #define TO_PLUS_INF 0x30 /* The SUN FP user's guide seems to be wrong here */
786 /* Bits 0xc0 = extended rounding */
787 #define EXT_BITS 0xc0
788 #define ROUND_EXTENDED 0x00
789 #define ROUND_SINGLE 0x40
790 #define ROUND_DOUBLE 0x80
793 #define EXE_INEX1 0x100
794 #define EXE_INEX2 0x200
796 #define EXE_UNFL 0x800
797 #define EXE_OVFL 0x1000
798 #define EXE_OPERR 0x2000
799 #define EXE_SNAN 0x4000
800 #define EXE_BSUN 0x8000
802 /* Only used for testing, on a Sun with 68881 chip */
803 /* Print the FP mode */
804 printmode(new) unsigned new; {
806 printf("New fp mode:\n");
807 printf(" Round toward ");
808 switch (new & ROUND_BITS
) {
809 case TO_NEAREST
: printf("nearest"); break;
810 case TO_ZERO
: printf("zero"); break;
811 case TO_MINUS_INF
: printf("minus infinity"); break;
812 case TO_PLUS_INF
: printf("plus infinity"); break;
813 default: printf("???"); break;
816 printf("\n Extended rounding precision: ");
818 switch (new & EXT_BITS
) {
819 case ROUND_EXTENDED
: printf("extended"); break;
820 case ROUND_SINGLE
: printf("single"); break;
821 case ROUND_DOUBLE
: printf("double"); break;
822 default: printf("???"); break;
825 printf("\n Enabled exceptions:");
826 if (new & (unsigned) EXE_INEX1
) printf(" inex1");
827 if (new & (unsigned) EXE_INEX2
) printf(" inex2");
828 if (new & (unsigned) EXE_DZ
) printf(" divz");
829 if (new & (unsigned) EXE_UNFL
) printf(" unfl");
830 if (new & (unsigned) EXE_OVFL
) printf(" ovfl");
831 if (new & (unsigned) EXE_OPERR
) printf(" operr");
832 if (new & (unsigned) EXE_SNAN
) printf(" snan");
833 if (new & (unsigned) EXE_BSUN
) printf(" bsun");
837 /* Only used for testing, on a Sun with 68881 chip */
838 /* Set the FP mode */
839 int setmode(s
) char *s
; {
840 unsigned mode
=0, dig
;
845 if (c
>='0' && c
<='9') dig
= c
-'0';
846 else if (c
>='a' && c
<='f') dig
= c
-'a'+10;
847 else if (c
>='A' && c
<='F') dig
= c
-'A'+10;
857 #ifdef TESTI /* Test mode using SunOs IEEE routines */
859 #include <sys/ieeefp.h>
861 int setmode(char *s
) {
862 char *dummy
, c
, *cmd
, *val
;
865 case '=': cmd
= "direction"; val
= "nearest"; break;
866 case '0': cmd
= "direction"; val
= "tozero"; break;
867 case '+': cmd
= "direction"; val
= "positive"; break;
868 case '-': cmd
= "direction"; val
= "negative"; break;
869 case '1': cmd
= "precision"; val
= "single"; break;
870 case '2': cmd
= "precision"; val
= "double"; break;
871 case '3': cmd
= "precision"; val
= "extended"; break;
872 case '~': cmd
= "exception"; val
= "inexact"; break;
873 case '/': cmd
= "exception"; val
= "division"; break;
874 case '>': cmd
= "exception"; val
= "overflow"; break;
875 case '<': cmd
= "exception"; val
= "underflow"; break;
877 printf("Bad setmode character: %c\n", c
);
881 printf("Set %s %s", cmd
, val
);
882 if (ieee_flags("set", cmd
, val
, &dummy
)) {
883 printf(": failed\n");
898 fprintf(stderr
, "Can't set mode: not compiled with TEST\n");
911 /* See if two blocks of store are identical */
913 if (size1
!= size2
) return 0;
914 for (i
=1; i
<=size1
; i
++) {
915 if (*p1
++ != *p2
++) return 0;
923 if (bugs
== 0) exit(0);
924 printf("\n%sFor hints on dealing with the ", co
);
925 if (bugs
== 1) printf("problem");
926 else printf("%d problems", bugs
);
927 printf(" above\n see the section 'TROUBLESHOOTING' in the file ");
928 printf("%s%s\n", FILENAME
, oc
);
932 /* The program has received a signal where it wasn't expecting one */
936 printf("*** Unexpected signal at point %d\n", place
);
937 farewell(bugs
+1); /* An exit isn't essential here, but avoids loops */
940 /* This is here in case alloca.c is used, which calls this. */
942 xmalloc(unsigned size
)
944 char *value
= malloc(size
);
946 fprintf(stderr
, "Virtual memory exceeded\n");
957 /* Find the maximum integer */
958 Volatile
int newi
, int_max
, two
=2;
960 /* Calculate maxint ***********************************/
961 /* Calculate 2**n-1 until overflow - then use the previous value */
965 if (setjmp(lab
)==0) { /* Yields int_max */
966 while(newi
>int_max
) {
975 /* How long are my identifiers? I could go further here, but some compilers
976 have line length limits that I don't want to break.
979 int zzzzzzzzz1zzzzzzzzz2zzzzzzzzz3zzzzzzzzz4zzzzzzzzz5zzzzzzzzz6zzzz
=64;
984 int zzzzzzzzz1zzzzzzzzz2zzzzzzzzz3zz
=32;
985 { int zzzzzzzzz1zzzzzz
=16;
990 zzzzzzzzz1zzzzzzzzz2zzzzzzzzz3zzzzzzzzz4zzzzzzzzz5zzzzzzzzz6zzzz
;
997 #define aaaaaaaaa1aaaaaaaaa2aaaaaaaaa3aaaaaaaaa4aaaaaaaaa5aaaaaaaaa6aaaa 64
1000 #ifdef aaaaaaaaa1aaaaaaaaa2aaaaaaaaa3aa
1005 #ifdef aaaaaaaaa1aaaaaa
1015 #undef aaaaaaaaa1aaaaaaaaa2aaaaaaaaa3aaaaaaaaa4aaaaaaaaa5aaaaaaaaa6aaaa
1020 Vprintf("Compiler names are at least %d chars long", l
);
1022 Vprintf(" (but less than %d)", l
*2);
1024 Vprintf("Preprocessor names are at least %d long", LENGTH
);
1026 Vprintf(" (but less than %d)", LENGTH
*2);
1030 /* Used by FPROP to see if FP traps are generated, and if they may return */
1041 trapped
= 1; /* A global */
1049 signal(SIGFPE
, overflow
);
1052 signal(SIGOVER
, overflow
);
1055 signal(SIGBUS
, address
);
1058 signal(SIGSEGV
, address
);
1060 /* Add more calls as necessary */
1066 main(int argc
, char *argv
[])
1068 int dprec
, fprec
, lprec
;
1077 for (i
=1; i
< argc
; i
++) {
1078 s
= (wchar_t *)(argv
[i
]);
1083 case L
'v': V
=1; break;
1084 case L
'l': L
=1; break;
1085 case L
'f': F
=1; break;
1086 default: bad
=1; break;
1089 } else if (*s
== L
'+') {
1091 bad
= setmode((char *)s
);
1096 "Usage: %ls [-vlf]\n v=Verbose l=Limits.h f=Float.h\n",
1097 (wchar_t *)(argv
[0]));
1101 co
[0]= '/'; oc
[0]= ' ';
1102 co
[1]= '*'; oc
[1]= '*';
1103 co
[2]= ' '; oc
[2]= '/';
1104 co
[3]= '\0'; oc
[3]= '\0';
1106 co
[0]= '\0'; oc
[0]= '\0';
1110 if (L
) printf("%slimits.h%s\n", co
, oc
);
1111 if (F
) printf("%sfloat.h%s\n", co
, oc
);
1113 printf("%sProduced by enquire version %s (%s), CWI, Amsterdam\n %s\n",
1114 co
, VERSION
, ID
, WEB
, oc
);
1116 printf("%sProduced by enquire version %s, CWI, Amsterdam\n %s %s\n",
1117 co
, VERSION
, WEB
, oc
);
1121 printf("%sVerification phase%s\n", co
, oc
);
1125 Vprintf("%sCompiled without signal(): %s%s\n",
1127 "there's nothing that can be done if overflow occurs",
1131 Vprintf("%sCompiled without signed char%s\n", co
, oc
);
1134 Vprintf("%sCompiled without unsigned char%s\n", co
, oc
);
1137 Vprintf("%sCompiled without unsigned short or long%s\n", co
, oc
);
1140 Vprintf("%sCompiler claims to be ANSI C level %d%s\n",
1143 Vprintf("%sCompiler does not claim to be ANSI C%s\n", co
, oc
);
1150 maxint
= maximum_int();
1151 bits_per_byte
= basic();
1154 fprec
= fprop(bits_per_byte
);
1155 dprec
= dprop(bits_per_byte
);
1156 lprec
= ldprop(bits_per_byte
);
1157 efprop(fprec
, dprec
, lprec
);
1158 edprop(fprec
, dprec
, lprec
);
1159 eldprop(fprec
, dprec
, lprec
);
1163 /* An extra goody: the approximate amount of data-space */
1164 /* Allocate store until no more available */
1165 /* Different implementations have a different argument type
1166 to malloc. Here we assume that it's the same type as
1167 that which sizeof() returns */
1169 Volatile
long total
;
1170 char kmg
, *ptr
, *save
;
1174 size
=maximum_int()/4;
1177 if (setjmp(mlab
) == 0) {
1178 while ((ptr
= malloc((false()?sizeof(int):size
))) != (char *)NULL
) {
1179 //if (save == NULL) save= ptr; /* save the biggest chunk */
1180 link
= (char **)ptr
;
1182 // Save pointer to first allocated chunk
1187 // Build list of all subsequently allocated chunks, LIFO
1194 eek_a_bug("Trying to malloc all store generates a trap");
1198 if (setjmp(mlab
)!=0) croak(-1);
1200 //if (save != NULL) free(save);
1201 while(save
!= NULL
) {
1202 link
= (char **)save
;
1208 total
= (total
+511)/512; /* Sic */ kmg
= 'K';
1209 if (total
> 10000) {
1210 total
= (total
+999)/1000; kmg
= 'M';
1212 if (total
> 10000) {
1213 total
= (total
+999)/1000; kmg
= 'G';
1215 if (total
> 10000) {
1216 total
= (total
+999)/1000; kmg
= 'T';
1218 Vprintf("%sMemory mallocatable ~= %ld %cbytes%s\n",
1219 co
, total
, kmg
, oc
);
1223 return bugs
; /* To keep compilers and lint happy */
1227 eek_a_bug(char *problem
)
1229 /* The program has discovered a problem */
1230 printf("\n%s*** WARNING: %s%s\n", co
, problem
, oc
);
1235 describe(char *description
, char *extra
)
1237 /* Produce the description for a #define */
1239 printf(description
, extra
);
1255 /* Produce a #define for a signed int type */
1256 describe(desc
, extra
);
1258 printf("#define %s%s %ld%s\n", sort
, name
, val
, mark
);
1259 } else if (val
+ lim
< 0) {
1260 /* We may not produce a constant like -1024 if the max
1261 allowable value is 1023. It has then to be output as
1262 -1023-1. lim is the max allowable value. */
1263 printf("#define %s%s (%ld%s%ld%s)\n",
1264 sort
, name
, -lim
, mark
, val
+lim
, mark
);
1266 printf("#define %s%s (%ld%s)\n", sort
, name
, val
, mark
);
1268 /* If VERIFY is not set, val and req are just the same value;
1269 if it is set, val is the value as calculated, and req is
1270 the #defined constant
1273 printf("%s*** Verify failed for above #define!\n", co
);
1274 printf(" Compiler has %ld for value%s\n\n", req
, oc
);
1291 /* Produce a #define for an unsigned value */
1292 describe(desc
, extra
);
1293 printf("#define %s%s %lu%s%s\n", sort
, name
, val
, U
, mark
);
1295 printf("%s*** Verify failed for above #define!\n", co
);
1296 printf(" Compiler has %lu for value%s\n\n", req
, oc
);
1312 /* Produce a #define for a float/double/long double */
1313 describe(desc
, extra
);
1315 printf("#define %s%s %s%s\n",
1316 sort
, name
, f_rep(precision
, val
), mark
);
1317 } else if (*mark
== 'F') {
1318 /* non-ANSI C has no float constants, so cast the constant */
1319 printf("#define %s%s ((float)%s)\n",
1320 sort
, name
, f_rep(precision
, val
));
1322 printf("#define %s%s %s\n", sort
, name
, f_rep(precision
, val
));
1328 floor_log(int base
, Long_double x
)
1330 /* return floor(log base(x)) */
1332 while (x
>=base
) { r
++; x
/=base
; }
1337 ceil_log(int base
, Long_double x
)
1340 while (x
>1.0) { r
++; x
/=base
; }
1345 exponent(Long_double x
, Long_double
*fract
, int *exp
)
1347 /* Split x into a fraction and a power of ten;
1348 returns 0 if x is unusable, 1 otherwise.
1349 Only used for error messages about faulty output.
1358 if (x
==0.0) return 1;
1361 old
=x
; r
++; x
/=10.0;
1362 if (old
==x
) return 0;
1366 old
=x
; r
--; x
*=10.0;
1367 if (old
==x
) return 0;
1370 if (neg
) *fract
= -x
;
1377 f_rep(int precision
, Long_double val
)
1379 /* Return the floating representation of val */
1380 static char buf
[1024];
1382 if (sizeof(double) == sizeof(Long_double
)) {
1383 /* Assume they're the same, and use non-stdc format */
1384 /* This is for stdc compilers using non-stdc libraries */
1387 /* It had better support Le then */
1390 sprintf(buf
, f1
, precision
, val
);
1395 bitpattern(char *p
, unsigned int size
)
1397 /* Printf the bit-pattern of p */
1402 for (i
=1; i
<=size
; i
++) {
1405 for (j
=bits_per_byte
-1; j
>=0; j
--)
1406 printf("%c", (c
>>j
)&1 ? '1' : '0');
1407 if (i
!=size
) printf(" ");
1412 fill(char *p
, int size
)
1414 char *ab
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1417 for (i
=0; i
<size
; i
++)
1421 #define Order(x, mode)\
1422 printf("%s%s ", co, mode); fill((char *)&x, sizeof(x)); \
1423 for (i=1; i<=sizeof(x); i++) { c=((x>>(byte_size*(sizeof(x)-i)))&mask);\
1424 putchar(c==0 ? '?' : (char)c); }\
1428 endian(int byte_size
)
1430 /* Printf the byte-order used on this machine */
1431 /*unsigned*/ short s
=0;
1432 /*unsigned*/ int j
=0;
1433 /*unsigned*/ long l
=0;
1435 unsigned int mask
, i
, c
;
1438 for (i
=1; i
<=(unsigned)byte_size
; i
++) mask
= (mask
<<1)|1;
1441 printf("%sCHARACTER ORDER%s\n", co
, oc
);
1451 printf("%s*** #define %s missing from limits.h%s\n", co
, s
, oc
);
1458 printf("%s*** #define %s missing from float.h%s\n", co
, s
, oc
);
1462 /* To try and fool optimisers */
1463 int false( void ) { return 0; }
1465 #define Promoted(x) (false()?(x):(-1))
1466 #define is_signed(x) (Promoted(x) < 0)
1467 #define sign_of(x) (is_signed(x)?"signed":"unsigned")
1470 #define sgn(x) ((is_signed(x))?Signed:Unsigned)
1472 #define showtype(t, x) Vprintf("%s%s %s %s%s\n", co, t, sign_of(x), type_of((int)sizeof(x)), oc)
1474 char *type_of(int x
)
1476 if (x
== sizeof(char)) {
1477 if (sizeof(char) == sizeof(int)) return "char/short/int";
1478 if (sizeof(char) == sizeof(short)) return "char/short";
1481 if (x
== sizeof(short)) {
1482 if (sizeof(short) == sizeof(int)) return "short/int";
1485 if (x
== sizeof(int)) {
1486 if (sizeof(int) == sizeof(long)) return "int/long";
1489 if (x
== sizeof(long)) return "long";
1490 return "unknown-type";
1493 char *ftype_of(int x
)
1495 if (x
== sizeof(float)) {
1498 if (x
== sizeof(double)) {
1499 if (sizeof(double) == sizeof(Long_double
))
1500 return "(long)double";
1503 if (x
== sizeof(Long_double
)) {
1504 return "long double";
1506 return "unknown-type";
1509 Void
typerr(char *name
, int esign
, int esize
, int sign
, int size
)
1511 Vprintf("*** %s has wrong type: expected %s %s, found %s %s\n",
1512 name
, sign_of(esign
), type_of(esize
),
1513 sign_of(sign
), type_of(size
));
1516 Void
ftyperr(char *name
, int esize
, int size
)
1518 Vprintf("*** %s has wrong type: expected %s, found %s\n",
1519 name
, ftype_of(esize
), ftype_of(size
));
1522 Void
promotions( void )
1529 unsigned long ul
; /* if this fails, define NO_UI */
1530 unsigned short us
; /* if this fails, define NO_UI */
1534 /* Shut compiler warnings up: */
1535 si
=0; sl
=0; ui
=0; ss
=0;
1537 Vprintf("\n%sPROMOTIONS%s\n", co
, oc
);
1539 /* Sanity checks. Possible warnings here; should be no problem */
1541 eek_a_bug("unsigned int promotes to signed!\n");
1543 eek_a_bug("signed int promotes to unsigned!\n");
1545 eek_a_bug("signed long promotes to unsigned!\n");
1546 if (sizeof(Promoted(si
)) != sizeof(int))
1547 eek_a_bug("int doesn't promote to int!\n");
1548 if (sizeof(Promoted(sl
)) != sizeof(long))
1549 eek_a_bug("long doesn't promote to long!\n");
1550 if (sizeof(Promoted(ss
)) != sizeof(int))
1551 eek_a_bug("short doesn't promote to int!\n");
1552 if (sizeof(Promoted(ui
)) != sizeof(int))
1553 eek_a_bug("unsigned int doesn't promote to int!\n");
1555 if (sizeof(Promoted(ul
)) != sizeof(long))
1556 eek_a_bug("unsigned long doesn't promote to long!\n");
1558 eek_a_bug("unsigned long promotes to signed!\n");
1562 showtype("unsigned short promotes to", Promoted(us
));
1564 showtype("long+unsigned gives", sl
+ui
);
1567 #define checktype(x, n, s, t) if((sgn(x)!=s)||(sizeof(x)!=sizeof(t))) typerr(n, s, (int)sizeof(t), sgn(x), (int)sizeof(x));
1569 #define fchecktype(x, n, t) if (sizeof(x) != sizeof(t)) ftyperr(n, (int)sizeof(x), (int)sizeof(t));
1571 Void
check_defines( void )
1573 /* ensure that all #defines are present and have the correct type */
1580 /* Implementations promote unsigned short differently */
1581 usign
= is_signed((unsigned short)0);
1586 checktype(CHAR_BIT
, "CHAR_BIT", Signed
, int);
1588 missing("CHAR_BIT");
1591 checktype(CHAR_MAX
, "CHAR_MAX", Signed
, int);
1593 missing("CHAR_MAX");
1596 checktype(CHAR_MIN
, "CHAR_MIN", Signed
, int);
1598 missing("CHAR_MIN");
1601 checktype(SCHAR_MAX
, "SCHAR_MAX", Signed
, int);
1603 missing("SCHAR_MAX");
1606 checktype(SCHAR_MIN
, "SCHAR_MIN", Signed
, int);
1608 missing("SCHAR_MIN");
1611 checktype(UCHAR_MAX
, "UCHAR_MAX", Signed
, int);
1613 missing("UCHAR_MAX");
1616 checktype(SHRT_MAX
, "SHRT_MAX", Signed
, int);
1618 missing("SHRT_MAX");
1621 checktype(SHRT_MIN
, "SHRT_MIN", Signed
, int);
1623 missing("SHRT_MIN");
1626 checktype(INT_MAX
, "INT_MAX", Signed
, int);
1631 checktype(INT_MIN
, "INT_MIN", Signed
, int);
1636 checktype(LONG_MAX
, "LONG_MAX", Signed
, long);
1638 missing("LONG_MAX");
1641 checktype(LONG_MIN
, "LONG_MIN", Signed
, long);
1643 missing("LONG_MIN");
1646 checktype(USHRT_MAX
, "USHRT_MAX", usign
, int);
1648 missing("USHRT_MAX");
1651 checktype(UINT_MAX
, "UINT_MAX", Unsigned
, int);
1653 missing("UINT_MAX");
1656 checktype(ULONG_MAX
, "ULONG_MAX", Unsigned
, long);
1658 missing("ULONG_MAX");
1664 checktype(FLT_RADIX
, "FLT_RADIX", Signed
, int);
1666 fmissing("FLT_RADIX");
1669 checktype(FLT_MANT_DIG
, "FLT_MANT_DIG", Signed
, int);
1671 fmissing("FLT_MANT_DIG");
1674 checktype(FLT_DIG
, "FLT_DIG", Signed
, int);
1676 fmissing("FLT_DIG");
1679 checktype(FLT_ROUNDS
, "FLT_ROUNDS", Signed
, int);
1681 fmissing("FLT_ROUNDS");
1684 fchecktype(FLT_EPSILON
, "FLT_EPSILON", float);
1686 fmissing("FLT_EPSILON");
1689 checktype(FLT_MIN_EXP
, "FLT_MIN_EXP", Signed
, int);
1691 fmissing("FLT_MIN_EXP");
1694 fchecktype(FLT_MIN
, "FLT_MIN", float);
1696 fmissing("FLT_MIN");
1698 #ifdef FLT_MIN_10_EXP
1699 checktype(FLT_MIN_10_EXP
, "FLT_MIN_10_EXP", Signed
, int);
1701 fmissing("FLT_MIN_10_EXP");
1704 checktype(FLT_MAX_EXP
, "FLT_MAX_EXP", Signed
, int);
1706 fmissing("FLT_MAX_EXP");
1709 fchecktype(FLT_MAX
, "FLT_MAX", float);
1711 fmissing("FLT_MAX");
1713 #ifdef FLT_MAX_10_EXP
1714 checktype(FLT_MAX_10_EXP
, "FLT_MAX_10_EXP", Signed
, int);
1716 fmissing("FLT_MAX_10_EXP");
1719 checktype(DBL_MANT_DIG
, "DBL_MANT_DIG", Signed
, int);
1721 fmissing("DBL_MANT_DIG");
1724 checktype(DBL_DIG
, "DBL_DIG", Signed
, int);
1726 fmissing("DBL_DIG");
1729 fchecktype(DBL_EPSILON
, "DBL_EPSILON", double);
1731 fmissing("DBL_EPSILON");
1734 checktype(DBL_MIN_EXP
, "DBL_MIN_EXP", Signed
, int);
1736 fmissing("DBL_MIN_EXP");
1739 fchecktype(DBL_MIN
, "DBL_MIN", double);
1741 fmissing("DBL_MIN");
1743 #ifdef DBL_MIN_10_EXP
1744 checktype(DBL_MIN_10_EXP
, "DBL_MIN_10_EXP", Signed
, int);
1746 fmissing("DBL_MIN_10_EXP");
1749 checktype(DBL_MAX_EXP
, "DBL_MAX_EXP", Signed
, int);
1751 fmissing("DBL_MAX_EXP");
1754 fchecktype(DBL_MAX
, "DBL_MAX", double);
1756 fmissing("DBL_MAX");
1758 #ifdef DBL_MAX_10_EXP
1759 checktype(DBL_MAX_10_EXP
, "DBL_MAX_10_EXP", Signed
, int);
1761 fmissing("DBL_MAX_10_EXP");
1764 #ifdef LDBL_MANT_DIG
1765 checktype(LDBL_MANT_DIG
, "LDBL_MANT_DIG", Signed
, int);
1767 fmissing("LDBL_MANT_DIG");
1770 checktype(LDBL_DIG
, "LDBL_DIG", Signed
, int);
1772 fmissing("LDBL_DIG");
1775 fchecktype(LDBL_EPSILON
, "LDBL_EPSILON", long double);
1777 fmissing("LDBL_EPSILON");
1780 checktype(LDBL_MIN_EXP
, "LDBL_MIN_EXP", Signed
, int);
1782 fmissing("LDBL_MIN_EXP");
1785 fchecktype(LDBL_MIN
, "LDBL_MIN", long double);
1787 fmissing("LDBL_MIN");
1789 #ifdef LDBL_MIN_10_EXP
1790 checktype(LDBL_MIN_10_EXP
, "LDBL_MIN_10_EXP", Signed
, int);
1792 fmissing("LDBL_MIN_10_EXP");
1795 checktype(LDBL_MAX_EXP
, "LDBL_MAX_EXP", Signed
, int);
1797 fmissing("LDBL_MAX_EXP");
1800 fchecktype(LDBL_MAX
, "LDBL_MAX", long double);
1802 fmissing("LDBL_MAX");
1804 #ifdef LDBL_MAX_10_EXP
1805 checktype(LDBL_MAX_10_EXP
, "LDBL_MAX_10_EXP", Signed
, int);
1807 fmissing("LDBL_MAX_10_EXP");
1816 #define SCHAR_MAX char_max
1819 #define SCHAR_MIN char_min
1822 #define UCHAR_MAX char_max
1827 #define CHAR_BIT char_bit
1830 #define CHAR_MAX char_max
1833 #define CHAR_MIN char_min
1836 #define SCHAR_MAX char_max
1839 #define SCHAR_MIN char_min
1842 #define UCHAR_MAX char_max
1847 /* Properties of type char */
1848 Volatile
char c
, char_max
, char_min
;
1849 Volatile
int byte_size
, c_signed
;
1854 /* Calculate number of bits per character *************************/
1856 do { c
=c
<<1; byte_size
++; } while(c
!=0);
1858 if (((int)c
)<0) c_signed
=1;
1860 Vprintf("%schar = %d bits, %ssigned%s\n",
1861 co
, (int)sizeof(c
)*byte_size
, (c_signed
?"":"un"), oc
);
1862 char_bit
=(long)(sizeof(c
)*byte_size
);
1863 if (L
) i_define(D_CHAR_BIT
, "", "CHAR", "_BIT",
1864 char_bit
, 0L, (long) CHAR_BIT
, "");
1868 if (setjmp(lab
)==0) { /* Yields char_max */
1869 while (c
>char_max
) {
1874 Vprintf("%sCharacter overflow generates a trap!%s\n", co
, oc
);
1878 if (c
<char_min
) /* then the min char < 0 */ {
1879 /* Minimum value: assume either two's or one's complement *********/
1880 char_min
= -char_max
;
1881 if (setjmp(lab
)==0) { /* Yields char_min */
1882 if (char_min
-1 < char_min
) char_min
--;
1886 if (c_signed
&& char_min
== 0) {
1887 Vprintf("%sBEWARE! Chars are pseudo-unsigned:%s\n", co
, oc
);
1888 Vprintf("%s %s%s%s\n",
1889 "They contain only nonnegative values, ",
1890 "but sign extend when used as integers.", co
, oc
);
1895 /* Because of the integer promotions, you must use a U after
1896 the MAX_CHARS in the following cases */
1897 if ((sizeof(char) == sizeof(int)) && !c_signed
) {
1898 u_define(D_CHAR_MAX
, "", "CHAR", "_MAX",
1900 (ulong
) CHAR_MAX
, "");
1902 i_define(D_CHAR_MAX
, "", "CHAR", "_MAX",
1903 (long) char_max
, 0L,
1904 (long) CHAR_MAX
, "");
1906 i_define(D_CHAR_MIN
, "", "CHAR", "_MIN",
1907 (long) char_min
, (long) maxint
,
1908 (long) CHAR_MIN
, "");
1910 i_define(D_SCHAR_MAX
, "", "SCHAR", "_MAX",
1911 (long) char_max
, 0L,
1912 (long) SCHAR_MAX
, "");
1913 i_define(D_SCHAR_MIN
, "", "SCHAR", "_MIN",
1914 (long) char_min
, (long) maxint
,
1915 (long) SCHAR_MIN
, "");
1917 if (sizeof(char) == sizeof(int)) {
1918 u_define(D_UCHAR_MAX
, "", "UCHAR", "_MAX",
1920 (ulong
) UCHAR_MAX
, "");
1922 i_define(D_UCHAR_MAX
, "", "UCHAR", "_MAX",
1923 (long) char_max
, 0L,
1924 (long) UCHAR_MAX
, "");
1930 /* Syntax error? Define NO_UC */ Volatile
unsigned char c1
, char_max
;
1933 if (setjmp(lab
)==0) { /* Yields char_max */
1934 while (c1
>char_max
) {
1940 if (sizeof(char) == sizeof(int)) {
1941 u_define(D_UCHAR_MAX
, "", "UCHAR", "_MAX",
1943 (ulong
) UCHAR_MAX
, "");
1945 i_define(D_UCHAR_MAX
, "", "UCHAR", "_MAX",
1946 (long) char_max
, 0L,
1947 (long) UCHAR_MAX
, "");
1952 /* Syntax error? Define NO_SC */ Volatile
signed char c1
, char_max
, char_min
;
1955 if (setjmp(lab
)==0) { /* Yields char_max */
1956 while (c1
>char_max
) {
1963 if (setjmp(lab
)==0) { /* Yields char_min */
1964 while (c1
<char_min
) {
1970 i_define(D_SCHAR_MIN
, "", "SCHAR", "_MIN",
1971 (long) char_min
, (long) maxint
,
1972 (long) SCHAR_MIN
, "");
1973 i_define(D_SCHAR_MAX
, "", "SCHAR", "_MAX",
1974 (long) char_max
, 0L,
1975 (long) SCHAR_MAX
, "");
1984 /* The properties of the basic types.
1985 Returns number of bits per sizeof unit */
1986 Volatile
int byte_size
;
1987 typedef int function ();
1989 char *cp
; int *ip
; function
*fp
;
1992 Vprintf("%sSIZES%s\n", co
, oc
);
1995 /* Shorts, ints and longs *****************************************/
1996 Vprintf("%sshort=%d int=%d long=%d float=%d double=%d bits %s\n",
1998 (int) sizeof(short)*byte_size
,
1999 (int) sizeof(int)*byte_size
,
2000 (int) sizeof(long)*byte_size
,
2001 (int) sizeof(float)*byte_size
,
2002 (int) sizeof(double)*byte_size
, oc
);
2004 Vprintf("%slong double=%d bits%s\n",
2005 co
, (int) sizeof(Long_double
)*byte_size
, oc
);
2007 Vprintf("%schar*=%d bits%s%s\n",
2008 co
, (int)sizeof(char *)*byte_size
,
2009 sizeof(char *)>sizeof(int)?" BEWARE! larger than int!":"",
2011 Vprintf("%sint* =%d bits%s%s\n",
2012 co
, (int)sizeof(int *)*byte_size
,
2013 sizeof(int *)>sizeof(int)?" BEWARE! larger than int!":"",
2015 Vprintf("%sfunc*=%d bits%s%s\n",
2016 co
, (int)sizeof(function
*)*byte_size
,
2017 sizeof(function
*)>sizeof(int)?" BEWARE! larger than int!":"",
2020 showtype("Type size_t is", sizeof(0));
2022 showtype("Type wchar_t is", L
'x');
2025 /* Alignment constants ********************************************/
2027 #define alignment(TYPE) \
2028 ((long)((char *)&((struct{char c; TYPE d;}*)0)->d - (char *)0))
2030 Vprintf("\n%sALIGNMENTS%s\n", co
, oc
);
2032 Vprintf("%schar=%ld short=%ld int=%ld long=%ld%s\n",
2034 alignment(char), alignment(short),
2035 alignment(int), alignment(long),
2038 Vprintf("%sfloat=%ld double=%ld%s\n",
2040 alignment(float), alignment(double),
2044 Vprintf("%slong double=%ld%s\n",
2046 alignment(Long_double
),
2049 Vprintf("%schar*=%ld int*=%ld func*=%ld%s\n",
2051 alignment(char *), alignment(int *), alignment(function
*),
2056 /* Ten little endians *********************************************/
2060 /* Pointers *******************************************************/
2062 Vprintf("\n%sPROPERTIES OF POINTERS%s\n", co
, oc
);
2063 cp
= (char *) &variable
;
2064 ip
= (int *) &variable
;
2065 fp
= (function
*) &variable
;
2067 Vprintf("%sChar and int pointer formats ", co
);
2068 if (memeq((char *) &cp
, sizeof(cp
), (char *) &ip
, sizeof(ip
))) {
2069 Vprintf("seem identical%s\n", oc
);
2071 Vprintf("are different%s\n", oc
);
2073 Vprintf("%sChar and function pointer formats ", co
);
2074 if (memeq((char *) &cp
, sizeof(cp
), (char *) &fp
, sizeof(fp
))) {
2075 Vprintf("seem identical%s\n", oc
);
2077 Vprintf("are different%s\n", oc
);
2081 if ((VOID
*)"abcd" == (VOID
*)"abcd")
2082 printf("%sStrings are shared%s\n", co
, oc
);
2083 else printf("%sStrings are not shared%s\n", co
, oc
);
2087 showtype("Type ptrdiff_t is", p
-q
);
2089 //if (setjmp(mlab) == 0) {
2091 // Vprintf("%sBEWARE! Dereferencing NULL doesn't cause a trap%s\n",
2094 // Vprintf("%sDereferencing NULL causes a trap%s\n", co, oc);
2096 if (setjmp(mlab
)!=0) croak(-2);
2098 Vprintf("\n%sPROPERTIES OF INTEGRAL TYPES%s\n", co
, oc
);
2114 #else /* not PASS0 */
2117 /* The global variables used by several passes */
2119 extern int V
, L
, F
, bugs
, bits_per_byte
;
2120 extern int maxint
, flt_radix
, flt_rounds
;
2121 extern Volatile
int trapped
;
2122 extern char co
[], oc
[];
2123 extern char *f_rep();
2124 extern Void
trap1();
2126 #endif /* ifdef PASS0 */
2128 /* As I said, I apologise for the contortions below. The functions are
2129 expanded by the preprocessor twice or three times (for float and double,
2130 and maybe for long double, and for short, int and long). That way,
2131 I never make a change to one that I forget to make to the other.
2132 You can look on it as C's fault for not supporting multi-line macros.
2133 This whole file is read 3 times by the preprocessor, with PASSn set for
2134 n=1, 2 or 3, to decide which parts to reprocess.
2137 /* #undef on an already undefined thing is (wrongly) flagged as an error
2138 by some compilers, therefore the #ifdef that follows:
2164 /* These are the float.h constants */
2195 /* Define the things we're going to use this pass */
2197 #define Number float
2198 #define THING "FLOAT"
2199 #define Thing "Float"
2200 #define thing "float"
2203 #define Store fStore
2215 #define F_check fCheck
2218 #define Verify fVerify
2221 #define EPROP efprop
2223 #define Integer short
2226 #define Iname "SHRT"
2232 #define UPROP usprop
2233 #define Uname "USHRT"
2237 #define I_MAX SHRT_MAX
2240 #define I_MIN SHRT_MIN
2243 #define U_MAX USHRT_MAX
2247 #define F_RADIX FLT_RADIX
2250 #define F_MANT_DIG FLT_MANT_DIG
2253 #define F_DIG FLT_DIG
2256 #define F_ROUNDS FLT_ROUNDS
2259 #define F_EPSILON FLT_EPSILON
2262 #define F_MIN_EXP FLT_MIN_EXP
2265 #define F_MIN FLT_MIN
2267 #ifdef FLT_MIN_10_EXP
2268 #define F_MIN_10_EXP FLT_MIN_10_EXP
2271 #define F_MAX_EXP FLT_MAX_EXP
2274 #define F_MAX FLT_MAX
2276 #ifdef FLT_MAX_10_EXP
2277 #define F_MAX_10_EXP FLT_MAX_10_EXP
2285 #define Number double
2286 #define THING "DOUBLE"
2287 #define Thing "Double"
2288 #define thing "double"
2291 #define Store dStore
2303 #define F_check dCheck
2306 #define Verify dVerify
2309 #define EPROP edprop
2315 #define OK_UI 1 /* Unsigned int is always possible */
2318 #define UPROP uiprop
2319 #define Uname "UINT"
2323 #define I_MAX INT_MAX
2326 #define I_MIN INT_MIN
2329 #define U_MAX UINT_MAX
2333 #define F_MANT_DIG DBL_MANT_DIG
2336 #define F_DIG DBL_DIG
2339 #define F_EPSILON DBL_EPSILON
2342 #define F_MIN_EXP DBL_MIN_EXP
2345 #define F_MIN DBL_MIN
2347 #ifdef DBL_MIN_10_EXP
2348 #define F_MIN_10_EXP DBL_MIN_10_EXP
2351 #define F_MAX_EXP DBL_MAX_EXP
2354 #define F_MAX DBL_MAX
2356 #ifdef DBL_MAX_10_EXP
2357 #define F_MAX_10_EXP DBL_MAX_10_EXP
2366 #define Number long double
2376 #define THING "LONG DOUBLE"
2377 #define Thing "Long double"
2378 #define thing "long double"
2379 #define Fname "LDBL"
2380 #define FPROP ldprop
2381 #define Store ldStore
2387 #define F_check ldCheck
2390 #define Verify ldVerify
2393 #define EPROP eldprop
2395 #define Integer long
2398 #define Iname "LONG"
2404 #define UPROP ulprop
2405 #define Uname "ULONG"
2409 #define I_MAX LONG_MAX
2412 #define I_MIN LONG_MIN
2415 #define U_MAX ULONG_MAX
2418 #ifdef LDBL_MANT_DIG
2419 #define F_MANT_DIG LDBL_MANT_DIG
2422 #define F_DIG LDBL_DIG
2425 #define F_EPSILON LDBL_EPSILON
2428 #define F_MIN_EXP LDBL_MIN_EXP
2431 #define F_MIN LDBL_MIN
2433 #ifdef LDBL_MIN_10_EXP
2434 #define F_MIN_10_EXP LDBL_MIN_10_EXP
2437 #define F_MAX_EXP LDBL_MAX_EXP
2440 #define F_MAX LDBL_MAX
2442 #ifdef LDBL_MAX_10_EXP
2443 #define F_MAX_10_EXP LDBL_MAX_10_EXP
2449 /* The rest of the file gets read all three times;
2450 the differences are encoded in the things #defined above.
2454 #define I_MAX int_max
2457 #define I_MIN int_min
2464 #define F_RADIX f_radix
2467 #define F_MANT_DIG f_mant_dig
2473 #define F_ROUNDS f_rounds
2476 #define F_EPSILON f_epsilon
2479 #define F_MIN_EXP f_min_exp
2484 #ifndef F_MIN_10_EXP
2485 #define F_MIN_10_EXP f_min_10_exp
2488 #define F_MAX_EXP f_max_exp
2493 #ifndef F_MAX_10_EXP
2494 #define F_MAX_10_EXP f_max_10_exp
2498 #define Verify(prec, val, req, same, same1) {;}
2505 /* the properties of short, int, and long */
2506 Volatile Integer newi
, int_max
, maxeri
, int_min
, minneri
;
2507 Volatile
int ibits
, ipower
, two
=2;
2509 /* Calculate max short/int/long ***********************************/
2510 /* Calculate 2**n-1 until overflow - then use the previous value */
2514 if (setjmp(lab
)==0) { /* Yields int_max */
2515 for(ipower
=0; newi
>int_max
; ipower
++) {
2519 Vprintf("%sOverflow of a%s %s does not generate a trap%s\n",
2520 co
, INT
[0]=='i'?"n":"", INT
, oc
);
2522 Vprintf("%sOverflow of a%s %s generates a trap%s\n",
2523 co
, INT
[0]=='i'?"n":"", INT
, oc
);
2527 /* Minimum value: assume either two's or one's complement *********/
2529 if (setjmp(lab
)==0) { /* Yields int_min */
2530 if (int_min
-1 < int_min
) int_min
--;
2534 /* Now for those daft Cybers */
2536 maxeri
=0; newi
=int_max
;
2538 if (setjmp(lab
)==0) { /* Yields maxeri */
2539 for(ibits
=ipower
; newi
>maxeri
; ibits
++) {
2547 if (setjmp(lab
)==0) { /* Yields minneri */
2548 if (minneri
-1 < minneri
) minneri
--;
2552 Vprintf("%sMaximum %s = %ld (= 2**%d-1)%s\n",
2553 co
, INT
, (long)int_max
, ipower
, oc
);
2554 Vprintf("%sMinimum %s = %ld%s\n", co
, INT
, (long)int_min
, oc
);
2556 if (L
) i_define(D_INT_MAX
, INT
, Iname
, "_MAX",
2558 (long) I_MAX
, IMARK
);
2559 if (L
) i_define(D_INT_MIN
, INT
, Iname
, "_MIN",
2560 (long) int_min
, (long) (PASS
==1?maxint
:int_max
),
2561 (long) I_MIN
, IMARK
);
2563 if(int_max
< 0) { /* It has happened (on a Cray) */
2564 eek_a_bug("signed integral comparison faulty?");
2567 if (maxeri
>int_max
) {
2568 Vprintf("%sThere is a larger %s, %ld (= 2**%d-1), %s %s%s\n",
2569 co
, INT
, (long)maxeri
, ibits
,
2570 "but only for addition, not multiplication",
2571 "(I smell a Cyber!)",
2575 if (minneri
<int_min
) {
2576 Vprintf("%sThere is a smaller %s, %ld, %s %s%s\n",
2577 co
, INT
, (long)minneri
,
2578 "but only for addition, not multiplication",
2579 "(I smell a Cyber!)",
2586 /* The properties of unsigned short/int/long */
2588 Volatile
unsigned Integer u_max
, newi
, two
;
2589 newi
=1; u_max
=0; two
=2;
2591 if (setjmp(lab
)==0) { /* Yields u_max */
2598 Vprintf("%sMaximum unsigned %s = %lu%s\n",
2599 co
, INT
, (unsigned long) u_max
, oc
);
2601 /* Oh woe: new standard C defines value preserving promotions:
2602 3.2.1.1: "If an int can represent all values of the original type,
2603 the value is converted to an int;
2604 otherwise it is converted to an unsigned int."
2607 if (PASS
== 1 /* we're dealing with short */
2608 && u_max
<= maxint
/* an int can represent all values */
2610 { /* the value is converted to an int */
2611 i_define(D_UINT_MAX
, INT
, Uname
, "_MAX",
2613 (long) U_MAX
, IMARK
);
2614 } else { /* it is converted to an unsigned int */
2615 u_define(D_UINT_MAX
, INT
, Uname
, "_MAX",
2616 (unsigned long) u_max
,
2617 (unsigned long) U_MAX
, IMARK
);
2623 #endif /* Integer */
2627 /* The following routines are intended to defeat any attempt at optimisation
2628 or use of extended precision, and to defeat faulty narrowing casts.
2629 The weird prototypes are because of widening incompatibilities.
2631 #if defined(STDC) || defined(_MSC_VER)
2632 #define ARGS1(A, a) (A a)
2633 #define ARGS2(A, a, B, b) (A a, B b)
2634 #define ARGS5(A, a, B, b, C, c, D, d, E, e) (A a, B b, C c, D d, E e)
2636 #define ARGS1(A, a) (a) A a;
2637 #define ARGS2(A, a, B, b) (a, b) A a; B b;
2638 #define ARGS5(A, a, B, b, C, c, D, d, E, e) (a,b,c,d,e)A a; B b; C c; D d; E e;
2641 Void Store
ARGS2(Number
, a
, Number
*, b
) { *b
=a
; }
2642 Number Sum
ARGS2(Number
, a
, Number
, b
) {Number r
; Store(a
+b
, &r
); return r
; }
2643 Number Diff
ARGS2(Number
, a
, Number
, b
){Number r
; Store(a
-b
, &r
); return r
; }
2644 Number Mul
ARGS2(Number
, a
, Number
, b
) {Number r
; Store(a
*b
, &r
); return r
; }
2645 Number Div
ARGS2(Number
, a
, Number
, b
) {Number r
; Store(a
/b
, &r
); return r
; }
2646 Number Self
ARGS1(Number
, a
) {Number r
; Store(a
, &r
); return r
; }
2648 Void F_check
ARGS((int precision
, Long_double val1
));
2650 Void
F_check(int precision
, Long_double val1
)
2652 /* You don't think I'm going to go to all the trouble of writing
2653 a program that works out what all sorts of values are, only to
2654 have printf go and print the wrong values out, do you?
2655 No, you're right, so this function tries to see if printf
2656 has written the right value, by reading it back again.
2657 This introduces a new problem of course: suppose printf writes
2658 the correct value, and scanf reads it back wrong... oh well.
2659 But I'm adamant about this: the precision given is enough
2660 to uniquely identify the printed number, therefore I insist
2661 that sscanf read the number back identically. Harsh yes, but
2662 sometimes you've got to be cruel to be kind.
2664 Long_double new1
, rem
;
2665 Number val
, new, diff
;
2669 if (sizeof(double) == sizeof(Long_double
)) {
2670 /* Assume they're the same, and use non-stdc format */
2671 /* This is for stdc compilers using non-stdc libraries */
2672 f2
= "%le"; /* Input */
2674 /* It had better support Le then */
2678 rep
= f_rep(precision
, (Long_double
) val
);
2679 if (setjmp(lab
)==0) {
2680 sscanf(rep
, f2
, &new1
);
2682 eek_a_bug("sscanf caused a trap");
2683 printf("%s scanning: %s format: %s%s\n\n", co
, rep
, f2
, oc
);
2688 if (setjmp(lab
)==0) { /* See if new is usable */
2691 diff
= val
/new - 1.0;
2692 if (diff
< 0.1) diff
= 1.0;
2693 /* That should be enough to generate a trap */
2696 eek_a_bug("sscanf returned an unusable number");
2697 printf("%s scanning: %s with format: %s%s\n\n",
2705 eek_a_bug("Possibly bad output from printf above");
2706 if (!exponent((Long_double
)val
, &rem
, &e
)) {
2707 printf("%s but value was an unusable number%s\n\n",
2711 printf("%s expected value around ", co
);
2712 //if (sizeof(double) == sizeof(Long_double)) {
2713 /* Assume they're the same, and use non-stdc format */
2714 /* This is for stdc compilers using non-stdc libraries */
2715 //printf("%.*fe%d, bit pattern:\n ", precision, rem, e);
2717 /* It had better support Lfe then */
2718 printf("%.*Lfe%d, bit pattern:\n ", precision
, rem
, e
);
2720 bitpattern((char *) &val
, (unsigned)sizeof(val
));
2721 printf ("%s\n", oc
);
2722 printf("%s sscanf gave %s, bit pattern:\n ",
2723 co
, f_rep(precision
, (Long_double
) new));
2724 bitpattern((char *) &new, (unsigned)sizeof(new));
2725 printf ("%s\n", oc
);
2726 if (setjmp(lab
) == 0) {
2728 printf("%s difference= %s%s\n\n",
2729 co
, f_rep(precision
, (Long_double
) diff
), oc
);
2730 } /* else forget it */
2736 Void Verify
ARGS5(int, prec
, Number
, val
, Number
, req
, int, same
, int, same1
)
2738 /* Check that the compiler has read a #define value correctly */
2741 printf("%s*** Verify failed for above #define!\n", co
);
2742 if (setjmp(lab
) == 0) { /* for the case that req == nan */
2743 printf(" Compiler has %s for value\n",
2746 printf(" Compiler has %s for value\n",
2747 "an unusable number");
2749 if (setjmp(lab
) == 0) {
2750 F_check(prec
, (Long_double
) req
);
2751 } /*else forget it*/
2752 if (setjmp(lab
) == 0) {
2753 if (req
> 0.0 && val
> 0.0) {
2754 printf(" difference= %s\n",
2755 f_rep(prec
, val
-req
));
2757 } /*else forget it*/
2761 } else if (!same1
) {
2762 if (stdc
) eek_a_bug("constant has the wrong precision");
2763 else eek_a_bug("the cast didn't work");
2769 int FPROP(int byte_size
)
2771 /* Properties of floating types, using algorithms by Cody and Waite
2772 from MA Malcolm, as modified by WM Gentleman and SB Marovich.
2773 Further extended by S Pemberton.
2775 Returns the number of digits in the fraction.
2779 i
, f_radix
, iexp
, irnd
, mrnd
, f_rounds
, f_mant_dig
,
2780 iz
, k
, inf
, machep
, f_max_exp
, f_min_exp
, mx
, negeps
,
2781 mantbits
, digs
, f_dig
, trap
,
2782 hidden
, normal
, f_min_10_exp
, f_max_10_exp
;
2784 a
, b
, base
, basein
, basem1
, f_epsilon
, epsneg
,
2785 eps
, epsp1
, etop
, ebot
,
2786 f_max
, newxmax
, f_min
, xminner
, y
, y1
, z
, z1
, z2
;
2790 Vprintf("%sPROPERTIES OF %s%s\n", co
, THING
, oc
);
2792 /* Base and size of significand **************************************/
2793 /* First repeatedly double until adding 1 has no effect. */
2794 /* For instance, if base is 10, with 3 significant digits */
2795 /* it will try 1, 2, 4, 8, ... 512, 1024, and stop there, */
2796 /* since 1024 is only representable as 1020. */
2798 if (setjmp(lab
)==0) { /* inexact trap? */
2800 while (Diff(Diff(Sum(a
, ONE
), a
), ONE
) == ZERO
);
2802 fprintf(stderr
, "*** Program got loss-of-precision trap!\n");
2803 /* And supporting those is just TOO much trouble! */
2807 /* Now double until you find a number that can be added to the */
2808 /* above number. For 1020 this is 8 or 16, depending whether the */
2809 /* result is rounded or truncated. */
2810 /* In either case the result is 1030. 1030-1020= the base, 10. */
2812 do { b
=Sum(b
, b
); } while ((base
=Diff(Sum(a
, b
), a
)) == ZERO
);
2814 Vprintf("%sBase = %d%s\n", co
, f_radix
, oc
);
2816 /* Sanity check; if base<2, I can't guarantee the rest will work */
2818 eek_a_bug("Function return or parameter passing faulty? (This is a guess.)");
2823 if (PASS
== 1) { /* only for FLT */
2825 if (F
) i_define(D_FLT_RADIX
, "", "FLT", "_RADIX",
2826 (long) f_radix
, 0L, (long) F_RADIX
, "");
2827 } else if (f_radix
!= flt_radix
) {
2828 printf("\n%s*** WARNING: %s %s (%d) %s%s\n",
2829 co
, thing
, "arithmetic has a different radix",
2830 f_radix
, "from float", oc
);
2834 /* Now the number of digits precision */
2835 f_mant_dig
=0; b
=1.0;
2836 do { f_mant_dig
++; b
=Mul(b
, base
); }
2837 while (Diff(Diff(Sum(b
, ONE
), b
), ONE
) == ZERO
);
2838 f_dig
=floor_log(10, (Long_double
)(b
/base
)) + (base
==10?1:0);
2839 Vprintf("%sSignificant base digits = %d %s %d %s%s\n",
2840 co
, f_mant_dig
, "(= at least", f_dig
, "decimal digits)", oc
);
2841 if (F
) i_define(D_MANT_DIG
, thing
, Fname
, "_MANT_DIG",
2842 (long) f_mant_dig
, 0L, (long) F_MANT_DIG
, "");
2843 if (F
) i_define(D_DIG
, thing
, Fname
, "_DIG",
2844 (long) f_dig
, 0L, (long) F_DIG
, "");
2845 digs
= ceil_log(10, (Long_double
)b
); /* the number of digits to printf */
2847 /* Rounding *******************************************************/
2848 basem1
=Diff(base
, HALF
);
2849 if (Diff(Sum(a
, basem1
), a
) != ZERO
) {
2850 if (f_radix
== 2) basem1
=0.375;
2852 if (Diff(Sum(a
, basem1
), a
) != ZERO
) irnd
=2; /* away from 0 */
2853 else irnd
=1; /* to nearest */
2854 } else irnd
=0; /* towards 0 */
2856 basem1
=Diff(base
, HALF
);
2858 if (Diff(Diff(-a
, basem1
), -a
) != ZERO
) {
2859 if (f_radix
== 2) basem1
=0.375;
2861 if (Diff(Diff(-a
, basem1
), -a
) != ZERO
) mrnd
=2; /* away from 0*/
2862 else mrnd
=1; /* to nearest */
2863 } else mrnd
=0; /* towards 0 */
2865 f_rounds
= -1; /* Unknown rounding */
2866 if (irnd
==0 && mrnd
==0) f_rounds
=0; /* zero = chops */
2867 if (irnd
==1 && mrnd
==1) f_rounds
=1; /* nearest */
2868 if (irnd
==2 && mrnd
==0) f_rounds
=2; /* +inf */
2869 if (irnd
==0 && mrnd
==2) f_rounds
=3; /* -inf */
2871 if (f_rounds
!= -1) {
2872 Vprintf("%sArithmetic rounds towards ", co
);
2874 case 0: Vprintf("zero (i.e. it chops)"); break;
2875 case 1: Vprintf("nearest"); break;
2876 case 2: Vprintf("+infinity"); break;
2877 case 3: Vprintf("-infinity"); break;
2878 default: Vprintf("???"); break;
2880 Vprintf("%s\n", oc
);
2881 } else { /* Hmm, try to give some help here */
2882 Vprintf("%sArithmetic rounds oddly: %s\n", co
, oc
);
2883 Vprintf("%s Negative numbers %s%s\n",
2884 co
, mrnd
==0 ? "towards zero" :
2885 mrnd
==1 ? "to nearest" :
2888 Vprintf("%s Positive numbers %s%s\n",
2889 co
, irnd
==0 ? "towards zero" :
2890 irnd
==1 ? "to nearest" :
2894 /* An extra goody */
2895 if (f_radix
== 2 && f_rounds
== 1) {
2896 if (Diff(Sum(a
, ONE
), a
) != ZERO
) {
2897 Vprintf("%s Tie breaking rounds up%s\n", co
, oc
);
2898 } else if (Diff(Sum(a
, THREE
), a
) == FOUR
) {
2899 Vprintf("%s Tie breaking rounds to even%s\n", co
, oc
);
2901 Vprintf("%s Tie breaking rounds down%s\n", co
, oc
);
2904 if (PASS
== 1) { /* only for FLT */
2905 flt_rounds
= f_rounds
;
2907 i_define(D_FLT_ROUNDS
, "", "FLT", "_ROUNDS",
2908 (long) f_rounds
, 1L, (long) F_ROUNDS
, "");
2909 } else if (f_rounds
!= flt_rounds
) {
2910 printf("\n%s*** WARNING: %s %s (%d) %s%s\n\n",
2911 co
, thing
, "arithmetic rounds differently",
2912 f_rounds
, "from float", oc
);
2916 /* Various flavours of epsilon ************************************/
2917 negeps
=f_mant_dig
+f_mant_dig
;
2920 for(i
=1; i
<=negeps
; i
++) a
*=basein
;
2923 while (Diff(Diff(ONE
, a
), ONE
) == ZERO
) {
2928 Vprintf("%sSmallest x such that 1.0-base**x != 1.0 = %d%s\n",
2933 eps
= Sum(ebot
, Div(Diff(etop
, ebot
), TWO
));
2934 /* find the smallest epsneg (1-epsneg != 1) by binary search.
2935 ebot and etop are the current bounds */
2936 while (eps
!= ebot
&& eps
!= etop
) {
2937 epsp1
= Diff(ONE
, eps
);
2938 if (epsp1
< ONE
) etop
= eps
;
2940 eps
= Sum(ebot
, Div(Diff(etop
, ebot
), TWO
));
2944 if (Diff(ONE
, etop
) >= ONE
|| Diff(ONE
, ebot
) != ONE
) {
2945 eek_a_bug("internal error calculating epsneg");
2947 Vprintf("%sSmallest x such that 1.0-x != 1.0 = %s%s\n",
2948 co
, f_rep(digs
, (Long_double
) eps
), oc
);
2949 if (V
) F_check(digs
, (Long_double
) eps
);
2952 if ((f_radix
!=2) && irnd
) {
2953 /* a=(a*(1.0+a))/(1.0+1.0); => */
2954 a
=Div(Mul(a
, Sum(ONE
, a
)), Sum(ONE
, ONE
));
2955 /* if ((1.0-a)-1.0 != 0.0) epsneg=a; => */
2956 if (Diff(Diff(ONE
, a
), ONE
) != ZERO
) epsneg
=a
;
2958 /* epsneg is used later */
2961 machep
= -f_mant_dig
-f_mant_dig
;
2963 while (Diff(Sum(ONE
, a
), ONE
) == ZERO
) { a
*=base
; machep
++; }
2964 Vprintf("%sSmallest x such that 1.0+base**x != 1.0 = %d%s\n",
2969 eps
= Sum(ebot
, Div(Diff(etop
, ebot
), TWO
));
2970 /* find the smallest eps (1+eps != 1) by binary search.
2971 ebot and etop are the current bounds */
2972 while (eps
!= ebot
&& eps
!= etop
) {
2973 epsp1
= Sum(ONE
, eps
);
2974 if (epsp1
> ONE
) etop
= eps
;
2976 eps
= Sum(ebot
, Div(Diff(etop
, ebot
), TWO
));
2979 if (Sum(ONE
, etop
) <= ONE
|| Sum(ONE
, ebot
) != ONE
) {
2980 eek_a_bug("internal error calculating eps");
2984 Vprintf("%sSmallest x such that 1.0+x != 1.0 = %s%s\n",
2985 co
, f_rep(digs
, (Long_double
) f_epsilon
), oc
);
2987 f_epsilon
= Diff(Sum(ONE
, f_epsilon
), ONE
); /* New C standard defn */
2988 Vprintf("%s(Above number + 1.0) - 1.0 = %s%s\n",
2989 co
, f_rep(digs
, (Long_double
) (f_epsilon
)), oc
);
2991 /* Possible loss of precision warnings here from non-stdc compilers */
2992 if (F
) f_define(D_EPSILON
, thing
,
2993 Fname
, "_EPSILON", digs
, (Long_double
) f_epsilon
, MARK
);
2994 if (V
|| F
) F_check(digs
, (Long_double
) f_epsilon
);
2996 if (F
) Verify(digs
, f_epsilon
, F_EPSILON
,
2997 f_epsilon
== Self(F_EPSILON
),
2998 (Long_double
) f_epsilon
== (Long_double
) F_EPSILON
);
3001 /* Extra chop info *************************************************/
3002 if (f_rounds
== 0) {
3003 if (Diff(Mul(Sum(ONE
,f_epsilon
),ONE
),ONE
) != ZERO
) {
3004 Vprintf("%sAlthough arithmetic chops, it uses guard digits%s\n", co
, oc
);
3008 /* Size of and minimum normalised exponent ************************/
3009 y
=0; i
=0; k
=1; z
=basein
; z1
=(1.0+f_epsilon
)/base
;
3011 /* Coarse search for the largest power of two */
3012 if (setjmp(lab
)==0) { /* for underflow trap */ /* Yields i, k, y, y1 */
3015 z
=Mul(y
,y
); z1
=Mul(z1
, y
);
3018 if (z2
!= y1
) break;
3019 if ((Sum(a
,a
) == ZERO
) || (fabs(z
) >= y
)) break;
3024 Vprintf("%s%s underflow generates a trap%s\n", co
, Thing
, oc
);
3028 if (f_radix
!= 10) {
3029 iexp
=i
+1; /* for the sign */
3034 while (k
>= iz
) { iz
*=f_radix
; iexp
++; }
3038 /* Fine tune starting with y and y1 */
3039 if (setjmp(lab
)==0) { /* for underflow trap */ /* Yields k, f_min */
3042 y
=Div(y
,base
); y1
=Div(y1
,base
);
3045 if (z2
!= z1
) break;
3046 if ((Sum(a
,a
) == ZERO
) || (fabs(y
) >= f_min
)) break;
3054 if ((mx
<= k
+k
-3) && (f_radix
!= 10)) { mx
+=mx
; iexp
+=1; }
3055 Vprintf("%sNumber of bits used for exponent = %d%s\n", co
, iexp
, oc
);
3056 Vprintf("%sMinimum normalised exponent = %d%s\n", co
, f_min_exp
-1, oc
);
3058 i_define(D_MIN_EXP
, thing
, Fname
, "_MIN_EXP",
3059 (long) f_min_exp
, (long) maxint
, (long) F_MIN_EXP
, "");
3061 if (setjmp(lab
)==0) {
3062 Vprintf("%sMinimum normalised positive number = %s%s\n",
3063 co
, f_rep(digs
, (Long_double
) f_min
), oc
);
3065 eek_a_bug("printf can't print the smallest normalised number");
3069 /* Possible loss of precision warnings here from non-stdc compilers */
3070 if (setjmp(lab
) == 0) {
3071 if (F
) f_define(D_MIN
, thing
,
3072 Fname
, "_MIN", digs
, (Long_double
) f_min
, MARK
);
3073 if (V
|| F
) F_check(digs
, (Long_double
) f_min
);
3075 eek_a_bug("xxx_MIN caused a trap");
3079 if (setjmp(lab
) == 0) {
3080 if (F
) Verify(digs
, f_min
, F_MIN
,
3081 f_min
== Self(F_MIN
),
3082 (Long_double
) f_min
== (Long_double
) F_MIN
);
3084 printf("%s*** Verify failed for above #define!\n %s %s\n\n",
3085 co
, "Compiler has an unusable number for value", oc
);
3090 a
=1.0; f_min_10_exp
=0;
3091 while (a
> f_min
*10.0) { a
/=10.0; f_min_10_exp
--; }
3092 if (F
) i_define(D_MIN_10_EXP
, thing
, Fname
, "_MIN_10_EXP",
3093 (long) f_min_10_exp
, (long) maxint
,
3094 (long) F_MIN_10_EXP
, "");
3096 /* Minimum exponent ************************************************/
3097 if (setjmp(lab
)==0) { /* for underflow trap */ /* Yields xminner */
3102 if ((Sum(a
,a
) == ZERO
) || (fabs(y
) >= xminner
)) break;
3107 if (xminner
!= 0.0 && xminner
!= f_min
) {
3109 Vprintf("%sThe smallest numbers are not kept normalised%s\n",
3111 if (setjmp(lab
)==0) {
3112 Vprintf("%sSmallest unnormalised positive number = %s%s\n",
3113 co
, f_rep(digs
, (Long_double
) xminner
), oc
);
3114 if (V
) F_check(digs
, (Long_double
) xminner
);
3116 eek_a_bug("printf can't print the smallest unnormalised number.");
3122 Vprintf("%sThe smallest numbers are normalised%s\n", co
, oc
);
3125 /* Maximum exponent ************************************************/
3126 f_max_exp
=2; f_max
=1.0; newxmax
=base
+1.0;
3128 while (f_max
<newxmax
) {
3130 if (setjmp(lab
) == 0) { /* Yields inf, f_max_exp */
3131 newxmax
=Mul(newxmax
, base
);
3136 if (Div(newxmax
, base
) != f_max
) {
3137 if (newxmax
> f_max
) inf
=1; /* ieee infinity */
3143 Vprintf("%sMaximum exponent = %d%s\n", co
, f_max_exp
, oc
);
3144 if (F
) i_define(D_MAX_EXP
, thing
, Fname
, "_MAX_EXP",
3145 (long) f_max_exp
, 0L, (long) F_MAX_EXP
, "");
3147 /* Largest number ***************************************************/
3148 f_max
=Diff(ONE
, epsneg
);
3149 if (Mul(f_max
,ONE
) != f_max
) f_max
=Diff(ONE
, Mul(base
,epsneg
));
3150 for (i
=1; i
<=f_max_exp
; i
++) f_max
=Mul(f_max
, base
);
3152 if (setjmp(lab
)==0) {
3153 Vprintf("%sMaximum number = %s%s\n",
3154 co
, f_rep(digs
, (Long_double
) f_max
), oc
);
3156 eek_a_bug("printf can't print the largest double.");
3159 if (setjmp(lab
)==0) {
3160 /* Possible loss of precision warnings here from non-stdc compilers */
3161 if (F
) f_define(D_MAX
, thing
,
3162 Fname
, "_MAX", digs
, (Long_double
) f_max
, MARK
);
3163 if (V
|| F
) F_check(digs
, (Long_double
) f_max
);
3165 eek_a_bug("xxx_MAX caused a trap");
3168 if (setjmp(lab
)==0) {
3169 if (F
) Verify(digs
, f_max
, F_MAX
,
3170 f_max
== Self(F_MAX
),
3171 (Long_double
) f_max
== (Long_double
) F_MAX
);
3173 printf("%s*** Verify failed for above #define!\n %s %s\n\n",
3174 co
, "Compiler has an unusable number for value", oc
);
3179 a
=1.0; f_max_10_exp
=0;
3180 while (a
< f_max
/10.0) { a
*=10.0; f_max_10_exp
++; }
3181 if (F
) i_define(D_MAX_10_EXP
, thing
, Fname
, "_MAX_10_EXP",
3182 (long) f_max_10_exp
, 0L, (long) F_MAX_10_EXP
, "");
3184 /* Traps and infinities ********************************************/
3186 Vprintf("%sOverflow generates a trap%s\n", co
, oc
);
3188 Vprintf("%sOverflow doesn't seem to generate a trap%s\n",
3192 if (inf
) { Vprintf("%sThere is an 'infinite' value%s\n", co
, oc
); }
3195 signal(SIGFPE
, trap1
);
3197 if (setjmp(lab
) == 0) {
3198 trapped
= 0; /* A global variable */
3202 Vprintf("%sDivide by zero doesn't generate a trap%s\n",
3205 Vprintf("%sDivide by zero generates a trap%s\n",
3207 Vprintf("%sFP signal handlers return safely%s\n",
3211 Vprintf("%sDivide by zero generates a trap%s\n", co
, oc
);
3212 Vprintf("%sBEWARE! FP signal handlers can NOT return%s\n",
3218 /* Hidden bit + sanity check ****************************************/
3219 if (f_radix
!= 10) {
3221 mantbits
=floor_log(2, (Long_double
)f_radix
)*f_mant_dig
;
3222 if (mantbits
+iexp
== (int)sizeof(Number
)*byte_size
) {
3224 Vprintf("%sArithmetic uses a hidden bit%s\n", co
, oc
);
3225 } else if (mantbits
+iexp
+1 == (int)sizeof(Number
)*byte_size
) {
3226 Vprintf("%sArithmetic doesn't use a hidden bit%s\n",
3228 } else if (mantbits
+iexp
+1 < (int)sizeof(Number
)*byte_size
) {
3229 Vprintf("%sOnly %d of the %d bits of a %s %s%s\n",
3232 (int)sizeof(Number
)*byte_size
,
3234 "are actually used",
3237 printf("\n%s%s\n %s (%d) %s (%d) %s %s (%d)!%s\n\n",
3239 "*** Something fishy here!",
3242 "+ significand size",
3244 "doesn't match with the size of a",
3246 (int)sizeof(Number
)*byte_size
,
3249 if (hidden
&& f_radix
== 2 && f_max_exp
+f_min_exp
==3) {
3250 Vprintf("%sIt looks like %s length IEEE format%s\n",
3251 co
, f_mant_dig
==24 ? "single" :
3252 f_mant_dig
==53 ? "double" :
3253 f_mant_dig
>53 ? "extended" :
3255 if (f_rounds
!= 1 || normal
) {
3256 Vprintf("%s though ", co
);
3257 if (f_rounds
!= 1) {
3258 Vprintf("the rounding is unusual");
3259 if (normal
) { Vprintf(" and "); }
3262 Vprintf("the normalisation is unusual");
3264 Vprintf("%s\n", oc
);
3267 Vprintf("%sIt doesn't look like IEEE format%s\n",
3271 printf("\n"); /* regardless of verbosity */
3275 Void
EPROP(int fprec
, int dprec
, int lprec
)
3277 /* See if expressions are evaluated in extended precision.
3278 Some compilers optimise even if you don't want it,
3279 and then this function fails to produce the right result.
3280 We try to diagnose this if it happens.
3283 Volatile
double a
, b
, base
, old
;
3284 Volatile Number d
, oldd
, dbase
, one
, zero
;
3287 /* Size of significand **************************************/
3289 if (setjmp(lab
) == 0) { /* Yields nothing */
3290 do { old
=a
; a
=a
+a
; }
3291 while ((((a
+1.0)-a
)-1.0) == 0.0 && a
>old
);
3293 if (!bad
&& a
<= old
) bad
=1;
3297 if (setjmp(lab
) == 0) { /* Yields nothing */
3298 do { old
=b
; b
=b
+b
; }
3299 while ((base
=((a
+b
)-a
)) == 0.0 && b
>old
);
3300 if (b
<= old
) bad
=1;
3305 eprec
=0; d
=1.0; dbase
=base
; one
=1.0; zero
=0.0;
3306 if (setjmp(lab
) == 0) { /* Yields nothing */
3307 do { eprec
++; oldd
=d
; d
=d
*dbase
; }
3308 while ((((d
+one
)-d
)-one
) == zero
&& d
>oldd
);
3309 if (d
<= oldd
) bad
=1;
3316 Vprintf("%sCan't determine precision for %s expressions:\n%s%s\n",
3317 co
, thing
, " check that you compiled without optimisation!",
3319 } else if (eprec
==dprec
) {
3320 Vprintf("%s%s expressions are evaluated in double precision%s\n",
3322 } else if (eprec
==fprec
) {
3323 Vprintf("%s%s expressions are evaluated in float precision%s\n",
3325 } else if (eprec
==lprec
) {
3326 Vprintf("%s%s expressions are evaluated in long double precision%s\n",
3329 Vprintf("%s%s expressions are evaluated in a %s %s %d %s%s\n",
3330 co
, Thing
, eprec
>dprec
? "higher" : "lower",
3331 "precision than double,\n using",
3332 eprec
, "base digits",
3337 #else /* not Number */
3339 #ifdef FPROP /* Then create dummy routines for long double */
3341 int FPROP(int byte_size
) { return 0; }
3345 Void
EPROP(int fprec
, int dprec
, int lprec
) {}
3348 #endif /* ifdef Number */
3350 /* Increment the pass number */
3370 #ifdef PASS /* then rescan this file */
3372 #include "enquire.c"
3374 #include FILENAME /* if this line fails to compile, define BAD_CPP */