1 /** @file 2 Every thing you wanted to know about your compiler but didn't know whom to ask. 3 4 COPYRIGHT(c) 1993-9 Steven Pemberton, CWI. All rights reserved. 5 Steven Pemberton, CWI, Amsterdam; "Steven.Pemberton@cwi.nl" 6 Used with permission. 7 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. 13 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. 16 **/ 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) */ 26 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() 32 33 /* Some compilers can't cope with "#ifdef __FILE__". Use 34 either the FILENAME or BAD_CPP macro as described below. 35 */ 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. 39 */ 40 //#define FILENAME "enquire.c" 41 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. 44 */ 45 //#define BAD_CPP 1 46 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). 51 */ 52 //#define BAD_STDC 1 53 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.) 57 */ 58 //#define BAD_STDDEF 1 59 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. 63 */ 64 //#define BAD_MALLOC 1 65 66 67 68 #ifndef PROGRAM 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" 79 #endif 80 81 #ifdef NOTDEFINED /* This is how you compile it; see below for details */ 82 case $0 in 83 *.c) ;; 84 sh) echo 'Use "sh enquire.c", not "sh < enquire.c"' >&2; exit 1;; 85 *) echo 'Filename must end in ".c"' >&2; exit 1;; 86 esac 87 if test -r test.c 88 then echo Would overwrite test.c - try it somewhere safer >&2; exit 1 89 fi 90 CFLAGS= 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 94 then : 95 else 96 echo '*** "'$CC ${1+"$@"} -o enquire test.c $LIBS'" failed' 97 echo '*** Giving up' 98 /bin/rm -f test.c 99 exit 1 100 fi 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" 104 else 105 CFLAGS=-DNO_SC 106 echo " Signed char not accepted; using $CFLAGS" 107 fi 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" 111 else 112 CFLAGS="$CFLAGS -DNO_UC" 113 echo " Unsigned char not accepted; using $CFLAGS" 114 fi 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" 118 else 119 CFLAGS="$CFLAGS -DNO_UI" 120 echo " Unsigned short or long not accepted; using $CFLAGS" 121 fi 122 echo "void foo(){} main(){foo();}" > test.c 123 if $CC ${1+"$@"} -o enquire test.c $LIBS 2>/dev/null 124 then echo " Void ok" 125 else 126 CFLAGS="$CFLAGS -DNO_VOID" 127 echo " Void not accepted; using $CFLAGS" 128 fi 129 /bin/rm -f test.c a.out 130 131 echo Compiling $0 ... 132 case $# in 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' ;; 137 "1 2") ;; 138 esac 139 esac 140 case $ID in 141 "") echo " $CC" $CFLAGS "$@" $0 -o enquire $LIBS 142 $CC $CFLAGS ${1+"$@"} $0 -o enquire $LIBS || 143 { echo '***' Try setting some CFLAGS; exit 1; } 144 ;; 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; } 148 esac 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' 163 echo Done 164 exit 0 165 #endif 166 167 /* 168 PURPOSE 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] 172 double, and so on. 173 174 As an option it produces the ANSI C float.h and limits.h files. 175 176 As a further option, it even checks that the compiler reads the 177 header files correctly. 178 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 181 numbers. 182 183 COMPILING AND RUNNING ON UNIX MACHINES 184 With luck and a following wind, on Unix systems just the following 185 will work: 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 190 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. 193 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 200 201 Compiling may give messages about unreachable code. These you can ignore. 202 203 Some compilers offer various flags for different floating point 204 modes; it's worth trying all possible combinations of these. 205 206 Don't say I haven't tried to make life easy for you... 207 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 213 enquire -f > float.h 214 cc -DVERIFY enquire.c -o verify #this includes limits.h and float.h 215 verify -fl > verify.out 216 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 221 void -DNO_VOID 222 signal(), or setjmp/longjmp() -DNO_SIG 223 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. 227 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. 231 232 Compiling may give messages about unreachable code. These you can ignore. 233 234 Some compilers offer various flags for different floating point 235 modes; it's worth trying all possible combinations of these. 236 237 FAULTY COMPILERS 238 Because of bugs and/or inadequacies, some compilers need the following 239 defines: 240 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\" . 244 245 - Some compilers won't accept the line "#include FILENAME". Add 246 flag -DBAD_CPP. In that case, this file *must* be called 247 enquire.c. 248 249 - Some compilers can't cope with "#ifdef __FILE__". Use 250 -DFILENAME= or -DBAD_CPP as above. 251 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). 256 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 260 include files.) 261 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. 265 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 274 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 284 285 SYSTEM DEPENDENCIES 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!). 289 290 OUTPUT 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. 299 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. 312 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. 315 316 TROUBLESHOOTING. 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 320 accepted, etc.) 321 322 The program only works if overflows are ignored by the C system or 323 are catchable with signal(). 324 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. 329 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). 333 334 Make sure you compiled with optimisation turned off. 335 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. 359 360 The warning that "a cast didn't work" refers to cases like this: 361 362 float f; 363 #define C 1.234567890123456789 364 f= C; 365 if (f != (float) C) printf ("Wrong!"); 366 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 374 wrong precision". 375 376 REPORTING PROBLEMS 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! 385 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. 389 390 I apologise unreservedly for the contorted use of the preprocessor... 391 but it was fun! 392 393 NEW VERSIONS 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 398 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 402 enquire.ps. 403 404 THE SMALL PRINT 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: 408 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 418 here. 419 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. 423 424 If you do have a fix to any problem, please send it to me, so that 425 other people can have the benefits. 426 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. 431 432 ACKNOWLEDGEMENTS 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. 435 436 HISTORY 437 Originally started as a program to generate configuration constants 438 for a large piece of software we were writing, which later took on 439 a life of its own... 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 447 Handles Cybers 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 453 Handles long double 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 458 Added SEP 459 Fixed eps/epsneg 460 Added check for pseudo-unsigned chars 461 Added description for each #define output 462 Added check for absence of defines during verify 463 Added prototypes 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 483 Added BAD_STDDEF 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 488 Added BAD_MALLOC 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 495 Added TESTI 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 504 Fixed NO_UI 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> 509 5.0a Aug 1997 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 519 */ 520 521 /* Set FILENAME to the name of this file */ 522 #ifndef FILENAME 523 #ifdef BAD_CPP 524 #define FILENAME "enquire.c" 525 #else 526 #ifdef __FILE__ /* It's a compiler bug if this fails. Define BAD_CPP */ 527 #define FILENAME __FILE__ 528 #else 529 #define FILENAME "enquire.c" 530 #endif /* __FILE__ */ 531 #endif /* BAD_CPP */ 532 #endif /* FILENAME */ 533 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. 539 */ 540 #ifndef PASS 541 #ifdef SEP /* so we're only interested if this is pass 1 or not */ 542 #ifdef PASS1 543 #define PASS 1 544 #else 545 #define PASS 0 546 #endif 547 #else /* no SEP, so this is the first pass */ 548 #define PASS 1 549 #define PASS0 1 550 #define PASS1 1 551 #endif /* SEP */ 552 553 /* Void just marks the functions that don't return a result */ 554 #ifdef NO_VOID 555 #define Void int 556 #else 557 #define Void void 558 #endif 559 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. 563 */ 564 #ifndef BAD_STDC 565 #ifdef __STDC__ 566 #if __STDC__ /* If __STDC__ is 0, assume it isn't supported */ 567 #define STDC 568 #endif 569 #endif 570 #endif 571 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. 580 */ 581 #ifdef STDC 582 583 #define ARGS(x) x 584 #define NOARGS (void) 585 #define Volatile volatile 586 #define Long_double long double 587 #define stdc 1 588 #define U "U" 589 590 #else /* Old style C */ 591 592 #define ARGS(x) () 593 #define NOARGS () 594 #define Volatile static 595 #define Long_double double 596 #define stdc 0 597 #define U "" 598 599 #endif /* STDC */ 600 601 /* include files */ 602 #include <stdio.h> 603 #include <wchar.h> 604 605 #ifdef STDC 606 #ifndef BAD_STDDEF 607 #include <stddef.h> /* for size_t: if this fails, define BAD_STDDEF */ 608 #endif 609 #endif 610 611 #ifdef NO_SIG 612 #define jmp_buf int 613 #else 614 #include <signal.h> /* if this fails, define NO_SIG */ 615 #include <setjmp.h> /* if this fails, define NO_SIG */ 616 #endif 617 //#ifndef NO_SIG 618 //#include <signal.h> /* if this fails, define NO_SIG */ 619 //#include <setjmp.h> /* if this fails, define NO_SIG */ 620 //#endif 621 622 /* Kludge around the possiblity that <stdio.h> includes <limits.h> */ 623 #ifdef CHAR_BIT 624 #undef CHAR_BIT 625 #undef CHAR_MAX 626 #undef CHAR_MIN 627 #undef SCHAR_MAX 628 #undef SCHAR_MIN 629 #undef UCHAR_MAX 630 #undef UCHAR_MIN 631 #endif 632 633 #ifdef VERIFY 634 #include "limits.h" 635 #include "float.h" 636 #endif 637 638 /* The largest unsigned type */ 639 #ifdef NO_UI 640 #define ulong unsigned int 641 #else 642 #define ulong unsigned long 643 #endif 644 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)) 649 650 #endif /* PASS */ 651 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)" 659 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)" 663 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" 675 676 #ifdef PASS0 677 678 /* Prototypes for what's to come: */ 679 680 int false NOARGS; 681 682 #ifdef BAD_STDDEF 683 char *malloc (); /* Old style prototype, since we don't know what size_t is */ 684 #else 685 char *malloc ARGS((size_t size)); 686 #endif 687 Void free ARGS((char *p)); /* Syntax error here? Try -DNO_VOID */ 688 689 Void exit ARGS((int status)); 690 691 char *f_rep ARGS((int precision, Long_double val)); 692 693 int maximum_int NOARGS; 694 int cprop NOARGS; 695 int basic NOARGS; 696 Void sprop NOARGS; 697 Void iprop NOARGS; 698 Void lprop NOARGS; 699 Void usprop NOARGS; 700 Void uiprop NOARGS; 701 Void ulprop 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)); 708 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)); 729 730 #ifdef NO_SIG /* There's no signal(), or setjmp/longjmp() */ 731 732 /* Dummy routines instead */ 733 typedef int jmp_buf; 734 735 int setjmp ARGS((jmp_buf lab)); 736 737 jmp_buf lab, mlab; 738 int setjmp(jmp_buf lab) { return(0); } 739 void longjmp(jmp_buf lab, int val) { return; } 740 741 Void signal(int i, void (*p)()) {} 742 743 #else 744 jmp_buf lab, mlab; 745 Void overflow(int sig) 746 { /* what to do on over/underflow */ 747 signal(sig, overflow); 748 longjmp(lab, 1); 749 } 750 751 Void address(int sig) 752 { /* what to do on an address error */ 753 signal(sig, address); 754 longjmp(mlab, 1); 755 } 756 757 #endif /*NO_SIG*/ 758 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 */ 763 764 char co[4], oc[4]; /* Comment starter and ender symbols */ 765 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 */ 770 771 #ifdef TEST 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 777 */ 778 779 /* Bits 0x30 = rounding mode */ 780 #define ROUND_BITS 0x30 781 #define TO_NEAREST 0x00 782 #define TO_ZERO 0x10 783 #define TO_MINUS_INF 0x20 784 #define TO_PLUS_INF 0x30 /* The SUN FP user's guide seems to be wrong here */ 785 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 791 792 /* Enabled traps */ 793 #define EXE_INEX1 0x100 794 #define EXE_INEX2 0x200 795 #define EXE_DZ 0x400 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 801 802 /* Only used for testing, on a Sun with 68881 chip */ 803 /* Print the FP mode */ 804 printmode(new) unsigned new; { 805 fpmode_(&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; 814 } 815 816 printf("\n Extended rounding precision: "); 817 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; 823 } 824 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"); 834 printf("\n"); 835 } 836 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; 841 char c; 842 843 while (*s) { 844 c= *s++; 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; 848 else return 1; 849 mode= mode<<4 | dig; 850 } 851 printmode(mode); 852 return 0; 853 } 854 #define SETMODE 855 #endif 856 857 #ifdef TESTI /* Test mode using SunOs IEEE routines */ 858 859 #include <sys/ieeefp.h> 860 861 int setmode(char *s) { 862 char *dummy, c, *cmd, *val; 863 while (*s) { 864 switch (c= *s++) { 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; 876 default: 877 printf("Bad setmode character: %c\n", c); 878 return 1; 879 break; 880 } 881 printf("Set %s %s", cmd, val); 882 if (ieee_flags("set", cmd, val, &dummy)) { 883 printf(": failed\n"); 884 return 1; 885 } 886 printf("\n"); 887 } 888 return 0; 889 } 890 #define SETMODE 891 #endif 892 893 #ifndef SETMODE 894 /* ARGSUSED */ 895 int 896 setmode(char *s) 897 { 898 fprintf(stderr, "Can't set mode: not compiled with TEST\n"); 899 return(1); 900 } 901 #endif 902 903 int 904 memeq( 905 char *p1, 906 int size1, 907 char *p2, 908 int size2 909 ) 910 { 911 /* See if two blocks of store are identical */ 912 int i; 913 if (size1 != size2) return 0; 914 for (i=1; i<=size1; i++) { 915 if (*p1++ != *p2++) return 0; 916 } 917 return 1; 918 } 919 920 Void 921 farewell(int bugs) 922 { 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); 929 exit(bugs); 930 } 931 932 /* The program has received a signal where it wasn't expecting one */ 933 Void 934 croak(int place) 935 { 936 printf("*** Unexpected signal at point %d\n", place); 937 farewell(bugs+1); /* An exit isn't essential here, but avoids loops */ 938 } 939 940 /* This is here in case alloca.c is used, which calls this. */ 941 char * 942 xmalloc(unsigned size) 943 { 944 char *value = malloc(size); 945 if (value == 0) { 946 fprintf(stderr, "Virtual memory exceeded\n"); 947 exit(bugs+1); 948 } 949 return value; 950 } 951 952 int maxint; 953 954 int 955 maximum_int( void ) 956 { 957 /* Find the maximum integer */ 958 Volatile int newi, int_max, two=2; 959 960 /* Calculate maxint ***********************************/ 961 /* Calculate 2**n-1 until overflow - then use the previous value */ 962 963 newi=1; int_max=0; 964 965 if (setjmp(lab)==0) { /* Yields int_max */ 966 while(newi>int_max) { 967 int_max=newi; 968 newi=newi*two+1; 969 } 970 } 971 Unexpected(0); 972 return int_max; 973 } 974 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. 977 */ 978 979 int zzzzzzzzz1zzzzzzzzz2zzzzzzzzz3zzzzzzzzz4zzzzzzzzz5zzzzzzzzz6zzzz=64; 980 981 int 982 name_len( void ) 983 { 984 int zzzzzzzzz1zzzzzzzzz2zzzzzzzzz3zz=32; 985 { int zzzzzzzzz1zzzzzz=16; 986 { int zzzzzzzz=8; 987 { int zzzzzzz=7; 988 { int zzzzzz=6; 989 return 990 zzzzzzzzz1zzzzzzzzz2zzzzzzzzz3zzzzzzzzz4zzzzzzzzz5zzzzzzzzz6zzzz; 991 } 992 } 993 } 994 } 995 } 996 997 #define aaaaaaaaa1aaaaaaaaa2aaaaaaaaa3aaaaaaaaa4aaaaaaaaa5aaaaaaaaa6aaaa 64 998 #define LENGTH 64 999 1000 #ifdef aaaaaaaaa1aaaaaaaaa2aaaaaaaaa3aa 1001 #undef LENGTH 1002 #define LENGTH 32 1003 #endif 1004 1005 #ifdef aaaaaaaaa1aaaaaa 1006 #undef LENGTH 1007 #define LENGTH 16 1008 #endif 1009 1010 #ifdef aaaaaaaa 1011 #undef LENGTH 1012 #define LENGTH 8 1013 #endif 1014 1015 #undef aaaaaaaaa1aaaaaaaaa2aaaaaaaaa3aaaaaaaaa4aaaaaaaaa5aaaaaaaaa6aaaa 1016 1017 Void long_names() 1018 { 1019 int l= name_len(); 1020 Vprintf("Compiler names are at least %d chars long", l); 1021 if (l != 64) 1022 Vprintf(" (but less than %d)", l*2); 1023 Vprintf("\n"); 1024 Vprintf("Preprocessor names are at least %d long", LENGTH); 1025 if (LENGTH != 64) 1026 Vprintf(" (but less than %d)", LENGTH*2); 1027 Vprintf("\n\n"); 1028 } 1029 1030 /* Used by FPROP to see if FP traps are generated, and if they may return */ 1031 1032 Void 1033 trap2(int sig) 1034 { 1035 longjmp(lab, 1); 1036 } 1037 1038 Void 1039 trap1(int sig) 1040 { 1041 trapped= 1; /* A global */ 1042 signal(sig, trap2); 1043 } 1044 1045 Void 1046 setsignals( void ) 1047 { 1048 #ifdef SIGFPE 1049 signal(SIGFPE, overflow); 1050 #endif 1051 #ifdef SIGOVER 1052 signal(SIGOVER, overflow); 1053 #endif 1054 #ifdef SIGBUS 1055 signal(SIGBUS, address); 1056 #endif 1057 #ifdef SIGSEGV 1058 signal(SIGSEGV, address); 1059 #endif 1060 /* Add more calls as necessary */ 1061 } 1062 1063 #undef LENGTH 1064 1065 int 1066 main(int argc, char *argv[]) 1067 { 1068 int dprec, fprec, lprec; 1069 int i; 1070 wchar_t *s; 1071 int bad; 1072 1073 setsignals(); 1074 Unexpected(1); 1075 1076 bad=0; 1077 for (i=1; i < argc; i++) { 1078 s = (wchar_t *)(argv[i]); 1079 if (*s == L'-') { 1080 s++; 1081 while (*s) { 1082 switch (*(s++)) { 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; 1087 } 1088 } 1089 } else if (*s == L'+') { 1090 s++; 1091 bad = setmode((char *)s); 1092 } else bad= 1; 1093 } 1094 if (bad) { 1095 fprintf(stderr, 1096 "Usage: %ls [-vlf]\n v=Verbose l=Limits.h f=Float.h\n", 1097 (wchar_t *)(argv[0])); 1098 exit(1); 1099 } 1100 if (L || F) { 1101 co[0]= '/'; oc[0]= ' '; 1102 co[1]= '*'; oc[1]= '*'; 1103 co[2]= ' '; oc[2]= '/'; 1104 co[3]= '\0'; oc[3]= '\0'; 1105 } else { 1106 co[0]= '\0'; oc[0]= '\0'; 1107 V=1; 1108 } 1109 1110 if (L) printf("%slimits.h%s\n", co, oc); 1111 if (F) printf("%sfloat.h%s\n", co, oc); 1112 #ifdef ID 1113 printf("%sProduced by enquire version %s (%s), CWI, Amsterdam\n %s\n", 1114 co, VERSION, ID, WEB, oc); 1115 #else 1116 printf("%sProduced by enquire version %s, CWI, Amsterdam\n %s %s\n", 1117 co, VERSION, WEB, oc); 1118 #endif 1119 1120 #ifdef VERIFY 1121 printf("%sVerification phase%s\n", co, oc); 1122 #endif 1123 1124 #ifdef NO_SIG 1125 Vprintf("%sCompiled without signal(): %s%s\n", 1126 co, 1127 "there's nothing that can be done if overflow occurs", 1128 oc); 1129 #endif 1130 #ifdef NO_SC 1131 Vprintf("%sCompiled without signed char%s\n", co, oc); 1132 #endif 1133 #ifdef NO_UC 1134 Vprintf("%sCompiled without unsigned char%s\n", co, oc); 1135 #endif 1136 #ifdef NO_UI 1137 Vprintf("%sCompiled without unsigned short or long%s\n", co, oc); 1138 #endif 1139 #ifdef __STDC__ 1140 Vprintf("%sCompiler claims to be ANSI C level %d%s\n", 1141 co, __STDC__, oc); 1142 #else 1143 Vprintf("%sCompiler does not claim to be ANSI C%s\n", co, oc); 1144 #endif 1145 printf("\n"); 1146 1147 long_names(); 1148 check_defines(); 1149 1150 maxint= maximum_int(); 1151 bits_per_byte= basic(); 1152 Vprintf("\n"); 1153 if (F||V) { 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); 1160 } 1161 #ifndef BAD_MALLOC 1162 if (V) { 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 */ 1168 unsigned int size; 1169 Volatile long total; 1170 char kmg, *ptr, *save; 1171 char **link; 1172 1173 save= NULL; 1174 size=maximum_int()/4; 1175 total=0; 1176 while (size!=0) { 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; 1181 if (save == NULL) { 1182 // Save pointer to first allocated chunk 1183 save= ptr; 1184 *link = NULL; 1185 } 1186 else { 1187 // Build list of all subsequently allocated chunks, LIFO 1188 *link = save; 1189 save = ptr; 1190 } 1191 total+=(size/2); 1192 } 1193 } else { 1194 eek_a_bug("Trying to malloc all store generates a trap"); 1195 } 1196 size/=2; 1197 } 1198 if (setjmp(mlab)!=0) croak(-1); 1199 1200 //if (save != NULL) free(save); 1201 while(save != NULL) { 1202 link = (char **)save; 1203 ptr = *link; 1204 free(save); 1205 save = ptr; 1206 } 1207 1208 total= (total+511)/512; /* Sic */ kmg= 'K'; 1209 if (total > 10000) { 1210 total= (total+999)/1000; kmg= 'M'; 1211 } 1212 if (total > 10000) { 1213 total= (total+999)/1000; kmg= 'G'; 1214 } 1215 if (total > 10000) { 1216 total= (total+999)/1000; kmg= 'T'; 1217 } 1218 Vprintf("%sMemory mallocatable ~= %ld %cbytes%s\n", 1219 co, total, kmg, oc); 1220 } 1221 #endif 1222 farewell(bugs); 1223 return bugs; /* To keep compilers and lint happy */ 1224 } 1225 1226 Void 1227 eek_a_bug(char *problem) 1228 { 1229 /* The program has discovered a problem */ 1230 printf("\n%s*** WARNING: %s%s\n", co, problem, oc); 1231 bugs++; 1232 } 1233 1234 Void 1235 describe(char *description, char *extra) 1236 { 1237 /* Produce the description for a #define */ 1238 printf(" %s", co); 1239 printf(description, extra); 1240 printf("%s\n", oc); 1241 } 1242 1243 Void 1244 i_define( 1245 char *desc, 1246 char *extra, 1247 char *sort, 1248 char *name, 1249 long val, 1250 long lim, 1251 long req, 1252 char *mark 1253 ) 1254 { 1255 /* Produce a #define for a signed int type */ 1256 describe(desc, extra); 1257 if (val >= 0) { 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); 1265 } else { 1266 printf("#define %s%s (%ld%s)\n", sort, name, val, mark); 1267 } 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 1271 */ 1272 if (val != req) { 1273 printf("%s*** Verify failed for above #define!\n", co); 1274 printf(" Compiler has %ld for value%s\n\n", req, oc); 1275 bugs++; 1276 } 1277 Vprintf("\n"); 1278 } 1279 1280 Void 1281 u_define( 1282 char *desc, 1283 char *extra, 1284 char *sort, 1285 char *name, 1286 ulong val, 1287 ulong req, 1288 char *mark 1289 ) 1290 { 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); 1294 if (val != req) { 1295 printf("%s*** Verify failed for above #define!\n", co); 1296 printf(" Compiler has %lu for value%s\n\n", req, oc); 1297 bugs++; 1298 } 1299 Vprintf("\n"); 1300 } 1301 1302 Void f_define( 1303 char *desc, 1304 char *extra, 1305 char *sort, 1306 char *name, 1307 int precision, 1308 Long_double val, 1309 char *mark 1310 ) 1311 { 1312 /* Produce a #define for a float/double/long double */ 1313 describe(desc, extra); 1314 if (stdc) { 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)); 1321 } else { 1322 printf("#define %s%s %s\n", sort, name, f_rep(precision, val)); 1323 } 1324 Vprintf("\n"); 1325 } 1326 1327 int 1328 floor_log(int base, Long_double x) 1329 { 1330 /* return floor(log base(x)) */ 1331 int r=0; 1332 while (x>=base) { r++; x/=base; } 1333 return r; 1334 } 1335 1336 int 1337 ceil_log(int base, Long_double x) 1338 { 1339 int r=0; 1340 while (x>1.0) { r++; x/=base; } 1341 return r; 1342 } 1343 1344 int 1345 exponent(Long_double x, Long_double *fract, int *exp) 1346 { 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. 1350 */ 1351 int r=0, neg=0; 1352 Long_double old; 1353 *fract=0.0; *exp=0; 1354 if (x<0.0) { 1355 x= -x; 1356 neg= 1; 1357 } 1358 if (x==0.0) return 1; 1359 if (x>=10.0) { 1360 while (x>=10.0) { 1361 old=x; r++; x/=10.0; 1362 if (old==x) return 0; 1363 } 1364 } else { 1365 while (x<1.0) { 1366 old=x; r--; x*=10.0; 1367 if (old==x) return 0; 1368 } 1369 } 1370 if (neg) *fract= -x; 1371 else *fract= x; 1372 *exp=r; 1373 return 1; 1374 } 1375 1376 char * 1377 f_rep(int precision, Long_double val) 1378 { 1379 /* Return the floating representation of val */ 1380 static char buf[1024]; 1381 char *f1; 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 */ 1385 f1= "%.*e"; 1386 } else { 1387 /* It had better support Le then */ 1388 f1= "%.*Le"; 1389 } 1390 sprintf(buf, f1, precision, val); 1391 return buf; 1392 } 1393 1394 Void 1395 bitpattern(char *p, unsigned int size) 1396 { 1397 /* Printf the bit-pattern of p */ 1398 char c; 1399 unsigned int i; 1400 int j; 1401 1402 for (i=1; i<=size; i++) { 1403 c= *p; 1404 p++; 1405 for (j=bits_per_byte-1; j>=0; j--) 1406 printf("%c", (c>>j)&1 ? '1' : '0'); 1407 if (i!=size) printf(" "); 1408 } 1409 } 1410 1411 Void 1412 fill(char *p, int size) 1413 { 1414 char *ab= "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 1415 int i; 1416 1417 for (i=0; i<size; i++) 1418 p[i]= ab[i]; 1419 } 1420 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); }\ 1425 printf("%s\n", oc); 1426 1427 Void 1428 endian(int byte_size) 1429 { 1430 /* Printf the byte-order used on this machine */ 1431 /*unsigned*/ short s=0; 1432 /*unsigned*/ int j=0; 1433 /*unsigned*/ long l=0; 1434 1435 unsigned int mask, i, c; 1436 1437 mask=0; 1438 for (i=1; i<=(unsigned)byte_size; i++) mask= (mask<<1)|1; 1439 1440 if (V) { 1441 printf("%sCHARACTER ORDER%s\n", co, oc); 1442 Order(s, "short:"); 1443 Order(j, "int: "); 1444 Order(l, "long: "); 1445 } 1446 } 1447 1448 Void 1449 missing(char *s) 1450 { 1451 printf("%s*** #define %s missing from limits.h%s\n", co, s, oc); 1452 bugs++; 1453 } 1454 1455 Void 1456 fmissing(char *s) 1457 { 1458 printf("%s*** #define %s missing from float.h%s\n", co, s, oc); 1459 bugs++; 1460 } 1461 1462 /* To try and fool optimisers */ 1463 int false( void ) { return 0; } 1464 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") 1468 #define Signed 1 1469 #define Unsigned 0 1470 #define sgn(x) ((is_signed(x))?Signed:Unsigned) 1471 1472 #define showtype(t, x) Vprintf("%s%s %s %s%s\n", co, t, sign_of(x), type_of((int)sizeof(x)), oc) 1473 1474 char *type_of(int x) 1475 { 1476 if (x == sizeof(char)) { 1477 if (sizeof(char) == sizeof(int)) return "char/short/int"; 1478 if (sizeof(char) == sizeof(short)) return "char/short"; 1479 return "char"; 1480 } 1481 if (x == sizeof(short)) { 1482 if (sizeof(short) == sizeof(int)) return "short/int"; 1483 return "short"; 1484 } 1485 if (x == sizeof(int)) { 1486 if (sizeof(int) == sizeof(long)) return "int/long"; 1487 return "int"; 1488 } 1489 if (x == sizeof(long)) return "long"; 1490 return "unknown-type"; 1491 } 1492 1493 char *ftype_of(int x) 1494 { 1495 if (x == sizeof(float)) { 1496 return "float"; 1497 } 1498 if (x == sizeof(double)) { 1499 if (sizeof(double) == sizeof(Long_double)) 1500 return "(long)double"; 1501 return "double"; 1502 } 1503 if (x == sizeof(Long_double)) { 1504 return "long double"; 1505 } 1506 return "unknown-type"; 1507 } 1508 1509 Void typerr(char *name, int esign, int esize, int sign, int size) 1510 { 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)); 1514 } 1515 1516 Void ftyperr(char *name, int esize, int size) 1517 { 1518 Vprintf("*** %s has wrong type: expected %s, found %s\n", 1519 name, ftype_of(esize), ftype_of(size)); 1520 } 1521 1522 Void promotions( void ) 1523 { 1524 int si; long sl; 1525 unsigned int ui; 1526 short ss; 1527 1528 #ifndef NO_UI 1529 unsigned long ul; /* if this fails, define NO_UI */ 1530 unsigned short us; /* if this fails, define NO_UI */ 1531 1532 ul=0; us=0; 1533 #endif 1534 /* Shut compiler warnings up: */ 1535 si=0; sl=0; ui=0; ss=0; 1536 1537 Vprintf("\n%sPROMOTIONS%s\n", co, oc); 1538 1539 /* Sanity checks. Possible warnings here; should be no problem */ 1540 if (is_signed(ui)) 1541 eek_a_bug("unsigned int promotes to signed!\n"); 1542 if (!is_signed(si)) 1543 eek_a_bug("signed int promotes to unsigned!\n"); 1544 if (!is_signed(sl)) 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"); 1554 #ifndef NO_UI 1555 if (sizeof(Promoted(ul)) != sizeof(long)) 1556 eek_a_bug("unsigned long doesn't promote to long!\n"); 1557 if (is_signed(ul)) 1558 eek_a_bug("unsigned long promotes to signed!\n"); 1559 #endif 1560 1561 #ifndef NO_UI 1562 showtype("unsigned short promotes to", Promoted(us)); 1563 #endif 1564 showtype("long+unsigned gives", sl+ui); 1565 } 1566 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)); 1568 1569 #define fchecktype(x, n, t) if (sizeof(x) != sizeof(t)) ftyperr(n, (int)sizeof(x), (int)sizeof(t)); 1570 1571 Void check_defines( void ) 1572 { 1573 /* ensure that all #defines are present and have the correct type */ 1574 #ifdef VERIFY 1575 int usign; 1576 1577 #ifdef NO_UI 1578 usign= Signed; 1579 #else 1580 /* Implementations promote unsigned short differently */ 1581 usign= is_signed((unsigned short)0); 1582 #endif 1583 1584 if (L) { 1585 #ifdef CHAR_BIT 1586 checktype(CHAR_BIT, "CHAR_BIT", Signed, int); 1587 #else 1588 missing("CHAR_BIT"); 1589 #endif 1590 #ifdef CHAR_MAX 1591 checktype(CHAR_MAX, "CHAR_MAX", Signed, int); 1592 #else 1593 missing("CHAR_MAX"); 1594 #endif 1595 #ifdef CHAR_MIN 1596 checktype(CHAR_MIN, "CHAR_MIN", Signed, int); 1597 #else 1598 missing("CHAR_MIN"); 1599 #endif 1600 #ifdef SCHAR_MAX 1601 checktype(SCHAR_MAX, "SCHAR_MAX", Signed, int); 1602 #else 1603 missing("SCHAR_MAX"); 1604 #endif 1605 #ifdef SCHAR_MIN 1606 checktype(SCHAR_MIN, "SCHAR_MIN", Signed, int); 1607 #else 1608 missing("SCHAR_MIN"); 1609 #endif 1610 #ifdef UCHAR_MAX 1611 checktype(UCHAR_MAX, "UCHAR_MAX", Signed, int); 1612 #else 1613 missing("UCHAR_MAX"); 1614 #endif 1615 #ifdef SHRT_MAX 1616 checktype(SHRT_MAX, "SHRT_MAX", Signed, int); 1617 #else 1618 missing("SHRT_MAX"); 1619 #endif 1620 #ifdef SHRT_MIN 1621 checktype(SHRT_MIN, "SHRT_MIN", Signed, int); 1622 #else 1623 missing("SHRT_MIN"); 1624 #endif 1625 #ifdef INT_MAX 1626 checktype(INT_MAX, "INT_MAX", Signed, int); 1627 #else 1628 missing("INT_MAX"); 1629 #endif 1630 #ifdef INT_MIN 1631 checktype(INT_MIN, "INT_MIN", Signed, int); 1632 #else 1633 missing("INT_MIN"); 1634 #endif 1635 #ifdef LONG_MAX 1636 checktype(LONG_MAX, "LONG_MAX", Signed, long); 1637 #else 1638 missing("LONG_MAX"); 1639 #endif 1640 #ifdef LONG_MIN 1641 checktype(LONG_MIN, "LONG_MIN", Signed, long); 1642 #else 1643 missing("LONG_MIN"); 1644 #endif 1645 #ifdef USHRT_MAX 1646 checktype(USHRT_MAX, "USHRT_MAX", usign, int); 1647 #else 1648 missing("USHRT_MAX"); 1649 #endif 1650 #ifdef UINT_MAX 1651 checktype(UINT_MAX, "UINT_MAX", Unsigned, int); 1652 #else 1653 missing("UINT_MAX"); 1654 #endif 1655 #ifdef ULONG_MAX 1656 checktype(ULONG_MAX, "ULONG_MAX", Unsigned, long); 1657 #else 1658 missing("ULONG_MAX"); 1659 #endif 1660 } /* if (L) */ 1661 1662 if (F) { 1663 #ifdef FLT_RADIX 1664 checktype(FLT_RADIX, "FLT_RADIX", Signed, int); 1665 #else 1666 fmissing("FLT_RADIX"); 1667 #endif 1668 #ifdef FLT_MANT_DIG 1669 checktype(FLT_MANT_DIG, "FLT_MANT_DIG", Signed, int); 1670 #else 1671 fmissing("FLT_MANT_DIG"); 1672 #endif 1673 #ifdef FLT_DIG 1674 checktype(FLT_DIG, "FLT_DIG", Signed, int); 1675 #else 1676 fmissing("FLT_DIG"); 1677 #endif 1678 #ifdef FLT_ROUNDS 1679 checktype(FLT_ROUNDS, "FLT_ROUNDS", Signed, int); 1680 #else 1681 fmissing("FLT_ROUNDS"); 1682 #endif 1683 #ifdef FLT_EPSILON 1684 fchecktype(FLT_EPSILON, "FLT_EPSILON", float); 1685 #else 1686 fmissing("FLT_EPSILON"); 1687 #endif 1688 #ifdef FLT_MIN_EXP 1689 checktype(FLT_MIN_EXP, "FLT_MIN_EXP", Signed, int); 1690 #else 1691 fmissing("FLT_MIN_EXP"); 1692 #endif 1693 #ifdef FLT_MIN 1694 fchecktype(FLT_MIN, "FLT_MIN", float); 1695 #else 1696 fmissing("FLT_MIN"); 1697 #endif 1698 #ifdef FLT_MIN_10_EXP 1699 checktype(FLT_MIN_10_EXP, "FLT_MIN_10_EXP", Signed, int); 1700 #else 1701 fmissing("FLT_MIN_10_EXP"); 1702 #endif 1703 #ifdef FLT_MAX_EXP 1704 checktype(FLT_MAX_EXP, "FLT_MAX_EXP", Signed, int); 1705 #else 1706 fmissing("FLT_MAX_EXP"); 1707 #endif 1708 #ifdef FLT_MAX 1709 fchecktype(FLT_MAX, "FLT_MAX", float); 1710 #else 1711 fmissing("FLT_MAX"); 1712 #endif 1713 #ifdef FLT_MAX_10_EXP 1714 checktype(FLT_MAX_10_EXP, "FLT_MAX_10_EXP", Signed, int); 1715 #else 1716 fmissing("FLT_MAX_10_EXP"); 1717 #endif 1718 #ifdef DBL_MANT_DIG 1719 checktype(DBL_MANT_DIG, "DBL_MANT_DIG", Signed, int); 1720 #else 1721 fmissing("DBL_MANT_DIG"); 1722 #endif 1723 #ifdef DBL_DIG 1724 checktype(DBL_DIG, "DBL_DIG", Signed, int); 1725 #else 1726 fmissing("DBL_DIG"); 1727 #endif 1728 #ifdef DBL_EPSILON 1729 fchecktype(DBL_EPSILON, "DBL_EPSILON", double); 1730 #else 1731 fmissing("DBL_EPSILON"); 1732 #endif 1733 #ifdef DBL_MIN_EXP 1734 checktype(DBL_MIN_EXP, "DBL_MIN_EXP", Signed, int); 1735 #else 1736 fmissing("DBL_MIN_EXP"); 1737 #endif 1738 #ifdef DBL_MIN 1739 fchecktype(DBL_MIN, "DBL_MIN", double); 1740 #else 1741 fmissing("DBL_MIN"); 1742 #endif 1743 #ifdef DBL_MIN_10_EXP 1744 checktype(DBL_MIN_10_EXP, "DBL_MIN_10_EXP", Signed, int); 1745 #else 1746 fmissing("DBL_MIN_10_EXP"); 1747 #endif 1748 #ifdef DBL_MAX_EXP 1749 checktype(DBL_MAX_EXP, "DBL_MAX_EXP", Signed, int); 1750 #else 1751 fmissing("DBL_MAX_EXP"); 1752 #endif 1753 #ifdef DBL_MAX 1754 fchecktype(DBL_MAX, "DBL_MAX", double); 1755 #else 1756 fmissing("DBL_MAX"); 1757 #endif 1758 #ifdef DBL_MAX_10_EXP 1759 checktype(DBL_MAX_10_EXP, "DBL_MAX_10_EXP", Signed, int); 1760 #else 1761 fmissing("DBL_MAX_10_EXP"); 1762 #endif 1763 #ifdef STDC 1764 #ifdef LDBL_MANT_DIG 1765 checktype(LDBL_MANT_DIG, "LDBL_MANT_DIG", Signed, int); 1766 #else 1767 fmissing("LDBL_MANT_DIG"); 1768 #endif 1769 #ifdef LDBL_DIG 1770 checktype(LDBL_DIG, "LDBL_DIG", Signed, int); 1771 #else 1772 fmissing("LDBL_DIG"); 1773 #endif 1774 #ifdef LDBL_EPSILON 1775 fchecktype(LDBL_EPSILON, "LDBL_EPSILON", long double); 1776 #else 1777 fmissing("LDBL_EPSILON"); 1778 #endif 1779 #ifdef LDBL_MIN_EXP 1780 checktype(LDBL_MIN_EXP, "LDBL_MIN_EXP", Signed, int); 1781 #else 1782 fmissing("LDBL_MIN_EXP"); 1783 #endif 1784 #ifdef LDBL_MIN 1785 fchecktype(LDBL_MIN, "LDBL_MIN", long double); 1786 #else 1787 fmissing("LDBL_MIN"); 1788 #endif 1789 #ifdef LDBL_MIN_10_EXP 1790 checktype(LDBL_MIN_10_EXP, "LDBL_MIN_10_EXP", Signed, int); 1791 #else 1792 fmissing("LDBL_MIN_10_EXP"); 1793 #endif 1794 #ifdef LDBL_MAX_EXP 1795 checktype(LDBL_MAX_EXP, "LDBL_MAX_EXP", Signed, int); 1796 #else 1797 fmissing("LDBL_MAX_EXP"); 1798 #endif 1799 #ifdef LDBL_MAX 1800 fchecktype(LDBL_MAX, "LDBL_MAX", long double); 1801 #else 1802 fmissing("LDBL_MAX"); 1803 #endif 1804 #ifdef LDBL_MAX_10_EXP 1805 checktype(LDBL_MAX_10_EXP, "LDBL_MAX_10_EXP", Signed, int); 1806 #else 1807 fmissing("LDBL_MAX_10_EXP"); 1808 #endif 1809 #endif /* STDC */ 1810 } /* if (F) */ 1811 #endif /* VERIFY */ 1812 } 1813 1814 #ifdef VERIFY 1815 #ifndef SCHAR_MAX 1816 #define SCHAR_MAX char_max 1817 #endif 1818 #ifndef SCHAR_MIN 1819 #define SCHAR_MIN char_min 1820 #endif 1821 #ifndef UCHAR_MAX 1822 #define UCHAR_MAX char_max 1823 #endif 1824 #endif /* VERIFY */ 1825 1826 #ifndef CHAR_BIT 1827 #define CHAR_BIT char_bit 1828 #endif 1829 #ifndef CHAR_MAX 1830 #define CHAR_MAX char_max 1831 #endif 1832 #ifndef CHAR_MIN 1833 #define CHAR_MIN char_min 1834 #endif 1835 #ifndef SCHAR_MAX 1836 #define SCHAR_MAX char_max 1837 #endif 1838 #ifndef SCHAR_MIN 1839 #define SCHAR_MIN char_min 1840 #endif 1841 #ifndef UCHAR_MAX 1842 #define UCHAR_MAX char_max 1843 #endif 1844 1845 int cprop( void ) 1846 { 1847 /* Properties of type char */ 1848 Volatile char c, char_max, char_min; 1849 Volatile int byte_size, c_signed; 1850 long char_bit; 1851 1852 Unexpected(2); 1853 1854 /* Calculate number of bits per character *************************/ 1855 c=1; byte_size=0; 1856 do { c=c<<1; byte_size++; } while(c!=0); 1857 c= (char)(-1); 1858 if (((int)c)<0) c_signed=1; 1859 else c_signed=0; 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, ""); 1865 1866 c=0; char_max=0; 1867 c++; 1868 if (setjmp(lab)==0) { /* Yields char_max */ 1869 while (c>char_max) { 1870 char_max=c; 1871 c=(char)(c*2+1); 1872 } 1873 } else { 1874 Vprintf("%sCharacter overflow generates a trap!%s\n", co, oc); 1875 } 1876 c=0; char_min=0; 1877 c--; 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--; 1883 } 1884 } 1885 Unexpected(8); 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); 1891 } 1892 Unexpected(3); 1893 1894 if (L) { 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", 1899 (ulong) char_max, 1900 (ulong) CHAR_MAX, ""); 1901 } else { 1902 i_define(D_CHAR_MAX, "", "CHAR", "_MAX", 1903 (long) char_max, 0L, 1904 (long) CHAR_MAX, ""); 1905 } 1906 i_define(D_CHAR_MIN, "", "CHAR", "_MIN", 1907 (long) char_min, (long) maxint, 1908 (long) CHAR_MIN, ""); 1909 if (c_signed) { 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, ""); 1916 } else { 1917 if (sizeof(char) == sizeof(int)) { 1918 u_define(D_UCHAR_MAX, "", "UCHAR", "_MAX", 1919 (ulong) char_max, 1920 (ulong) UCHAR_MAX, ""); 1921 } else { 1922 i_define(D_UCHAR_MAX, "", "UCHAR", "_MAX", 1923 (long) char_max, 0L, 1924 (long) UCHAR_MAX, ""); 1925 } 1926 } 1927 1928 if (c_signed) { 1929 #ifndef NO_UC 1930 /* Syntax error? Define NO_UC */ Volatile unsigned char c1, char_max; 1931 c1=0; char_max=0; 1932 c1++; 1933 if (setjmp(lab)==0) { /* Yields char_max */ 1934 while (c1>char_max) { 1935 char_max=c1; 1936 c1++; 1937 } 1938 } 1939 Unexpected(4); 1940 if (sizeof(char) == sizeof(int)) { 1941 u_define(D_UCHAR_MAX, "", "UCHAR", "_MAX", 1942 (ulong) char_max, 1943 (ulong) UCHAR_MAX, ""); 1944 } else { 1945 i_define(D_UCHAR_MAX, "", "UCHAR", "_MAX", 1946 (long) char_max, 0L, 1947 (long) UCHAR_MAX, ""); 1948 } 1949 #endif 1950 } else { 1951 #ifndef NO_SC 1952 /* Syntax error? Define NO_SC */ Volatile signed char c1, char_max, char_min; 1953 c1=0; char_max=0; 1954 c1++; 1955 if (setjmp(lab)==0) { /* Yields char_max */ 1956 while (c1>char_max) { 1957 char_max=c1; 1958 c1++; 1959 } 1960 } 1961 c1=0; char_min=0; 1962 c1--; 1963 if (setjmp(lab)==0) { /* Yields char_min */ 1964 while (c1<char_min) { 1965 char_min=c1; 1966 c1--; 1967 } 1968 } 1969 Unexpected(5); 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, ""); 1976 #endif /* NO_SC */ 1977 } 1978 } 1979 return byte_size; 1980 } 1981 1982 int basic( void ) 1983 { 1984 /* The properties of the basic types. 1985 Returns number of bits per sizeof unit */ 1986 Volatile int byte_size; 1987 typedef int function (); 1988 int variable; 1989 char *cp; int *ip; function *fp; 1990 int *p, *q; 1991 1992 Vprintf("%sSIZES%s\n", co, oc); 1993 byte_size= cprop(); 1994 1995 /* Shorts, ints and longs *****************************************/ 1996 Vprintf("%sshort=%d int=%d long=%d float=%d double=%d bits %s\n", 1997 co, 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); 2003 if (stdc) { 2004 Vprintf("%slong double=%d bits%s\n", 2005 co, (int) sizeof(Long_double)*byte_size, oc); 2006 } 2007 Vprintf("%schar*=%d bits%s%s\n", 2008 co, (int)sizeof(char *)*byte_size, 2009 sizeof(char *)>sizeof(int)?" BEWARE! larger than int!":"", 2010 oc); 2011 Vprintf("%sint* =%d bits%s%s\n", 2012 co, (int)sizeof(int *)*byte_size, 2013 sizeof(int *)>sizeof(int)?" BEWARE! larger than int!":"", 2014 oc); 2015 Vprintf("%sfunc*=%d bits%s%s\n", 2016 co, (int)sizeof(function *)*byte_size, 2017 sizeof(function *)>sizeof(int)?" BEWARE! larger than int!":"", 2018 oc); 2019 2020 showtype("Type size_t is", sizeof(0)); 2021 #ifdef STDC 2022 showtype("Type wchar_t is", L'x'); 2023 #endif 2024 2025 /* Alignment constants ********************************************/ 2026 2027 #define alignment(TYPE) \ 2028 ((long)((char *)&((struct{char c; TYPE d;}*)0)->d - (char *)0)) 2029 2030 Vprintf("\n%sALIGNMENTS%s\n", co, oc); 2031 2032 Vprintf("%schar=%ld short=%ld int=%ld long=%ld%s\n", 2033 co, 2034 alignment(char), alignment(short), 2035 alignment(int), alignment(long), 2036 oc); 2037 2038 Vprintf("%sfloat=%ld double=%ld%s\n", 2039 co, 2040 alignment(float), alignment(double), 2041 oc); 2042 2043 if (stdc) { 2044 Vprintf("%slong double=%ld%s\n", 2045 co, 2046 alignment(Long_double), 2047 oc); 2048 } 2049 Vprintf("%schar*=%ld int*=%ld func*=%ld%s\n", 2050 co, 2051 alignment(char *), alignment(int *), alignment(function *), 2052 oc); 2053 2054 Vprintf("\n"); 2055 2056 /* Ten little endians *********************************************/ 2057 2058 endian(byte_size); 2059 2060 /* Pointers *******************************************************/ 2061 2062 Vprintf("\n%sPROPERTIES OF POINTERS%s\n", co, oc); 2063 cp= (char *) &variable; 2064 ip= (int *) &variable; 2065 fp= (function *) &variable; 2066 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); 2070 } else { 2071 Vprintf("are different%s\n", oc); 2072 } 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); 2076 } else { 2077 Vprintf("are different%s\n", oc); 2078 } 2079 2080 if (V) { 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); 2084 } 2085 2086 p=0; q=0; 2087 showtype("Type ptrdiff_t is", p-q); 2088 2089 //if (setjmp(mlab) == 0) { 2090 // variable= *p; 2091 // Vprintf("%sBEWARE! Dereferencing NULL doesn't cause a trap%s\n", 2092 // co, oc); 2093 //} else { 2094 // Vprintf("%sDereferencing NULL causes a trap%s\n", co, oc); 2095 //} 2096 if (setjmp(mlab)!=0) croak(-2); 2097 2098 Vprintf("\n%sPROPERTIES OF INTEGRAL TYPES%s\n", co, oc); 2099 2100 sprop(); 2101 iprop(); 2102 lprop(); 2103 usprop(); 2104 uiprop(); 2105 ulprop(); 2106 2107 promotions(); 2108 2109 Unexpected(6); 2110 2111 return byte_size; 2112 } 2113 2114 #else /* not PASS0 */ 2115 2116 #ifdef SEP 2117 /* The global variables used by several passes */ 2118 extern jmp_buf lab; 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(); 2125 #endif /* SEP */ 2126 #endif /* ifdef PASS0 */ 2127 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. 2135 */ 2136 2137 /* #undef on an already undefined thing is (wrongly) flagged as an error 2138 by some compilers, therefore the #ifdef that follows: 2139 */ 2140 #ifdef Number 2141 #undef Number 2142 #undef THING 2143 #undef Thing 2144 #undef thing 2145 #undef FPROP 2146 #undef Fname 2147 #undef Store 2148 #undef Sum 2149 #undef Diff 2150 #undef Mul 2151 #undef Div 2152 #undef ZERO 2153 #undef HALF 2154 #undef ONE 2155 #undef TWO 2156 #undef THREE 2157 #undef FOUR 2158 #undef Self 2159 #undef F_check 2160 #undef Verify 2161 #undef EPROP 2162 #undef MARK 2163 2164 /* These are the float.h constants */ 2165 #undef F_RADIX 2166 #undef F_MANT_DIG 2167 #undef F_DIG 2168 #undef F_ROUNDS 2169 #undef F_EPSILON 2170 #undef F_MIN_EXP 2171 #undef F_MIN 2172 #undef F_MIN_10_EXP 2173 #undef F_MAX_EXP 2174 #undef F_MAX 2175 #undef F_MAX_10_EXP 2176 #endif 2177 2178 #ifdef Integer 2179 #undef Integer 2180 #undef INT 2181 #undef IPROP 2182 #undef Iname 2183 #undef UPROP 2184 #undef Uname 2185 #undef OK_UI 2186 #undef IMARK 2187 2188 #undef I_MAX 2189 #undef I_MIN 2190 #undef U_MAX 2191 #endif 2192 2193 #ifdef PASS1 2194 2195 /* Define the things we're going to use this pass */ 2196 2197 #define Number float 2198 #define THING "FLOAT" 2199 #define Thing "Float" 2200 #define thing "float" 2201 #define Fname "FLT" 2202 #define FPROP fprop 2203 #define Store fStore 2204 #define Sum fSum 2205 #define Diff fDiff 2206 #define Mul fMul 2207 #define Div fDiv 2208 #define ZERO 0.0 2209 #define HALF 0.5 2210 #define ONE 1.0 2211 #define TWO 2.0 2212 #define THREE 3.0 2213 #define FOUR 4.0 2214 #define Self fSelf 2215 #define F_check fCheck 2216 #define MARK "F" 2217 #ifdef VERIFY 2218 #define Verify fVerify 2219 #endif 2220 2221 #define EPROP efprop 2222 2223 #define Integer short 2224 #define INT "short" 2225 #define IPROP sprop 2226 #define Iname "SHRT" 2227 #ifndef NO_UI 2228 #define OK_UI 1 2229 #endif 2230 #define IMARK "" 2231 2232 #define UPROP usprop 2233 #define Uname "USHRT" 2234 2235 #ifdef VERIFY 2236 #ifdef SHRT_MAX 2237 #define I_MAX SHRT_MAX 2238 #endif 2239 #ifdef SHRT_MIN 2240 #define I_MIN SHRT_MIN 2241 #endif 2242 #ifdef USHRT_MAX 2243 #define U_MAX USHRT_MAX 2244 #endif 2245 2246 #ifdef FLT_RADIX 2247 #define F_RADIX FLT_RADIX 2248 #endif 2249 #ifdef FLT_MANT_DIG 2250 #define F_MANT_DIG FLT_MANT_DIG 2251 #endif 2252 #ifdef FLT_DIG 2253 #define F_DIG FLT_DIG 2254 #endif 2255 #ifdef FLT_ROUNDS 2256 #define F_ROUNDS FLT_ROUNDS 2257 #endif 2258 #ifdef FLT_EPSILON 2259 #define F_EPSILON FLT_EPSILON 2260 #endif 2261 #ifdef FLT_MIN_EXP 2262 #define F_MIN_EXP FLT_MIN_EXP 2263 #endif 2264 #ifdef FLT_MIN 2265 #define F_MIN FLT_MIN 2266 #endif 2267 #ifdef FLT_MIN_10_EXP 2268 #define F_MIN_10_EXP FLT_MIN_10_EXP 2269 #endif 2270 #ifdef FLT_MAX_EXP 2271 #define F_MAX_EXP FLT_MAX_EXP 2272 #endif 2273 #ifdef FLT_MAX 2274 #define F_MAX FLT_MAX 2275 #endif 2276 #ifdef FLT_MAX_10_EXP 2277 #define F_MAX_10_EXP FLT_MAX_10_EXP 2278 #endif 2279 #endif /* VERIFY */ 2280 2281 #endif /* PASS1 */ 2282 2283 #ifdef PASS2 2284 2285 #define Number double 2286 #define THING "DOUBLE" 2287 #define Thing "Double" 2288 #define thing "double" 2289 #define Fname "DBL" 2290 #define FPROP dprop 2291 #define Store dStore 2292 #define Sum dSum 2293 #define Diff dDiff 2294 #define Mul dMul 2295 #define Div dDiv 2296 #define ZERO 0.0 2297 #define HALF 0.5 2298 #define ONE 1.0 2299 #define TWO 2.0 2300 #define THREE 3.0 2301 #define FOUR 4.0 2302 #define Self dSelf 2303 #define F_check dCheck 2304 #define MARK "" 2305 #ifdef VERIFY 2306 #define Verify dVerify 2307 #endif 2308 2309 #define EPROP edprop 2310 2311 #define Integer int 2312 #define INT "int" 2313 #define IPROP iprop 2314 #define Iname "INT" 2315 #define OK_UI 1 /* Unsigned int is always possible */ 2316 #define IMARK "" 2317 2318 #define UPROP uiprop 2319 #define Uname "UINT" 2320 2321 #ifdef VERIFY 2322 #ifdef INT_MAX 2323 #define I_MAX INT_MAX 2324 #endif 2325 #ifdef INT_MIN 2326 #define I_MIN INT_MIN 2327 #endif 2328 #ifdef UINT_MAX 2329 #define U_MAX UINT_MAX 2330 #endif 2331 2332 #ifdef DBL_MANT_DIG 2333 #define F_MANT_DIG DBL_MANT_DIG 2334 #endif 2335 #ifdef DBL_DIG 2336 #define F_DIG DBL_DIG 2337 #endif 2338 #ifdef DBL_EPSILON 2339 #define F_EPSILON DBL_EPSILON 2340 #endif 2341 #ifdef DBL_MIN_EXP 2342 #define F_MIN_EXP DBL_MIN_EXP 2343 #endif 2344 #ifdef DBL_MIN 2345 #define F_MIN DBL_MIN 2346 #endif 2347 #ifdef DBL_MIN_10_EXP 2348 #define F_MIN_10_EXP DBL_MIN_10_EXP 2349 #endif 2350 #ifdef DBL_MAX_EXP 2351 #define F_MAX_EXP DBL_MAX_EXP 2352 #endif 2353 #ifdef DBL_MAX 2354 #define F_MAX DBL_MAX 2355 #endif 2356 #ifdef DBL_MAX_10_EXP 2357 #define F_MAX_10_EXP DBL_MAX_10_EXP 2358 #endif 2359 #endif /* VERIFY */ 2360 2361 #endif /* PASS2 */ 2362 2363 #ifdef PASS3 2364 2365 #ifdef STDC 2366 #define Number long double 2367 2368 #define ZERO 0.0L 2369 #define HALF 0.5L 2370 #define ONE 1.0L 2371 #define TWO 2.0L 2372 #define THREE 3.0L 2373 #define FOUR 4.0L 2374 #endif 2375 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 2382 #define Sum ldSum 2383 #define Diff ldDiff 2384 #define Mul ldMul 2385 #define Div ldDiv 2386 #define Self ldSelf 2387 #define F_check ldCheck 2388 #define MARK "L" 2389 #ifdef VERIFY 2390 #define Verify ldVerify 2391 #endif 2392 2393 #define EPROP eldprop 2394 2395 #define Integer long 2396 #define INT "long" 2397 #define IPROP lprop 2398 #define Iname "LONG" 2399 #ifndef NO_UI 2400 #define OK_UI 1 2401 #endif 2402 #define IMARK "L" 2403 2404 #define UPROP ulprop 2405 #define Uname "ULONG" 2406 2407 #ifdef VERIFY 2408 #ifdef LONG_MAX 2409 #define I_MAX LONG_MAX 2410 #endif 2411 #ifdef LONG_MIN 2412 #define I_MIN LONG_MIN 2413 #endif 2414 #ifdef ULONG_MAX 2415 #define U_MAX ULONG_MAX 2416 #endif 2417 2418 #ifdef LDBL_MANT_DIG 2419 #define F_MANT_DIG LDBL_MANT_DIG 2420 #endif 2421 #ifdef LDBL_DIG 2422 #define F_DIG LDBL_DIG 2423 #endif 2424 #ifdef LDBL_EPSILON 2425 #define F_EPSILON LDBL_EPSILON 2426 #endif 2427 #ifdef LDBL_MIN_EXP 2428 #define F_MIN_EXP LDBL_MIN_EXP 2429 #endif 2430 #ifdef LDBL_MIN 2431 #define F_MIN LDBL_MIN 2432 #endif 2433 #ifdef LDBL_MIN_10_EXP 2434 #define F_MIN_10_EXP LDBL_MIN_10_EXP 2435 #endif 2436 #ifdef LDBL_MAX_EXP 2437 #define F_MAX_EXP LDBL_MAX_EXP 2438 #endif 2439 #ifdef LDBL_MAX 2440 #define F_MAX LDBL_MAX 2441 #endif 2442 #ifdef LDBL_MAX_10_EXP 2443 #define F_MAX_10_EXP LDBL_MAX_10_EXP 2444 #endif 2445 #endif /* VERIFY */ 2446 2447 #endif /* PASS3 */ 2448 2449 /* The rest of the file gets read all three times; 2450 the differences are encoded in the things #defined above. 2451 */ 2452 2453 #ifndef I_MAX 2454 #define I_MAX int_max 2455 #endif 2456 #ifndef I_MIN 2457 #define I_MIN int_min 2458 #endif 2459 #ifndef U_MAX 2460 #define U_MAX u_max 2461 #endif 2462 2463 #ifndef F_RADIX 2464 #define F_RADIX f_radix 2465 #endif 2466 #ifndef F_MANT_DIG 2467 #define F_MANT_DIG f_mant_dig 2468 #endif 2469 #ifndef F_DIG 2470 #define F_DIG f_dig 2471 #endif 2472 #ifndef F_ROUNDS 2473 #define F_ROUNDS f_rounds 2474 #endif 2475 #ifndef F_EPSILON 2476 #define F_EPSILON f_epsilon 2477 #endif 2478 #ifndef F_MIN_EXP 2479 #define F_MIN_EXP f_min_exp 2480 #endif 2481 #ifndef F_MIN 2482 #define F_MIN f_min 2483 #endif 2484 #ifndef F_MIN_10_EXP 2485 #define F_MIN_10_EXP f_min_10_exp 2486 #endif 2487 #ifndef F_MAX_EXP 2488 #define F_MAX_EXP f_max_exp 2489 #endif 2490 #ifndef F_MAX 2491 #define F_MAX f_max 2492 #endif 2493 #ifndef F_MAX_10_EXP 2494 #define F_MAX_10_EXP f_max_10_exp 2495 #endif 2496 2497 #ifndef VERIFY 2498 #define Verify(prec, val, req, same, same1) {;} 2499 #endif 2500 2501 #ifdef Integer 2502 2503 Void IPROP( void ) 2504 { 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; 2508 2509 /* Calculate max short/int/long ***********************************/ 2510 /* Calculate 2**n-1 until overflow - then use the previous value */ 2511 2512 newi=1; int_max=0; 2513 2514 if (setjmp(lab)==0) { /* Yields int_max */ 2515 for(ipower=0; newi>int_max; ipower++) { 2516 int_max=newi; 2517 newi=newi*two+1; 2518 } 2519 Vprintf("%sOverflow of a%s %s does not generate a trap%s\n", 2520 co, INT[0]=='i'?"n":"", INT, oc); 2521 } else { 2522 Vprintf("%sOverflow of a%s %s generates a trap%s\n", 2523 co, INT[0]=='i'?"n":"", INT, oc); 2524 } 2525 Unexpected(7); 2526 2527 /* Minimum value: assume either two's or one's complement *********/ 2528 int_min= -int_max; 2529 if (setjmp(lab)==0) { /* Yields int_min */ 2530 if (int_min-1 < int_min) int_min--; 2531 } 2532 Unexpected(8); 2533 2534 /* Now for those daft Cybers */ 2535 2536 maxeri=0; newi=int_max; 2537 2538 if (setjmp(lab)==0) { /* Yields maxeri */ 2539 for(ibits=ipower; newi>maxeri; ibits++) { 2540 maxeri=newi; 2541 newi=newi+newi+1; 2542 } 2543 } 2544 Unexpected(9); 2545 2546 minneri= -maxeri; 2547 if (setjmp(lab)==0) { /* Yields minneri */ 2548 if (minneri-1 < minneri) minneri--; 2549 } 2550 Unexpected(10); 2551 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); 2555 2556 if (L) i_define(D_INT_MAX, INT, Iname, "_MAX", 2557 (long) int_max, 0L, 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); 2562 2563 if(int_max < 0) { /* It has happened (on a Cray) */ 2564 eek_a_bug("signed integral comparison faulty?"); 2565 } 2566 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!)", 2572 oc); 2573 } 2574 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!)", 2580 oc); 2581 } 2582 } 2583 2584 Void UPROP ( void ) 2585 { 2586 /* The properties of unsigned short/int/long */ 2587 #ifdef OK_UI 2588 Volatile unsigned Integer u_max, newi, two; 2589 newi=1; u_max=0; two=2; 2590 2591 if (setjmp(lab)==0) { /* Yields u_max */ 2592 while(newi>u_max) { 2593 u_max=newi; 2594 newi=newi*two+1; 2595 } 2596 } 2597 Unexpected(11); 2598 Vprintf("%sMaximum unsigned %s = %lu%s\n", 2599 co, INT, (unsigned long) u_max, oc); 2600 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." 2605 */ 2606 if (L) { 2607 if (PASS == 1 /* we're dealing with short */ 2608 && u_max <= maxint /* an int can represent all values */ 2609 ) 2610 { /* the value is converted to an int */ 2611 i_define(D_UINT_MAX, INT, Uname, "_MAX", 2612 (long) u_max, 0L, 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); 2618 } 2619 } 2620 #endif 2621 } 2622 2623 #endif /* Integer */ 2624 2625 #ifdef Number 2626 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. 2630 */ 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) 2635 #else 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; 2639 #endif 2640 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; } 2647 2648 Void F_check ARGS((int precision, Long_double val1)); 2649 2650 Void F_check(int precision, Long_double val1) 2651 { 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. 2663 */ 2664 Long_double new1, rem; 2665 Number val, new, diff; 2666 int e; 2667 char *rep, *f2; 2668 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 */ 2673 } else { 2674 /* It had better support Le then */ 2675 f2= "%Le"; 2676 } 2677 val= (Number) val1; 2678 rep= f_rep(precision, (Long_double) val); 2679 if (setjmp(lab)==0) { 2680 sscanf(rep, f2, &new1); 2681 } else { 2682 eek_a_bug("sscanf caused a trap"); 2683 printf("%s scanning: %s format: %s%s\n\n", co, rep, f2, oc); 2684 Unexpected(12); 2685 return; 2686 } 2687 2688 if (setjmp(lab)==0) { /* See if new is usable */ 2689 new= new1; 2690 if (new != 0.0) { 2691 diff= val/new - 1.0; 2692 if (diff < 0.1) diff= 1.0; 2693 /* That should be enough to generate a trap */ 2694 } 2695 } else { 2696 eek_a_bug("sscanf returned an unusable number"); 2697 printf("%s scanning: %s with format: %s%s\n\n", 2698 co, rep, f2, oc); 2699 Unexpected(13); 2700 return; 2701 } 2702 2703 Unexpected(14); 2704 if (new != val) { 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", 2708 co, oc); 2709 return; 2710 } 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); 2716 //} else { 2717 /* It had better support Lfe then */ 2718 printf("%.*Lfe%d, bit pattern:\n ", precision, rem, e); 2719 //} 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) { 2727 diff= val-new; 2728 printf("%s difference= %s%s\n\n", 2729 co, f_rep(precision, (Long_double) diff), oc); 2730 } /* else forget it */ 2731 Unexpected(15); 2732 } 2733 } 2734 2735 #ifdef VERIFY 2736 Void Verify ARGS5(int, prec, Number, val, Number, req, int, same, int, same1) 2737 { 2738 /* Check that the compiler has read a #define value correctly */ 2739 Unexpected(16); 2740 if (!same) { 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", 2744 f_rep(prec, req)); 2745 } else { 2746 printf(" Compiler has %s for value\n", 2747 "an unusable number"); 2748 } 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)); 2756 } 2757 } /*else forget it*/ 2758 Unexpected(17); 2759 printf("%s\n", oc); 2760 bugs++; 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"); 2764 printf("\n"); 2765 } 2766 } 2767 #endif /* VERIFY */ 2768 2769 int FPROP(int byte_size) 2770 { 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. 2774 2775 Returns the number of digits in the fraction. 2776 */ 2777 2778 Volatile int 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; 2783 Volatile Number 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; 2787 2788 Unexpected(18); 2789 2790 Vprintf("%sPROPERTIES OF %s%s\n", co, THING, oc); 2791 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. */ 2797 a=1.0; 2798 if (setjmp(lab)==0) { /* inexact trap? */ 2799 do { a=Sum(a, a); } 2800 while (Diff(Diff(Sum(a, ONE), a), ONE) == ZERO); 2801 } else { 2802 fprintf(stderr, "*** Program got loss-of-precision trap!\n"); 2803 /* And supporting those is just TOO much trouble! */ 2804 farewell(bugs+1); 2805 } 2806 Unexpected(19); 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. */ 2811 b=1.0; 2812 do { b=Sum(b, b); } while ((base=Diff(Sum(a, b), a)) == ZERO); 2813 f_radix=base; 2814 Vprintf("%sBase = %d%s\n", co, f_radix, oc); 2815 2816 /* Sanity check; if base<2, I can't guarantee the rest will work */ 2817 if (f_radix < 2) { 2818 eek_a_bug("Function return or parameter passing faulty? (This is a guess.)"); 2819 printf("\n"); 2820 return(0); 2821 } 2822 2823 if (PASS == 1) { /* only for FLT */ 2824 flt_radix= f_radix; 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); 2831 bugs++; 2832 } 2833 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 */ 2846 2847 /* Rounding *******************************************************/ 2848 basem1=Diff(base, HALF); 2849 if (Diff(Sum(a, basem1), a) != ZERO) { 2850 if (f_radix == 2) basem1=0.375; 2851 else basem1=1.0; 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 */ 2855 2856 basem1=Diff(base, HALF); 2857 2858 if (Diff(Diff(-a, basem1), -a) != ZERO) { 2859 if (f_radix == 2) basem1=0.375; 2860 else basem1=1.0; 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 */ 2864 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 */ 2870 2871 if (f_rounds != -1) { 2872 Vprintf("%sArithmetic rounds towards ", co); 2873 switch (f_rounds) { 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; 2879 } 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" : 2886 "away from zero", 2887 oc); 2888 Vprintf("%s Positive numbers %s%s\n", 2889 co, irnd==0 ? "towards zero" : 2890 irnd==1 ? "to nearest" : 2891 "away from zero", 2892 oc); 2893 } 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); 2900 } else { 2901 Vprintf("%s Tie breaking rounds down%s\n", co, oc); 2902 } 2903 } 2904 if (PASS == 1) { /* only for FLT */ 2905 flt_rounds= f_rounds; 2906 if (F) 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); 2913 bugs++; 2914 } 2915 2916 /* Various flavours of epsilon ************************************/ 2917 negeps=f_mant_dig+f_mant_dig; 2918 basein=1.0/base; 2919 a=1.0; 2920 for(i=1; i<=negeps; i++) a*=basein; 2921 2922 b=a; 2923 while (Diff(Diff(ONE, a), ONE) == ZERO) { 2924 a*=base; 2925 negeps--; 2926 } 2927 negeps= -negeps; 2928 Vprintf("%sSmallest x such that 1.0-base**x != 1.0 = %d%s\n", 2929 co, negeps, oc); 2930 2931 etop = ONE; 2932 ebot = ZERO; 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; 2939 else ebot = eps; 2940 eps = Sum(ebot, Div(Diff(etop, ebot), TWO)); 2941 } 2942 eps= etop; 2943 /* Sanity check */ 2944 if (Diff(ONE, etop) >= ONE || Diff(ONE, ebot) != ONE) { 2945 eek_a_bug("internal error calculating epsneg"); 2946 } 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); 2950 2951 epsneg=a; 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; 2957 } 2958 /* epsneg is used later */ 2959 Unexpected(20); 2960 2961 machep= -f_mant_dig-f_mant_dig; 2962 a=b; 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", 2965 co, machep, oc); 2966 2967 etop = ONE; 2968 ebot = ZERO; 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; 2975 else ebot = eps; 2976 eps = Sum(ebot, Div(Diff(etop, ebot), TWO)); 2977 } 2978 /* Sanity check */ 2979 if (Sum(ONE, etop) <= ONE || Sum(ONE, ebot) != ONE) { 2980 eek_a_bug("internal error calculating eps"); 2981 } 2982 f_epsilon=etop; 2983 2984 Vprintf("%sSmallest x such that 1.0+x != 1.0 = %s%s\n", 2985 co, f_rep(digs, (Long_double) f_epsilon), oc); 2986 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); 2990 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); 2995 Unexpected(21); 2996 if (F) Verify(digs, f_epsilon, F_EPSILON, 2997 f_epsilon == Self(F_EPSILON), 2998 (Long_double) f_epsilon == (Long_double) F_EPSILON); 2999 Unexpected(22); 3000 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); 3005 } 3006 } 3007 3008 /* Size of and minimum normalised exponent ************************/ 3009 y=0; i=0; k=1; z=basein; z1=(1.0+f_epsilon)/base; 3010 3011 /* Coarse search for the largest power of two */ 3012 if (setjmp(lab)==0) { /* for underflow trap */ /* Yields i, k, y, y1 */ 3013 do { 3014 y=z; y1=z1; 3015 z=Mul(y,y); z1=Mul(z1, y); 3016 a=Mul(z,ONE); 3017 z2=Div(z1,y); 3018 if (z2 != y1) break; 3019 if ((Sum(a,a) == ZERO) || (fabs(z) >= y)) break; 3020 i++; 3021 k+=k; 3022 } while(1); 3023 } else { 3024 Vprintf("%s%s underflow generates a trap%s\n", co, Thing, oc); 3025 } 3026 Unexpected(23); 3027 3028 if (f_radix != 10) { 3029 iexp=i+1; /* for the sign */ 3030 mx=k+k; 3031 } else { 3032 iexp=2; 3033 iz=f_radix; 3034 while (k >= iz) { iz*=f_radix; iexp++; } 3035 mx=iz+iz-1; 3036 } 3037 3038 /* Fine tune starting with y and y1 */ 3039 if (setjmp(lab)==0) { /* for underflow trap */ /* Yields k, f_min */ 3040 do { 3041 f_min=y; z1=y1; 3042 y=Div(y,base); y1=Div(y1,base); 3043 a=Mul(y,ONE); 3044 z2=Mul(y1,base); 3045 if (z2 != z1) break; 3046 if ((Sum(a,a) == ZERO) || (fabs(y) >= f_min)) break; 3047 k++; 3048 } while (1); 3049 } 3050 Unexpected(24); 3051 3052 f_min_exp=(-k)+1; 3053 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); 3057 if (F) 3058 i_define(D_MIN_EXP, thing, Fname, "_MIN_EXP", 3059 (long) f_min_exp, (long) maxint, (long) F_MIN_EXP, ""); 3060 3061 if (setjmp(lab)==0) { 3062 Vprintf("%sMinimum normalised positive number = %s%s\n", 3063 co, f_rep(digs, (Long_double) f_min), oc); 3064 } else { 3065 eek_a_bug("printf can't print the smallest normalised number"); 3066 printf("\n"); 3067 } 3068 Unexpected(25); 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); 3074 } else { 3075 eek_a_bug("xxx_MIN caused a trap"); 3076 printf("\n"); 3077 } 3078 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); 3083 } else { 3084 printf("%s*** Verify failed for above #define!\n %s %s\n\n", 3085 co, "Compiler has an unusable number for value", oc); 3086 bugs++; 3087 } 3088 Unexpected(26); 3089 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, ""); 3095 3096 /* Minimum exponent ************************************************/ 3097 if (setjmp(lab)==0) { /* for underflow trap */ /* Yields xminner */ 3098 do { 3099 xminner=y; 3100 y=Div(y,base); 3101 a=Mul(y,ONE); 3102 if ((Sum(a,a) == ZERO) || (fabs(y) >= xminner)) break; 3103 } while (1); 3104 } 3105 Unexpected(27); 3106 3107 if (xminner != 0.0 && xminner != f_min) { 3108 normal= 0; 3109 Vprintf("%sThe smallest numbers are not kept normalised%s\n", 3110 co, oc); 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); 3115 } else { 3116 eek_a_bug("printf can't print the smallest unnormalised number."); 3117 printf("\n"); 3118 } 3119 Unexpected(28); 3120 } else { 3121 normal= 1; 3122 Vprintf("%sThe smallest numbers are normalised%s\n", co, oc); 3123 } 3124 3125 /* Maximum exponent ************************************************/ 3126 f_max_exp=2; f_max=1.0; newxmax=base+1.0; 3127 inf=0; trap=0; 3128 while (f_max<newxmax) { 3129 f_max=newxmax; 3130 if (setjmp(lab) == 0) { /* Yields inf, f_max_exp */ 3131 newxmax=Mul(newxmax, base); 3132 } else { 3133 trap=1; 3134 break; 3135 } 3136 if (Div(newxmax, base) != f_max) { 3137 if (newxmax > f_max) inf=1; /* ieee infinity */ 3138 break; 3139 } 3140 f_max_exp++; 3141 } 3142 Unexpected(29); 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, ""); 3146 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); 3151 3152 if (setjmp(lab)==0) { 3153 Vprintf("%sMaximum number = %s%s\n", 3154 co, f_rep(digs, (Long_double) f_max), oc); 3155 } else { 3156 eek_a_bug("printf can't print the largest double."); 3157 printf("\n"); 3158 } 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); 3164 } else { 3165 eek_a_bug("xxx_MAX caused a trap"); 3166 printf("\n"); 3167 } 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); 3172 } else { 3173 printf("%s*** Verify failed for above #define!\n %s %s\n\n", 3174 co, "Compiler has an unusable number for value", oc); 3175 bugs++; 3176 } 3177 Unexpected(30); 3178 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, ""); 3183 3184 /* Traps and infinities ********************************************/ 3185 if (trap) { 3186 Vprintf("%sOverflow generates a trap%s\n", co, oc); 3187 } else { 3188 Vprintf("%sOverflow doesn't seem to generate a trap%s\n", 3189 co, oc); 3190 } 3191 3192 if (inf) { Vprintf("%sThere is an 'infinite' value%s\n", co, oc); } 3193 3194 #ifdef SIGFPE 3195 signal(SIGFPE, trap1); 3196 #endif 3197 if (setjmp(lab) == 0) { 3198 trapped= 0; /* A global variable */ 3199 b= 0.0; 3200 a= (1.0/b)/b; 3201 if (!trapped) { 3202 Vprintf("%sDivide by zero doesn't generate a trap%s\n", 3203 co, oc); 3204 } else { 3205 Vprintf("%sDivide by zero generates a trap%s\n", 3206 co, oc); 3207 Vprintf("%sFP signal handlers return safely%s\n", 3208 co, oc); 3209 } 3210 } else { 3211 Vprintf("%sDivide by zero generates a trap%s\n", co, oc); 3212 Vprintf("%sBEWARE! FP signal handlers can NOT return%s\n", 3213 co, oc); 3214 } 3215 setsignals(); 3216 Unexpected(31); 3217 3218 /* Hidden bit + sanity check ****************************************/ 3219 if (f_radix != 10) { 3220 hidden=0; 3221 mantbits=floor_log(2, (Long_double)f_radix)*f_mant_dig; 3222 if (mantbits+iexp == (int)sizeof(Number)*byte_size) { 3223 hidden=1; 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", 3227 co, oc); 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", 3230 co, 3231 mantbits+iexp, 3232 (int)sizeof(Number)*byte_size, 3233 thing, 3234 "are actually used", 3235 oc); 3236 } else { 3237 printf("\n%s%s\n %s (%d) %s (%d) %s %s (%d)!%s\n\n", 3238 co, 3239 "*** Something fishy here!", 3240 "Exponent size", 3241 iexp, 3242 "+ significand size", 3243 mantbits, 3244 "doesn't match with the size of a", 3245 thing, 3246 (int)sizeof(Number)*byte_size, 3247 oc); 3248 } 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" : 3254 "some", oc); 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 "); } 3260 } 3261 if (normal) { 3262 Vprintf("the normalisation is unusual"); 3263 } 3264 Vprintf("%s\n", oc); 3265 } 3266 } else { 3267 Vprintf("%sIt doesn't look like IEEE format%s\n", 3268 co, oc); 3269 } 3270 } 3271 printf("\n"); /* regardless of verbosity */ 3272 return f_mant_dig; 3273 } 3274 3275 Void EPROP(int fprec, int dprec, int lprec) 3276 { 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. 3281 */ 3282 Volatile int eprec; 3283 Volatile double a, b, base, old; 3284 Volatile Number d, oldd, dbase, one, zero; 3285 Volatile int bad=0; 3286 3287 /* Size of significand **************************************/ 3288 a=1.0; 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); 3292 } else bad=1; 3293 if (!bad && a <= old) bad=1; 3294 3295 if (!bad) { 3296 b=1.0; 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; 3301 } else bad=1; 3302 } 3303 3304 if (!bad) { 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; 3310 } else bad=1; 3311 } 3312 3313 Unexpected(32); 3314 3315 if (bad) { 3316 Vprintf("%sCan't determine precision for %s expressions:\n%s%s\n", 3317 co, thing, " check that you compiled without optimisation!", 3318 oc); 3319 } else if (eprec==dprec) { 3320 Vprintf("%s%s expressions are evaluated in double precision%s\n", 3321 co, Thing, oc); 3322 } else if (eprec==fprec) { 3323 Vprintf("%s%s expressions are evaluated in float precision%s\n", 3324 co, Thing, oc); 3325 } else if (eprec==lprec) { 3326 Vprintf("%s%s expressions are evaluated in long double precision%s\n", 3327 co, Thing, oc); 3328 } else { 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", 3333 oc); 3334 } 3335 } 3336 3337 #else /* not Number */ 3338 3339 #ifdef FPROP /* Then create dummy routines for long double */ 3340 /* ARGSUSED */ 3341 int FPROP(int byte_size) { return 0; } 3342 #endif 3343 #ifdef EPROP 3344 /* ARGSUSED */ 3345 Void EPROP(int fprec, int dprec, int lprec) {} 3346 #endif 3347 3348 #endif /* ifdef Number */ 3349 3350 /* Increment the pass number */ 3351 #undef PASS 3352 3353 #ifdef PASS2 3354 #undef PASS2 3355 #define PASS 3 3356 #define PASS3 1 3357 #endif 3358 3359 #ifdef PASS1 3360 #undef PASS1 3361 #define PASS 2 3362 #define PASS2 1 3363 #endif 3364 3365 #ifdef PASS0 3366 #undef PASS0 3367 #endif 3368 3369 #ifndef SEP 3370 #ifdef PASS /* then rescan this file */ 3371 #ifdef BAD_CPP 3372 #include "enquire.c" 3373 #else 3374 #include FILENAME /* if this line fails to compile, define BAD_CPP */ 3375 #endif 3376 #endif /* PASS */ 3377 #endif /* SEP */ 3378