Home | History | Annotate | Download | only in Enquire
      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 (at) 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 (at) 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 (at) 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 (at) TechFak.Uni-Bielefeld.DE
    497   Added a free(): thanks nickc (at) 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 (at) 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