Annotation of researchv10no/cmd/lcc/etc/config.c, revision 1.1

1.1     ! root        1: /* Everything you wanted to know about your machine and C compiler,
        !             2:    but didn't know who to ask. */
        !             3: 
        !             4: #ifndef VERSION
        !             5: #define VERSION "4.2"
        !             6: #endif
        !             7: 
        !             8: /* Author: Steven Pemberton, CWI, Amsterdam; [email protected]
        !             9:    Bugfixes and upgrades gratefully received.
        !            10: 
        !            11:    Copyright (c) 1988, 1989, 1990 Steven Pemberton, CWI, Amsterdam.
        !            12:    All rights reserved.
        !            13: 
        !            14:    COMPILING
        !            15:    With luck and a following wind, just the following will work:
        !            16:        cc config.c -o config
        !            17:    You may get some messages about unreachable code. This is OK.
        !            18: 
        !            19:    If your compiler doesn't support:           add flag:
        !            20:        signed char (eg pcc)                    -DNO_SC
        !            21:        unsigned char                           -DNO_UC
        !            22:        unsigned short and long                 -DNO_UI
        !            23:        void                                    -DNO_VOID
        !            24:        signal(), or setjmp/longjmp()           -DNO_SIG
        !            25: 
        !            26:    Try to compile first with no flags, and see if you get any errors - 
        !            27:    you might be surprised. (Most non-ANSI compilers need -DNO_SC, though.)
        !            28:    Some compilers need a -f flag for floating point.
        !            29: 
        !            30:    If your C preprocessor doesn't have the predefined __FILE__ macro, and
        !            31:    you don't want to call this file config.c but, say, params.c, add the
        !            32:    flag -D__FILE__=\"params.c\" .
        !            33: 
        !            34:    Some naughty compilers define __STDC__, but don't really support it
        !            35:    (typically they define __STDC__ as 0). If this is the case for you,
        !            36:    add flag -DNO_STDC. (To those compiler writers: for shame).
        !            37: 
        !            38:    Some bad compilers won't accept the line "#include __FILE__" or
        !            39:    "#ifdef __FILE__". Add flag -DNO_FILE. In that case, this file *must*
        !            40:    be called config.c.
        !            41: 
        !            42:    Don't use any optimisation flags: the program may not work if you do.
        !            43:    Though "while (a+1.0-a-1.0 == 0.0)" may look like "while(1)" to an
        !            44:    optimiser, to a floating-point unit there's a world of difference.
        !            45: 
        !            46:    Some compilers offer various flags for different floating point
        !            47:    modes; it's worth trying all possible combinations of these.
        !            48: 
        !            49:    Add -DID=\"name\" if you want the machine/flags identified in the output.
        !            50: 
        !            51:    While it is not our policy to support defective compilers, pity has been
        !            52:    taken on people with compilers that can't produce object files bigger than
        !            53:    32k (especially since it was an easy addition). Compile the program
        !            54:    into separate parts like this:
        !            55:        cc -DSEP -DPASS0 -o p0.o <other flags> config.c
        !            56:        cc -DSEP -DPASS1 -o p1.o <other flags> config.c
        !            57:        cc -DSEP -DPASS2 -o p2.o <other flags> config.c
        !            58:        cc -DSEP -DPASS3 -o p3.o <other flags> config.c
        !            59:        cc -o config p0.o p1.o p2.o p3.o
        !            60: 
        !            61:    SYSTEM DEPENDENCIES
        !            62:    You may possibly need to add some calls to signal() for other sorts of
        !            63:    exception on your machine than SIGFPE, and SIGOVER.  See lines beginning
        !            64:    #ifdef SIGxxx in main() (and communicate the differences to me!).
        !            65: 
        !            66:    OUTPUT
        !            67:    Run without argument to get the information as English text.  If run
        !            68:    with argument -l (e.g. config -l), output is a series of #define's for
        !            69:    the ANSI standard limits.h include file, excluding MB_MAX_CHAR.  If run
        !            70:    with argument -f, output is a series of #define's for the ANSI standard
        !            71:    float.h include file (according to ANSI C Draft of May 13, 1988).
        !            72:    Flag -v gives verbose output: output includes the English text above
        !            73:    as C comments.  The program exit(0)'s if everything went ok, otherwise
        !            74:    it exits with a positive number, telling how many problems there were.
        !            75: 
        !            76:    VERIFYING THE COMPILER
        !            77:    If, having produced the float.h and limits.h header files, you want to
        !            78:    verify that the compiler reads them back correctly (there are a lot of
        !            79:    boundary cases, of course, like minimum and maximum numbers), you can
        !            80:    recompile config.c with -DVERIFY set (plus the other flags that you used
        !            81:    when compiling the version that produced the header files).  This then
        !            82:    recompiles the program so that it #includes "limits.h" and "float.h",
        !            83:    and checks that the constants it finds there are the same as the
        !            84:    constants it produces. Run the resulting program with config -fl.
        !            85:    Very few compilers have passed without error.
        !            86: 
        !            87:    You can also use this option if your compiler already has both files,
        !            88:    and you want to confirm that this program produces the right results.
        !            89: 
        !            90:    TROUBLESHOOTING.
        !            91:    This program is now quite trustworthy, and suspicious and wrong output
        !            92:    may well be caused by bugs in the compiler, not in the program (however
        !            93:    of course, this is not guaranteed, and no responsibility can be
        !            94:    accepted, etc.)
        !            95: 
        !            96:    The program only works if overflows are ignored by the C system or
        !            97:    are catchable with signal().
        !            98: 
        !            99:    If the program fails to run to completion (often with the error message
        !           100:    "Unexpected signal at point x"), this often turns out to be a bug in the
        !           101:    C compiler's run-time system. Check what was about to be printed, and
        !           102:    try to narrow the problem down.
        !           103: 
        !           104:    Another possible problem is that you have compiled the program to produce
        !           105:    loss-of-precision arithmetic traps. The program cannot cope with these,
        !           106:    and you should re-compile without them. (They should never be the default).
        !           107: 
        !           108:    Make sure you compiled with optimisation turned off.
        !           109: 
        !           110:    Output preceded by *** WARNING: identifies behaviour of the C system
        !           111:    deemed incorrect by the program. Likely problems are that printf or
        !           112:    scanf don't cope properly with certain boundary numbers: this program
        !           113:    goes to a lot of trouble to calculate its values, and these values
        !           114:    are mostly boundary numbers.  Experience has shown that often printf
        !           115:    cannot cope with these values, and so in an attempt to increase
        !           116:    confidence in the output, for each float and double that is printed,
        !           117:    the printed value is checked by using sscanf to read it back.
        !           118:    Care is taken that numbers are printed with enough digits to uniquely
        !           119:    identify them, and therefore that they can be read back identically.
        !           120:    If the number read back is different, then there is probably a bug in
        !           121:    printf or sscanf, and the program prints the warning message.
        !           122:    If the two numbers in the warning look identical, then printf is more
        !           123:    than likely rounding the last digit(s) incorrectly. To put you at ease
        !           124:    that the two really are different, the bit patterns of the two numbers
        !           125:    are also printed.  The difference is very likely in the last bit.
        !           126:    Many scanf's read the minimum double back as 0.0, and similarly cause
        !           127:    overflow when reading the maximum double.  The program quite ruthlessly
        !           128:    declares all these behaviours faulty. The point is that if you get
        !           129:    one of these warnings, the output may be wrong, so you should check
        !           130:    the result carefully if you intend to use the results. Of course, printf
        !           131:    and sscanf may both be wrong, and cancel each other out, so you should
        !           132:    check the output carefully anyway.
        !           133: 
        !           134:    The warning that "a cast didn't work" refers to cases like this:
        !           135: 
        !           136:       float f;
        !           137:       #define C 1.234567890123456789
        !           138:       f= C;
        !           139:       if (f != (float) C) printf ("Wrong!");
        !           140: 
        !           141:    A faulty compiler will widen f to double and ignore the cast to float,
        !           142:    and because there is more accuracy in a double than a float, fail to
        !           143:    recognise that they are the same. In the actual case in point, f and C
        !           144:    are passed as parameters to a function that discovers they are not equal,
        !           145:    so it's just possible that the error was in the parameter passing,
        !           146:    not in the cast (see function Validate()).
        !           147:    For ANSI C, which has float constants, the error message is "constant has
        !           148:    wrong precision".
        !           149: 
        !           150:    REPORTING PROBLEMS
        !           151:    If the program doesn't work for you for any reason that can't be
        !           152:    narrowed down to a problem in the C compiler, or it has to be changed in
        !           153:    order to get it to compile, or it produces suspicious output (like a very
        !           154:    low maximum float, for instance), please mail the problem and an example
        !           155:    of the incorrect output to [email protected] or ..!hp4nl!cwi.nl!steven, so that
        !           156:    improvements can be worked into future versions; cwi.nl is the European
        !           157:    backbone, and is connected to uunet and other fine hosts.
        !           158: 
        !           159:    The program tries to catch and diagnose bugs in the compiler/run-time
        !           160:    system. I would be especially pleased to have reports of failures so
        !           161:    that I can improve this service.
        !           162: 
        !           163:    I apologise unreservedly for the contorted use of the preprocessor...
        !           164: 
        !           165:    THE SMALL PRINT
        !           166:    You may copy and distribute verbatim copies of this source file.
        !           167: 
        !           168:    You may modify this source file, and copy and distribute such
        !           169:    modified versions, provided that you leave the copyright notice
        !           170:    at the top of the file and also cause the modified file to carry
        !           171:    prominent notices stating that you changed the files and the date
        !           172:    of any change; and cause the whole of any work that you distribute
        !           173:    or publish, that in whole or in part contains or is a derivative of
        !           174:    this program or any part thereof, to be licensed at no charge to
        !           175:    all third parties on terms identical to those here.
        !           176: 
        !           177:    If you do have a fix to any problem, please send it to me, so that
        !           178:    other people can have the benefits.
        !           179: 
        !           180:    While every effort has been taken to make this program as reliable as
        !           181:    possible, no responsibility can be taken for the correctness of the
        !           182:    output, or suitability for any particular use.
        !           183: 
        !           184:    ACKNOWLEDGEMENTS
        !           185:    Many people have given time and ideas to making this program what it is.
        !           186:    To all of them thanks, and apologies for not mentioning them by name.
        !           187: 
        !           188:    HISTORY
        !           189:    4.0 Added -f and -l options, and warnings
        !           190:    4.1 Added VERIFY
        !           191:    4.2 Added SEP
        !           192:        Fixed eps/epsneg
        !           193:        Added check for pseudo-unsigned chars
        !           194:        Added description for each #define output
        !           195:        Added check for absence of defines during verify
        !           196:        Added prototypes
        !           197:        Added NO_STDC and NO_FILE
        !           198:        Fixed alignments output
        !           199: */
        !           200: 
        !           201: #ifndef NO_FILE
        !           202: #ifndef __FILE__
        !           203: #define __FILE__ "config.c"
        !           204: #endif
        !           205: #endif
        !           206: 
        !           207: /* If PASS isn't defined, then this is the first pass over this file. */
        !           208: #ifndef PASS
        !           209: #ifndef SEP
        !           210: #define PASS 1
        !           211: #define PASS0 1
        !           212: #define PASS1 1
        !           213: #endif /* SEP */
        !           214: 
        !           215: /* A description of the ANSI constants */
        !           216: #define D_CHAR_BIT "Number of bits in a storage unit"
        !           217: #define D_CHAR_MAX "Maximum char"
        !           218: #define D_CHAR_MIN "Minimum char"
        !           219: #define D_SCHAR_MAX "Maximum signed char"
        !           220: #define D_SCHAR_MIN "Minimum signed char"
        !           221: #define D_UCHAR_MAX "Maximum unsigned char (minimum is always 0)"
        !           222: 
        !           223: #define D_INT_MAX "Maximum %s"
        !           224: #define D_INT_MIN "Minimum %s"
        !           225: #define D_UINT_MAX "Maximum unsigned %s (minimum is always 0)"
        !           226: 
        !           227: #define D_FLT_ROUNDS "Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown"
        !           228: #define D_FLT_RADIX "Radix of exponent representation"
        !           229: #define D_MANT_DIG "Number of base-FLT_RADIX digits in the mantissa of a %s"
        !           230: #define D_DIG "Number of decimal digits of precision in a %s"
        !           231: #define D_MIN_EXP "Minimum int x such that FLT_RADIX**(x-1) is a normalised %s"
        !           232: #define D_MIN_10_EXP "Minimum int x such that 10**x is a normalised %s"
        !           233: #define D_MAX_EXP "Maximum int x such that FLT_RADIX**(x-1) is a representable %s"
        !           234: #define D_MAX_10_EXP "Maximum int x such that 10**x is a representable %s"
        !           235: #define D_MAX "Maximum %s"
        !           236: #define D_EPSILON "Minimum %s x such that 1.0+x != 1.0"
        !           237: #define D_MIN "Minimum normalised %s"
        !           238: 
        !           239: /* Procedure just marks the functions that don't return a result */
        !           240: #ifdef NO_VOID
        !           241: #define Procedure int
        !           242: #else
        !           243: #define Procedure void
        !           244: #endif
        !           245: 
        !           246: /* Some bad compilers define __STDC__, when they don't support it.
        !           247:    Compile with -DNO_STDC to get round this.
        !           248: */
        !           249: #ifndef NO_STDC
        !           250: #ifdef __STDC__
        !           251: #define STDC
        !           252: #endif
        !           253: #endif
        !           254: 
        !           255: /* Stuff different for ANSI C, and old C:
        !           256:    ARGS and NOARGS are used for function prototypes.
        !           257:    Volatile is used to reduce the chance of optimisation,
        !           258:       and to prevent variables being put in registers (when setjmp/longjmp
        !           259:       wouldn't work as we want)
        !           260:    Long_double is the longest floating point type available.
        !           261:    stdc is used in tests like "if (stdc)", which is less ugly than #ifdef.
        !           262:    U is output after unsigned constants.
        !           263:  */
        !           264: #ifdef STDC
        !           265: 
        !           266: #define ARGS(x) x
        !           267: #define NOARGS (void)
        !           268: #define Volatile volatile
        !           269: #define Long_double long double
        !           270: #define stdc 1
        !           271: #define U "U"
        !           272: 
        !           273: #else /* Old style C */
        !           274: 
        !           275: #define ARGS(x) ()
        !           276: #define NOARGS ()
        !           277: #define Volatile static
        !           278: #define Long_double double
        !           279: #define stdc 0
        !           280: #define U ""
        !           281: 
        !           282: #endif /* STDC */
        !           283: 
        !           284: /* include files */
        !           285: #include <stdio.h>
        !           286: 
        !           287: #ifdef NO_SIG
        !           288: #define jmp_buf int
        !           289: #else
        !           290: #include <signal.h>
        !           291: #include <setjmp.h>
        !           292: #endif
        !           293: 
        !           294: #ifdef VERIFY
        !           295: #include "limits.h"
        !           296: #include "float.h"
        !           297: #endif
        !           298: 
        !           299: #define Vprintf if (V) printf
        !           300: #define Unexpected(place) if (setjmp(lab)!=0) croak(place)
        !           301: #define fabs(x) (((x)<0.0)?(-x):(x))
        !           302: 
        !           303: #endif /* PASS */
        !           304: 
        !           305: #ifdef PASS0
        !           306: 
        !           307: /* Prototypes for what's to come: */
        !           308: 
        !           309: char *malloc ARGS((unsigned size));
        !           310: Procedure exit ARGS((int status));
        !           311: 
        !           312: char *f_rep ARGS((int precision, Long_double val));
        !           313: 
        !           314: int cprop NOARGS;
        !           315: int basic NOARGS;
        !           316: Procedure sprop NOARGS;
        !           317: Procedure iprop NOARGS;
        !           318: Procedure lprop NOARGS;
        !           319: Procedure usprop NOARGS;
        !           320: Procedure uiprop NOARGS;
        !           321: Procedure ulprop NOARGS;
        !           322: int fprop ARGS((int bits_per_byte));
        !           323: int dprop ARGS((int bits_per_byte));
        !           324: int ldprop ARGS((int bits_per_byte));
        !           325: Procedure efprop ARGS((int fprec, int dprec, int lprec));
        !           326: Procedure edprop ARGS((int fprec, int dprec, int lprec));
        !           327: Procedure eldprop ARGS((int fprec, int dprec, int lprec));
        !           328: 
        !           329: int setmode ARGS((char *s));
        !           330: Procedure farewell ARGS((int bugs));
        !           331: Procedure describe ARGS((char *description, char *extra));
        !           332: Procedure check_defines NOARGS;
        !           333: Procedure bitpattern ARGS((char *p, unsigned int size));
        !           334: int ceil_log ARGS((int base, Long_double x));
        !           335: Procedure croak ARGS((int place));
        !           336: Procedure eek_a_bug ARGS((char *problem));
        !           337: Procedure endian ARGS((int bits_per_byte));
        !           338: int exponent ARGS((Long_double x, double *fract, int *exp));
        !           339: int floor_log ARGS((int base, Long_double x));
        !           340: Procedure f_define ARGS((char *desc, char *extra, char *sort, char *name,
        !           341:                         int prec, Long_double val, char *mark));
        !           342: Procedure i_define ARGS((char *desc, char *extra, char *sort, char *name,
        !           343:                         long val, long req, char *mark));
        !           344: Procedure u_define ARGS((char *desc, char *extra, char *sort, char *name,
        !           345:                         unsigned long val, unsigned long req, char *mark));
        !           346: 
        !           347: #ifdef NO_SIG  /* There's no signal(), or setjmp/longjmp() */
        !           348: 
        !           349:        /* Dummy routines instead */
        !           350: 
        !           351:        Procedure setjmp ARGS((int lab));
        !           352: 
        !           353:        int lab=1;
        !           354:        int setjmp(lab) int lab; { return(0); }
        !           355:        Procedure signal(i, p) int i, (*p)(); {}
        !           356: 
        !           357: #else
        !           358:        jmp_buf lab;
        !           359:        Procedure overflow(sig) int sig; { /* what to do on over/underflow */
        !           360:                signal(sig, overflow);
        !           361:                longjmp(lab, 1);
        !           362:        }
        !           363: 
        !           364: #endif /*NO_SIG*/
        !           365: 
        !           366: int V= 0,      /* verbose */
        !           367:     L= 0,      /* produce limits.h */
        !           368:     F= 0,      /* produce float.h  */
        !           369:     bugs=0;    /* The number of (possible) bugs in the output */
        !           370: 
        !           371: char co[4], oc[4]; /* Comment starter and ender symbols */
        !           372: 
        !           373: int bits_per_byte; /* the number of bits per unit returned by sizeof() */
        !           374: int flt_rounds;    /* The calculated value of FLT_ROUNDS */
        !           375: int flt_radix;     /* The calculated value of FLT_RADIX */
        !           376: 
        !           377: #ifdef TEST
        !           378: /* Set the fp modes on a SUN with 68881 chip, to check that different
        !           379:    rounding modes etc. get properly detected.
        !           380:    Compile with additional flag -DTEST, and run with additional parameter
        !           381:    +hex-number, to set the 68881 mode register to hex-number
        !           382: */
        !           383: 
        !           384: /* Bits 0x30 = rounding mode: */
        !           385: #define ROUND_BITS     0x30
        !           386: #define TO_NEAREST     0x00
        !           387: #define TO_ZERO                0x10
        !           388: #define TO_MINUS_INF   0x20
        !           389: #define TO_PLUS_INF    0x30 /* The SUN FP user's guide seems to be wrong here */
        !           390: 
        !           391: /* Bits 0xc0 = extended rounding: */
        !           392: #define EXT_BITS       0xc0
        !           393: #define ROUND_EXTENDED 0x00
        !           394: #define ROUND_SINGLE   0x40
        !           395: #define ROUND_DOUBLE   0x80
        !           396: 
        !           397: /* Enabled traps: */
        !           398: #define EXE_INEX1  0x100
        !           399: #define EXE_INEX2  0x200
        !           400: #define EXE_DZ    0x400
        !           401: #define EXE_UNFL   0x800
        !           402: #define EXE_OVFL  0x1000
        !           403: #define EXE_OPERR 0x2000
        !           404: #define EXE_SNAN  0x4000
        !           405: #define EXE_BSUN  0x8000
        !           406: 
        !           407: /* Only used for testing, on a Sun with 68881 chip */
        !           408: /* Print the FP mode */
        !           409: printmode(new) unsigned new; {
        !           410:        fpmode_(&new);
        !           411:        printf("New fp mode:\n");
        !           412:        printf("  Round toward ");
        !           413:        switch (new & ROUND_BITS) {
        !           414:              case TO_NEAREST:   printf("nearest"); break;
        !           415:              case TO_ZERO:      printf("zero"); break;
        !           416:              case TO_MINUS_INF: printf("minus infinity"); break;
        !           417:              case TO_PLUS_INF:  printf("plus infinity"); break;
        !           418:              default: printf("???"); break;
        !           419:        }
        !           420: 
        !           421:        printf("\n  Extended rounding precision: ");
        !           422: 
        !           423:        switch (new & EXT_BITS) {
        !           424:              case ROUND_EXTENDED: printf("extended"); break;
        !           425:              case ROUND_SINGLE:   printf("single"); break;
        !           426:              case ROUND_DOUBLE:   printf("double"); break;
        !           427:              default: printf("???"); break;
        !           428:        }
        !           429: 
        !           430:        printf("\n  Enabled exceptions:");
        !           431:        if (new & (unsigned) EXE_INEX1) printf(" inex1");
        !           432:        if (new & (unsigned) EXE_INEX2) printf(" inex2");
        !           433:        if (new & (unsigned) EXE_DZ)    printf(" dz"); 
        !           434:        if (new & (unsigned) EXE_UNFL)  printf(" unfl"); 
        !           435:        if (new & (unsigned) EXE_OVFL)  printf(" ovfl"); 
        !           436:        if (new & (unsigned) EXE_OPERR) printf(" operr"); 
        !           437:        if (new & (unsigned) EXE_SNAN)  printf(" snan"); 
        !           438:        if (new & (unsigned) EXE_BSUN)  printf(" bsun"); 
        !           439:        printf("\n");
        !           440: }
        !           441: 
        !           442: /* Only used for testing, on a Sun with 68881 chip */
        !           443: /* Set the FP mode */
        !           444: int setmode(s) char *s; {
        !           445:        unsigned mode=0, dig;
        !           446:        char c;
        !           447: 
        !           448:        while (*s) {
        !           449:                c= *s++;
        !           450:                if  (c>='0' && c<='9') dig= c-'0';
        !           451:                else if (c>='a' && c<='f') dig= c-'a'+10;
        !           452:                else if (c>='A' && c<='F') dig= c-'A'+10;
        !           453:                else return 1;
        !           454:                mode= mode<<4 | dig;
        !           455:        }
        !           456:        printmode(mode);
        !           457:        return 0;
        !           458: }
        !           459: #else
        !           460: int setmode(s) char *s; {
        !           461:        fprintf(stderr, "Can't set mode: not compiled with TEST\n");
        !           462:        return(1);
        !           463: }
        !           464: #endif
        !           465: 
        !           466: Procedure farewell(bugs) int bugs; {
        !           467:        if (bugs > 0) {
        !           468:                printf("\n%sFor hints on dealing with the problems above", co);
        !           469:                printf("\n   see the section 'TROUBLESHOOTING' in the file ");
        !           470:                printf("%s%s\n", __FILE__, oc);
        !           471:        }
        !           472:        exit(bugs);
        !           473: }
        !           474: 
        !           475: /* The program has received a signal where it wasn't expecting one */
        !           476: Procedure croak(place) int place; {
        !           477:        printf("*** Unexpected signal at point %d\n", place);
        !           478:        farewell(bugs+1); /* An exit isn't essential here, but avoids loops */
        !           479: }
        !           480: 
        !           481: main(argc, argv) int argc; char *argv[]; {
        !           482:        int dprec, fprec, lprec;
        !           483:        unsigned int size;
        !           484:        long total;
        !           485:        int i; char *s; int bad;
        !           486: 
        !           487: #ifdef SIGFPE
        !           488:        signal(SIGFPE, overflow);
        !           489: #endif
        !           490: #ifdef SIGOVER
        !           491:        signal(SIGOVER, overflow);
        !           492: #endif
        !           493: /* Add more calls as necessary */
        !           494: 
        !           495:        Unexpected(1);
        !           496: 
        !           497:        bad=0;
        !           498:        for (i=1; i < argc; i++) {
        !           499:                s= argv[i];
        !           500:                if (*s == '-') {
        !           501:                        s++;
        !           502:                        while (*s) {
        !           503:                                switch (*(s++)) {
        !           504:                                      case 'v': V=1; break;
        !           505:                                      case 'l': L=1; break;
        !           506:                                      case 'f': F=1; break;
        !           507:                                      default: bad=1; break;
        !           508:                                }
        !           509:                        }
        !           510:                } else if (*s == '+') {
        !           511:                        s++;
        !           512:                        bad= setmode(s);
        !           513:                } else bad= 1;
        !           514:        }
        !           515:        if (bad) {
        !           516:                fprintf(stderr,
        !           517:                        "Usage: %s [-vlf]\n  v=Verbose l=Limits.h f=Float.h\n",
        !           518:                        argv[0]);
        !           519:                exit(1);
        !           520:        }
        !           521:        if (L || F) {
        !           522:                co[0]= '/'; oc[0]= ' ';
        !           523:                co[1]= '*'; oc[1]= '*';
        !           524:                co[2]= ' '; oc[2]= '/';
        !           525:                co[3]= '\0'; oc[3]= '\0';
        !           526:        } else {
        !           527:                co[0]= '\0'; oc[0]= '\0';
        !           528:                V=1;
        !           529:        }
        !           530: 
        !           531:        if (L) printf("%slimits.h%s\n", co, oc);
        !           532:        if (F) printf("%sfloat.h%s\n", co, oc);
        !           533: #ifdef ID
        !           534:        printf("%sProduced on %s by config version %s, CWI, Amsterdam%s\n",
        !           535:               co, ID, VERSION, oc);
        !           536: #else
        !           537:        printf("%sProduced by config version %s, CWI, Amsterdam%s\n",
        !           538:               co, VERSION, oc);
        !           539: #endif
        !           540: 
        !           541: #ifdef VERIFY
        !           542:        printf("%sVerification phase%s\n", co, oc);
        !           543: #endif
        !           544: 
        !           545: #ifdef NO_SIG
        !           546:        Vprintf("%sCompiled without signal(): %s%s\n",
        !           547:                co,
        !           548:                "there's nothing that can be done if overflow occurs",
        !           549:                oc);
        !           550: #endif
        !           551: #ifdef NO_SC
        !           552:        Vprintf("%sCompiled without signed char%s\n", co, oc);
        !           553: #endif
        !           554: #ifdef NO_UC
        !           555:        Vprintf("%Compiled without unsigned char%s\n", co, oc);
        !           556: #endif
        !           557: #ifdef NO_UI
        !           558:        Vprintf("%Compiled without unsigned short or long%s\n", co, oc);
        !           559: #endif
        !           560: #ifdef __STDC__
        !           561:        Vprintf("%sCompiler claims to be ANSI C level %d%s\n",
        !           562:                co, __STDC__, oc);
        !           563: #else
        !           564:        Vprintf("%sCompiler does not claim to be ANSI C%s\n", co, oc);
        !           565: #endif
        !           566:        printf("\n");
        !           567:        check_defines();
        !           568: 
        !           569:        bits_per_byte= basic();
        !           570:        Vprintf("\n");
        !           571:        if (F||V) {
        !           572:                fprec= fprop(bits_per_byte);
        !           573:                dprec= dprop(bits_per_byte);
        !           574:                lprec= ldprop(bits_per_byte);
        !           575:                efprop(fprec, dprec, lprec);
        !           576:                edprop(fprec, dprec, lprec);
        !           577:                eldprop(fprec, dprec, lprec);
        !           578:        }
        !           579:        if (V) {
        !           580:                /* An extra goody: the approximate amount of data-space */
        !           581:                /* Allocate store until no more available */
        !           582:                size=1<<((bits_per_byte*sizeof(int))-2);
        !           583:                total=0;
        !           584:                while (size!=0) {
        !           585:                        while (malloc(size)!=(char *)NULL) total+=(size/2);
        !           586:                        size/=2;
        !           587:                }
        !           588: 
        !           589:                Vprintf("%sMemory mallocatable ~= %ld Kbytes%s\n",
        !           590:                        co, (total+511)/512, oc);
        !           591:        }
        !           592:        farewell(bugs);
        !           593:        return bugs; /* To keep compilers and lint happy */
        !           594: }
        !           595: 
        !           596: Procedure eek_a_bug(problem) char *problem; {
        !           597:        /* The program has discovered a problem */
        !           598:        printf("\n%s*** WARNING: %s%s\n", co, problem, oc);
        !           599:        bugs++;
        !           600: }
        !           601: 
        !           602: Procedure describe(description, extra) char *description, *extra; {
        !           603:        /* Produce the description for a #define */
        !           604:        printf("   %s", co);
        !           605:        printf(description, extra);
        !           606:        printf("%s\n", oc);
        !           607: }
        !           608: 
        !           609: Procedure i_define(desc, extra, sort, name, val, req, mark)
        !           610:      char *desc, *extra, *sort, *name; long val, req; char *mark; {
        !           611:        /* Produce a #define for a signed int type */
        !           612:        describe(desc, extra);
        !           613:        if (val >= 0) {
        !           614:                printf("#define %s%s %ld%s\n", sort, name, val, mark);
        !           615:        } else {
        !           616:                printf("#define %s%s (%ld%s)\n", sort, name, val, mark);
        !           617:        }
        !           618:        if (val != req) {
        !           619:                printf("%s*** Verify failed for above #define!\n", co);
        !           620:                printf("       Compiler has %ld for value%s\n\n", req, oc);
        !           621:                bugs++;
        !           622:        }
        !           623:        Vprintf("\n");
        !           624: }
        !           625: 
        !           626: Procedure u_define(desc, extra, sort, name, val, req, mark)
        !           627:      char *desc, *extra, *sort, *name; unsigned long val, req; char *mark; {
        !           628:        /* Produce a #define for an unsigned value */
        !           629:        describe(desc, extra);
        !           630:        printf("#define %s%s %lu%s%s\n", sort, name, val, U, mark);
        !           631:        if (val != req) {
        !           632:                printf("%s*** Verify failed for above #define!\n", co);
        !           633:                printf("       Compiler has %lu for value%s\n\n", req, oc);
        !           634:                bugs++;
        !           635:        }
        !           636:        Vprintf("\n");
        !           637: }
        !           638: 
        !           639: Procedure f_define(desc, extra, sort, name, precision, val, mark)
        !           640:      char *desc, *extra, *sort, *name; int precision;
        !           641:      Long_double val; char *mark; {
        !           642:        /* Produce a #define for a float/double/long double */
        !           643:        describe(desc, extra);
        !           644:        if (stdc) {
        !           645:                printf("#define %s%s %s%s\n",
        !           646:                       sort, name, f_rep(precision, val), mark);
        !           647:        } else if (*mark == 'F') {
        !           648:                /* non-ANSI C has no float constants, so cast the constant */
        !           649:                printf("#define %s%s ((float)%s)\n",
        !           650:                       sort, name, f_rep(precision, val));
        !           651:        } else {
        !           652:                printf("#define %s%s %s\n", sort, name, f_rep(precision, val));
        !           653:        }
        !           654:        Vprintf("\n");
        !           655: }
        !           656: 
        !           657: int floor_log(base, x) int base; Long_double x; {
        !           658:        /* return floor(log base(x)) */
        !           659:        int r=0;
        !           660:        while (x>=base) { r++; x/=base; }
        !           661:        return r;
        !           662: }
        !           663: 
        !           664: int ceil_log(base, x) int base; Long_double x; {
        !           665:        int r=0;
        !           666:        while (x>1.0) { r++; x/=base; }
        !           667:        return r;
        !           668: }
        !           669: 
        !           670: int exponent(x, fract, exp) Long_double x; double *fract; int *exp; {
        !           671:        /* Split x into a fraction and a power of ten;
        !           672:           returns 0 if x is unusable, 1 otherwise.
        !           673:           Only used for error messages about faulty output.
        !           674:        */
        !           675:        int r=0, neg=0;
        !           676:        Long_double old;
        !           677:        *fract=0.0; *exp=0;
        !           678:        if (x<0.0) {
        !           679:                x= -x;
        !           680:                neg= 1;
        !           681:        }
        !           682:        if (x==0.0) return 1;
        !           683:        if (x>=10.0) {
        !           684:                while (x>=10.0) {
        !           685:                        old=x; r++; x/=10.0;
        !           686:                        if (old==x) return 0;
        !           687:                }
        !           688:        } else {
        !           689:                while (x<1.0) {
        !           690:                        old=x; r--; x*=10.0;
        !           691:                        if (old==x) return 0;
        !           692:                }
        !           693:        }
        !           694:        if (neg) *fract= -x;
        !           695:        else *fract=x;
        !           696:        *exp=r;
        !           697:        return 1;
        !           698: }
        !           699: 
        !           700: char *f_rep(precision, val) int precision; Long_double val; {
        !           701:        /* Return the floating representation of val */
        !           702:        static char buf[1024];
        !           703:        char *f1;
        !           704:        if (sizeof(double) == sizeof(Long_double)) {
        !           705:                /* Assume they're the same, and use non-stdc format */
        !           706:                /* This is for stdc compilers using non-stdc libraries */
        !           707:                f1= "%.*e";
        !           708:        } else {
        !           709:                /* It had better support Le then */
        !           710:                f1= "%.*Le";
        !           711:        }
        !           712:        sprintf(buf, f1, precision, val);
        !           713:        return buf;
        !           714: }
        !           715: 
        !           716: Procedure bitpattern(p, size) char *p; unsigned int size; {
        !           717:        /* Printf the bit-pattern of p */
        !           718:        char c;
        !           719:        int i, j;
        !           720: 
        !           721:        for (i=1; i<=size; i++) {
        !           722:                c= *p;
        !           723:                p++;
        !           724:                for (j=bits_per_byte-1; j>=0; j--)
        !           725:                        printf("%c", (c>>j)&1 ? '1' : '0');
        !           726:                if (i!=size) printf(" ");
        !           727:        }
        !           728: }
        !           729: 
        !           730: #define Order(x, px, mode)\
        !           731:    printf("%s    %s ", co, mode); for (i=0; i<sizeof(x); i++) px[i]= c[i]; \
        !           732:    for (i=1; i<=sizeof(x); i++) { putchar((char)((x>>(bits_per_byte*(sizeof(x)-i)))&mask)); }\
        !           733:    printf("%s\n", oc);
        !           734: 
        !           735: Procedure endian(bits_per_byte) int bits_per_byte; {
        !           736:        /* Printf the byte-order used on this machine */
        !           737:        /*unsigned*/ short s=0;
        !           738:        /*unsigned*/ int j=0;
        !           739:        /*unsigned*/ long l=0;
        !           740: 
        !           741:        char *ps= (char *) &s,
        !           742:             *pj= (char *) &j,
        !           743:             *pl= (char *) &l,
        !           744:             *c= "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        !           745:        unsigned int mask, i;
        !           746: 
        !           747:        mask=0;
        !           748:        for (i=1; i<=(unsigned)bits_per_byte; i++) mask= (mask<<1)|1;
        !           749: 
        !           750:        if (V) {
        !           751:                printf("%sCharacter order:%s\n", co, oc);
        !           752:                Order(s, ps, "short:");
        !           753:                Order(j, pj, "int:  ");
        !           754:                Order(l, pl, "long: ");
        !           755:        }
        !           756: }
        !           757: 
        !           758: Procedure check_defines() {
        !           759:        /* ensure that all the #defines are present */
        !           760: #ifdef VERIFY
        !           761:        if (L) {
        !           762: #ifndef CHAR_BIT
        !           763:        printf("%s*** CHAR_BIT missing from limits.h%s\n", co, oc); bugs++;
        !           764: #endif
        !           765: #ifndef CHAR_MAX
        !           766:        printf("%s*** CHAR_MAX missing from limits.h%s\n", co, oc); bugs++;
        !           767: #endif
        !           768: #ifndef CHAR_MIN
        !           769:        printf("%s*** CHAR_MIN missing from limits.h%s\n", co, oc); bugs++;
        !           770: #endif
        !           771: #ifndef SCHAR_MAX
        !           772:        printf("%s*** SCHAR_MAX missing from limits.h%s\n", co, oc); bugs++;
        !           773: #endif
        !           774: #ifndef SCHAR_MIN
        !           775:        printf("%s*** SCHAR_MIN missing from limits.h%s\n", co, oc); bugs++;
        !           776: #endif
        !           777: #ifndef UCHAR_MAX
        !           778:        printf("%s*** UCHAR_MAX missing from limits.h%s\n", co, oc); bugs++;
        !           779: #endif
        !           780: #ifndef SHRT_MAX
        !           781:        printf("%s*** SHRT_MAX missing from limits.h%s\n", co, oc); bugs++;
        !           782: #endif
        !           783: #ifndef SHRT_MIN
        !           784:        printf("%s*** SHRT_MIN missing from limits.h%s\n", co, oc); bugs++;
        !           785: #endif
        !           786: #ifndef INT_MAX
        !           787:        printf("%s*** INT_MAX missing from limits.h%s\n", co, oc); bugs++;
        !           788: #endif
        !           789: #ifndef INT_MIN
        !           790:        printf("%s*** INT_MIN missing from limits.h%s\n", co, oc); bugs++;
        !           791: #endif
        !           792: #ifndef LONG_MAX
        !           793:        printf("%s*** LONG_MAX missing from limits.h%s\n", co, oc); bugs++;
        !           794: #endif
        !           795: #ifndef LONG_MIN
        !           796:        printf("%s*** LONG_MIN missing from limits.h%s\n", co, oc); bugs++;
        !           797: #endif
        !           798: #ifndef USHRT_MAX
        !           799:        printf("%s*** USHRT_MAX missing from limits.h%s\n", co, oc); bugs++;
        !           800: #endif
        !           801: #ifndef UINT_MAX
        !           802:        printf("%s*** UINT_MAX missing from limits.h%s\n", co, oc); bugs++;
        !           803: #endif
        !           804: #ifndef ULONG_MAX
        !           805:        printf("%s*** ULONG_MAX missing from limits.h%s\n", co, oc); bugs++;
        !           806: #endif
        !           807:        } /* if (L) */
        !           808: 
        !           809:        if (F) {
        !           810: #ifndef FLT_RADIX
        !           811:        printf("%s*** FLT_RADIX missing from float.h%s\n", co, oc); bugs++;
        !           812: #endif
        !           813: #ifndef FLT_MANT_DIG
        !           814:        printf("%s*** FLT_MANT_DIG missing from float.h%s\n", co, oc); bugs++;
        !           815: #endif
        !           816: #ifndef FLT_DIG
        !           817:        printf("%s*** FLT_DIG missing from float.h%s\n", co, oc); bugs++;
        !           818: #endif
        !           819: #ifndef FLT_ROUNDS
        !           820:        printf("%s*** FLT_ROUNDS missing from float.h%s\n", co, oc); bugs++;
        !           821: #endif
        !           822: #ifndef FLT_EPSILON
        !           823:        printf("%s*** FLT_EPSILON missing from float.h%s\n", co, oc); bugs++;
        !           824: #endif
        !           825: #ifndef FLT_MIN_EXP
        !           826:        printf("%s*** FLT_MIN_EXP missing from float.h%s\n", co, oc); bugs++;
        !           827: #endif
        !           828: #ifndef FLT_MIN
        !           829:        printf("%s*** FLT_MIN missing from float.h%s\n", co, oc); bugs++;
        !           830: #endif
        !           831: #ifndef FLT_MIN_10_EXP
        !           832:        printf("%s*** FLT_MIN_10_EXP missing from float.h%s\n", co, oc); bugs++;
        !           833: #endif
        !           834: #ifndef FLT_MAX_EXP
        !           835:        printf("%s*** FLT_MAX_EXP missing from float.h%s\n", co, oc); bugs++;
        !           836: #endif
        !           837: #ifndef FLT_MAX
        !           838:        printf("%s*** FLT_MAX missing from float.h%s\n", co, oc); bugs++;
        !           839: #endif
        !           840: #ifndef FLT_MAX_10_EXP
        !           841:        printf("%s*** FLT_MAX_10_EXP missing from float.h%s\n", co, oc); bugs++;
        !           842: #endif
        !           843: #ifndef DBL_MANT_DIG
        !           844:        printf("%s*** DBL_MANT_DIG missing from float.h%s\n", co, oc); bugs++;
        !           845: #endif
        !           846: #ifndef DBL_DIG
        !           847:        printf("%s*** DBL_DIG missing from float.h%s\n", co, oc); bugs++;
        !           848: #endif
        !           849: #ifndef DBL_EPSILON
        !           850:        printf("%s*** DBL_EPSILON missing from float.h%s\n", co, oc); bugs++;
        !           851: #endif
        !           852: #ifndef DBL_MIN_EXP
        !           853:        printf("%s*** DBL_MIN_EXP missing from float.h%s\n", co, oc); bugs++;
        !           854: #endif
        !           855: #ifndef DBL_MIN
        !           856:        printf("%s*** DBL_MIN missing from float.h%s\n", co, oc); bugs++;
        !           857: #endif
        !           858: #ifndef DBL_MIN_10_EXP
        !           859:        printf("%s*** DBL_MIN_10_EXP missing from float.h%s\n", co, oc); bugs++;
        !           860: #endif
        !           861: #ifndef DBL_MAX_EXP
        !           862:        printf("%s*** DBL_MAX_EXP missing from float.h%s\n", co, oc); bugs++;
        !           863: #endif
        !           864: #ifndef DBL_MAX
        !           865:        printf("%s*** DBL_MAX missing from float.h%s\n", co, oc); bugs++;
        !           866: #endif
        !           867: #ifndef DBL_MAX_10_EXP
        !           868:        printf("%s*** DBL_MAX_10_EXP missing from float.h%s\n", co, oc); bugs++;
        !           869: #endif
        !           870: #ifdef STDC
        !           871: #ifndef LDBL_MANT_DIG
        !           872:        printf("%s*** LDBL_MANT_DIG missing from float.h%s\n", co, oc); bugs++;
        !           873: #endif
        !           874: #ifndef LDBL_DIG
        !           875:        printf("%s*** LDBL_DIG missing from float.h%s\n", co, oc); bugs++;
        !           876: #endif
        !           877: #ifndef LDBL_EPSILON
        !           878:        printf("%s*** LDBL_EPSILON missing from float.h%s\n", co, oc); bugs++;
        !           879: #endif
        !           880: #ifndef LDBL_MIN_EXP
        !           881:        printf("%s*** LDBL_MIN_EXP missing from float.h%s\n", co, oc); bugs++;
        !           882: #endif
        !           883: #ifndef LDBL_MIN
        !           884:        printf("%s*** LDBL_MIN missing from float.h%s\n", co, oc); bugs++;
        !           885: #endif
        !           886: #ifndef LDBL_MIN_10_EXP
        !           887:        printf("%s*** LDBL_MIN_10_EXP missing from float.h%s\n", co, oc); bugs++;
        !           888: #endif
        !           889: #ifndef LDBL_MAX_EXP
        !           890:        printf("%s*** LDBL_MAX_EXP missing from float.h%s\n", co, oc); bugs++;
        !           891: #endif
        !           892: #ifndef LDBL_MAX
        !           893:        printf("%s*** LDBL_MAX missing from float.h%s\n", co, oc); bugs++;
        !           894: #endif
        !           895: #ifndef LDBL_MAX_10_EXP
        !           896:        printf("%s*** LDBL_MAX_10_EXP missing from float.h%s\n", co, oc); bugs++;
        !           897: #endif
        !           898: #endif /* STDC */
        !           899:        } /* if (F) */
        !           900: #endif /* VERIFY */
        !           901: }
        !           902: 
        !           903: #ifdef VERIFY
        !           904: #ifndef SCHAR_MAX
        !           905: #define SCHAR_MAX      char_max
        !           906: #endif
        !           907: #ifndef SCHAR_MIN
        !           908: #define SCHAR_MIN      char_min
        !           909: #endif
        !           910: #ifndef UCHAR_MAX
        !           911: #define UCHAR_MAX      char_max
        !           912: #endif
        !           913: #endif /* VERIFY */
        !           914: 
        !           915: #ifndef CHAR_BIT
        !           916: #define CHAR_BIT       char_bit
        !           917: #endif
        !           918: #ifndef CHAR_MAX
        !           919: #define CHAR_MAX       char_max
        !           920: #endif
        !           921: #ifndef CHAR_MIN
        !           922: #define CHAR_MIN       char_min
        !           923: #endif
        !           924: #ifndef SCHAR_MAX
        !           925: #define SCHAR_MAX      char_max
        !           926: #endif
        !           927: #ifndef SCHAR_MIN
        !           928: #define SCHAR_MIN      char_min
        !           929: #endif
        !           930: #ifndef UCHAR_MAX
        !           931: #define UCHAR_MAX      char_max
        !           932: #endif
        !           933: 
        !           934: int cprop() {
        !           935:        /* Properties of type char */
        !           936:        Volatile char c, char_max, char_min;
        !           937:        Volatile int bits_per_byte, is_signed;
        !           938:        long char_bit;
        !           939: 
        !           940:        Unexpected(2);
        !           941: 
        !           942:        /* Calculate number of bits per character *************************/
        !           943:        c=1; bits_per_byte=0;
        !           944:        do { c=c<<1; bits_per_byte++; } while(c!=0);
        !           945:        c= (char)(-1);
        !           946:        if (((int)c)<0) is_signed=1;
        !           947:        else is_signed=0;
        !           948:        Vprintf("%sChar = %d bits, %ssigned%s\n",
        !           949:                co, (int)sizeof(c)*bits_per_byte, (is_signed?"":"un"), oc);
        !           950:        char_bit=(long)(sizeof(c)*bits_per_byte);
        !           951:        if (L) i_define(D_CHAR_BIT, "",
        !           952:                        "CHAR", "_BIT", char_bit, (long) CHAR_BIT, "");
        !           953: 
        !           954:        c=0; char_max=0;
        !           955:        c++;
        !           956:        if (setjmp(lab)==0) { /* Yields char_max */
        !           957:                while (c>char_max) {
        !           958:                        char_max=c;
        !           959:                        c++;
        !           960:                }
        !           961:        } else {
        !           962:                Vprintf("%sCharacter overflow generates a trap!%s\n", co, oc);
        !           963:        }
        !           964:        c=0; char_min=0;
        !           965:        c--;
        !           966:        if (setjmp(lab)==0) { /* Yields char_min */
        !           967:                while (c<char_min) {
        !           968:                        char_min=c;
        !           969:                        c--;
        !           970:                }
        !           971:        }
        !           972:        if (is_signed && char_min == 0) {
        !           973:                Vprintf("%sBEWARE! Chars are pseudo-unsigned:%s\n", co, oc);
        !           974:                Vprintf("%s   %s%s%s\n",
        !           975:                        "They contain only nonnegative values, ",
        !           976:                        "but sign extend when used as integers.", co, oc);
        !           977:        }
        !           978:        Unexpected(3);
        !           979: 
        !           980:        if (L) {
        !           981:                i_define(D_CHAR_MAX, "",
        !           982:                         "CHAR", "_MAX", (long) char_max, (long) CHAR_MAX, "");
        !           983:                i_define(D_CHAR_MIN, "",
        !           984:                         "CHAR", "_MIN", (long) char_min, (long) CHAR_MIN, "");
        !           985:                if (is_signed) {
        !           986:                        i_define(D_SCHAR_MAX, "",
        !           987:                                 "SCHAR", "_MAX", (long) char_max,
        !           988:                                 (long) SCHAR_MAX, "");
        !           989:                        i_define(D_SCHAR_MIN, "",
        !           990:                                 "SCHAR", "_MIN", (long) char_min,
        !           991:                                 (long) SCHAR_MIN, "");
        !           992:                } else {
        !           993:                        i_define(D_UCHAR_MAX, "",
        !           994:                                 "UCHAR", "_MAX", (long) char_max,
        !           995:                                 (long) UCHAR_MAX, "");
        !           996:                }
        !           997: 
        !           998:                if (is_signed) {
        !           999: #ifndef NO_UC
        !          1000:                        Volatile unsigned char c, char_max;
        !          1001:                        c=0; char_max=0;
        !          1002:                        c++;
        !          1003:                        if (setjmp(lab)==0) { /* Yields char_max */
        !          1004:                                while (c>char_max) {
        !          1005:                                        char_max=c;
        !          1006:                                        c++;
        !          1007:                                }
        !          1008:                        }
        !          1009:                        Unexpected(4);
        !          1010:                        i_define(D_UCHAR_MAX, "",
        !          1011:                                 "UCHAR", "_MAX", (long) char_max,
        !          1012:                                 (long) UCHAR_MAX, "");
        !          1013: #endif
        !          1014:                } else {
        !          1015: #ifndef NO_SC /* Define NO_SC if the next line gives a syntax error */
        !          1016:                        Volatile signed char c, char_max, char_min;
        !          1017:                        c=0; char_max=0;
        !          1018:                        c++;
        !          1019:                        if (setjmp(lab)==0) { /* Yields char_max */
        !          1020:                                while (c>char_max) {
        !          1021:                                        char_max=c;
        !          1022:                                        c++;
        !          1023:                                }
        !          1024:                        }
        !          1025:                        c=0; char_min=0;
        !          1026:                        c--;
        !          1027:                        if (setjmp(lab)==0) { /* Yields char_min */
        !          1028:                                while (c<char_min) {
        !          1029:                                        char_min=c;
        !          1030:                                        c--;
        !          1031:                                }
        !          1032:                        }
        !          1033:                        Unexpected(5);
        !          1034:                        i_define(D_SCHAR_MIN, "",
        !          1035:                                 "SCHAR", "_MIN", (long) char_min,
        !          1036:                                 (long) SCHAR_MIN, "");
        !          1037:                        i_define(D_SCHAR_MAX, "",
        !          1038:                                 "SCHAR", "_MAX", (long) char_max,
        !          1039:                                 (long) SCHAR_MAX, "");
        !          1040: #endif /* NO_SC */
        !          1041:                }
        !          1042:        }
        !          1043:        return bits_per_byte;
        !          1044: }
        !          1045: 
        !          1046: int basic() {
        !          1047:        /* The properties of the basic types.
        !          1048:           Returns number of bits per sizeof unit */
        !          1049:        Volatile int bits_per_byte;
        !          1050:        struct{char i1; char c1;} schar;
        !          1051:        struct{short i2; char c2;} sshort;
        !          1052:        struct{int i3; char c3;} sint;
        !          1053:        struct{long i4; char c4;} slong;
        !          1054: 
        !          1055:        bits_per_byte= cprop();
        !          1056: 
        !          1057:        /* Shorts, ints and longs *****************************************/
        !          1058:        Vprintf("%sShort=%d int=%d long=%d float=%d double=%d bits %s\n",
        !          1059:                co,
        !          1060:                (int) sizeof(short)*bits_per_byte,
        !          1061:                (int) sizeof(int)*bits_per_byte,
        !          1062:                (int) sizeof(long)*bits_per_byte,
        !          1063:                (int) sizeof(float)*bits_per_byte,
        !          1064:                (int) sizeof(double)*bits_per_byte, oc);
        !          1065:        if (stdc) {
        !          1066:                Vprintf("%sLong double=%d bits%s\n",
        !          1067:                        co, (int) sizeof(Long_double)*bits_per_byte, oc);
        !          1068:        }
        !          1069:        Vprintf("%sChar pointers = %d bits%s%s\n",
        !          1070:                co, (int)sizeof(char *)*bits_per_byte,
        !          1071:                sizeof(char *)>sizeof(int)?" BEWARE! larger than int!":"",
        !          1072:                oc);
        !          1073:        Vprintf("%sInt pointers = %d bits%s%s\n",
        !          1074:                co, (int)sizeof(int *)*bits_per_byte,
        !          1075:                sizeof(int *)>sizeof(int)?" BEWARE! larger than int!":"",
        !          1076:                oc);
        !          1077: 
        !          1078:        /* Alignment constants ********************************************/
        !          1079:        Vprintf("%sAlignments used for char=%ld short=%ld int=%ld long=%ld%s\n",
        !          1080:                co,
        !          1081:                ((long)&schar.c1)-((long)&schar.i1),
        !          1082:                ((long)&sshort.c2)-((long)&sshort.i2),
        !          1083:                ((long)&sint.c3)-((long)&sint.i3),
        !          1084:                ((long)&slong.c4)-((long)&slong.i4),
        !          1085:                oc);
        !          1086: 
        !          1087:        /* Ten little endians *********************************************/
        !          1088: 
        !          1089:        endian(bits_per_byte);
        !          1090: 
        !          1091:        /* Pointers *******************************************************/
        !          1092:        if (V) {
        !          1093:                if ("abcd"=="abcd")
        !          1094:                        printf("%sStrings are shared%s\n", co, oc);
        !          1095:                else printf("%sStrings are not shared%s\n", co, oc);
        !          1096:        }
        !          1097: 
        !          1098:        sprop();
        !          1099:        iprop();
        !          1100:        lprop();
        !          1101:        usprop();
        !          1102:        uiprop();
        !          1103:        ulprop();
        !          1104: 
        !          1105:        Unexpected(6);
        !          1106: 
        !          1107:        return bits_per_byte;
        !          1108: }
        !          1109: 
        !          1110: #else /* not PASS0 */
        !          1111: 
        !          1112: #ifdef SEP
        !          1113: extern jmp_buf lab;
        !          1114: extern int V, L, F, bugs, bits_per_byte;
        !          1115: extern char co[], oc[];
        !          1116: extern char *f_rep();
        !          1117: #endif /* SEP */
        !          1118: #endif /* ifdef PASS0 */
        !          1119: 
        !          1120: /* As I said, I apologise for the contortions below. The functions are
        !          1121:    expanded by the preprocessor twice or three times (for float and double,
        !          1122:    and maybe for long double, and for short, int and long). That way,
        !          1123:    I never make a change to one that I forget to make to the other.
        !          1124:    You can look on it as C's fault for not supporting multi-line macro's.
        !          1125:    This whole file is read 3 times by the preprocessor, with PASSn set for
        !          1126:    n=1, 2 or 3, to decide which parts to reprocess.
        !          1127: */
        !          1128: 
        !          1129: /* #undef on an already undefined thing is (wrongly) flagged as an error
        !          1130:    by some compilers, therefore the #ifdef that follows: 
        !          1131: */
        !          1132: #ifdef Number
        !          1133: #undef Number
        !          1134: #undef THING
        !          1135: #undef Thing
        !          1136: #undef thing
        !          1137: #undef FPROP
        !          1138: #undef Fname
        !          1139: #undef Store
        !          1140: #undef Sum
        !          1141: #undef Diff
        !          1142: #undef Mul
        !          1143: #undef Div
        !          1144: #undef ZERO
        !          1145: #undef HALF
        !          1146: #undef ONE
        !          1147: #undef TWO
        !          1148: #undef THREE
        !          1149: #undef FOUR
        !          1150: #undef Self
        !          1151: #undef F_check
        !          1152: #undef Validate
        !          1153: #undef EPROP
        !          1154: #undef MARK
        !          1155: 
        !          1156: /* These are the float.h constants */
        !          1157: #undef F_RADIX
        !          1158: #undef F_MANT_DIG
        !          1159: #undef F_DIG
        !          1160: #undef F_ROUNDS
        !          1161: #undef F_EPSILON
        !          1162: #undef F_MIN_EXP
        !          1163: #undef F_MIN
        !          1164: #undef F_MIN_10_EXP
        !          1165: #undef F_MAX_EXP
        !          1166: #undef F_MAX
        !          1167: #undef F_MAX_10_EXP
        !          1168: #endif
        !          1169: 
        !          1170: #ifdef Integer
        !          1171: #undef Integer
        !          1172: #undef INT
        !          1173: #undef IPROP
        !          1174: #undef Iname
        !          1175: #undef UPROP
        !          1176: #undef Uname
        !          1177: #undef OK_UI
        !          1178: #undef IMARK
        !          1179: 
        !          1180: #undef I_MAX
        !          1181: #undef I_MIN
        !          1182: #undef U_MAX
        !          1183: #endif
        !          1184: 
        !          1185: #ifdef PASS1
        !          1186: 
        !          1187: /* Define the things we're going to use this pass */
        !          1188: 
        !          1189: #define Number float
        !          1190: #define THING  "FLOAT"
        !          1191: #define Thing  "Float"
        !          1192: #define thing  "float"
        !          1193: #define Fname  "FLT"
        !          1194: #define FPROP  fprop
        !          1195: #define Store  fStore
        !          1196: #define Sum    fSum
        !          1197: #define Diff   fDiff
        !          1198: #define Mul    fMul
        !          1199: #define Div    fDiv
        !          1200: #define ZERO   0.0
        !          1201: #define HALF   0.5
        !          1202: #define ONE    1.0
        !          1203: #define TWO    2.0
        !          1204: #define THREE  3.0
        !          1205: #define FOUR   4.0
        !          1206: #define Self   fSelf
        !          1207: #define F_check        fCheck
        !          1208: #define MARK   "F"
        !          1209: #ifdef VERIFY
        !          1210: #define Validate(prec, val, req, same) fValidate(prec, val, req, same)
        !          1211: #endif
        !          1212: 
        !          1213: #define EPROP  efprop
        !          1214: 
        !          1215: #define Integer        short
        !          1216: #define INT    "short"
        !          1217: #define IPROP  sprop
        !          1218: #define Iname  "SHRT"
        !          1219: #ifndef NO_UI
        !          1220: #define OK_UI 1
        !          1221: #endif
        !          1222: #define IMARK  ""
        !          1223: 
        !          1224: #define UPROP  usprop
        !          1225: #define Uname  "USHRT"
        !          1226: 
        !          1227: #ifdef VERIFY
        !          1228: #ifdef SHRT_MAX
        !          1229: #define I_MAX          SHRT_MAX
        !          1230: #endif
        !          1231: #ifdef SHRT_MIN
        !          1232: #define I_MIN          SHRT_MIN
        !          1233: #endif
        !          1234: #ifdef USHRT_MAX
        !          1235: #define U_MAX          USHRT_MAX
        !          1236: #endif
        !          1237: 
        !          1238: #ifdef FLT_RADIX
        !          1239: #define F_RADIX                FLT_RADIX
        !          1240: #endif
        !          1241: #ifdef FLT_MANT_DIG
        !          1242: #define F_MANT_DIG     FLT_MANT_DIG
        !          1243: #endif
        !          1244: #ifdef FLT_DIG
        !          1245: #define F_DIG          FLT_DIG
        !          1246: #endif
        !          1247: #ifdef FLT_ROUNDS
        !          1248: #define F_ROUNDS       FLT_ROUNDS
        !          1249: #endif
        !          1250: #ifdef FLT_EPSILON
        !          1251: #define F_EPSILON      FLT_EPSILON
        !          1252: #endif
        !          1253: #ifdef FLT_MIN_EXP
        !          1254: #define F_MIN_EXP      FLT_MIN_EXP
        !          1255: #endif
        !          1256: #ifdef FLT_MIN
        !          1257: #define F_MIN          FLT_MIN
        !          1258: #endif
        !          1259: #ifdef FLT_MIN_10_EXP
        !          1260: #define F_MIN_10_EXP   FLT_MIN_10_EXP
        !          1261: #endif
        !          1262: #ifdef FLT_MAX_EXP
        !          1263: #define F_MAX_EXP      FLT_MAX_EXP
        !          1264: #endif
        !          1265: #ifdef FLT_MAX
        !          1266: #define F_MAX          FLT_MAX
        !          1267: #endif
        !          1268: #ifdef FLT_MAX_10_EXP
        !          1269: #define F_MAX_10_EXP   FLT_MAX_10_EXP
        !          1270: #endif
        !          1271: #endif /* VERIFY */
        !          1272: 
        !          1273: #endif /* PASS1 */
        !          1274: 
        !          1275: #ifdef PASS2
        !          1276: 
        !          1277: #define Number double
        !          1278: #define THING  "DOUBLE"
        !          1279: #define Thing  "Double"
        !          1280: #define thing  "double"
        !          1281: #define Fname  "DBL"
        !          1282: #define FPROP  dprop
        !          1283: #define Store  dStore
        !          1284: #define Sum    dSum
        !          1285: #define Diff   dDiff
        !          1286: #define Mul    dMul
        !          1287: #define Div    dDiv
        !          1288: #define ZERO   0.0
        !          1289: #define HALF   0.5
        !          1290: #define ONE    1.0
        !          1291: #define TWO    2.0
        !          1292: #define THREE  3.0
        !          1293: #define FOUR   4.0
        !          1294: #define Self   dSelf
        !          1295: #define F_check        dCheck
        !          1296: #define MARK   ""
        !          1297: #ifdef VERIFY
        !          1298: #define Validate(prec, val, req, same) dValidate(prec, val, req, same)
        !          1299: #endif
        !          1300: 
        !          1301: #define EPROP  edprop
        !          1302: 
        !          1303: #define Integer        int
        !          1304: #define INT    "int"
        !          1305: #define IPROP  iprop
        !          1306: #define Iname  "INT"
        !          1307: #define OK_UI  1 /* Unsigned int is always possible */
        !          1308: #define IMARK  ""
        !          1309: 
        !          1310: #define UPROP  uiprop
        !          1311: #define Uname  "UINT"
        !          1312: 
        !          1313: #ifdef VERIFY
        !          1314: #ifdef INT_MAX
        !          1315: #define I_MAX          INT_MAX
        !          1316: #endif
        !          1317: #ifdef INT_MIN
        !          1318: #define I_MIN          INT_MIN
        !          1319: #endif
        !          1320: #ifdef UINT_MAX
        !          1321: #define U_MAX          UINT_MAX
        !          1322: #endif
        !          1323: 
        !          1324: #ifdef DBL_MANT_DIG
        !          1325: #define F_MANT_DIG     DBL_MANT_DIG
        !          1326: #endif
        !          1327: #ifdef DBL_DIG
        !          1328: #define F_DIG          DBL_DIG
        !          1329: #endif
        !          1330: #ifdef DBL_EPSILON
        !          1331: #define F_EPSILON      DBL_EPSILON
        !          1332: #endif
        !          1333: #ifdef DBL_MIN_EXP
        !          1334: #define F_MIN_EXP      DBL_MIN_EXP
        !          1335: #endif
        !          1336: #ifdef DBL_MIN
        !          1337: #define F_MIN          DBL_MIN
        !          1338: #endif
        !          1339: #ifdef DBL_MIN_10_EXP
        !          1340: #define F_MIN_10_EXP   DBL_MIN_10_EXP
        !          1341: #endif
        !          1342: #ifdef DBL_MAX_EXP
        !          1343: #define F_MAX_EXP      DBL_MAX_EXP
        !          1344: #endif
        !          1345: #ifdef DBL_MAX
        !          1346: #define F_MAX          DBL_MAX
        !          1347: #endif
        !          1348: #ifdef DBL_MAX_10_EXP
        !          1349: #define F_MAX_10_EXP   DBL_MAX_10_EXP
        !          1350: #endif
        !          1351: #endif /* VERIFY */
        !          1352: 
        !          1353: #endif /* PASS2 */
        !          1354: 
        !          1355: #ifdef PASS3
        !          1356: 
        !          1357: #ifdef STDC
        !          1358: #define Number long double
        !          1359: #endif
        !          1360: 
        !          1361: #define THING  "LONG DOUBLE"
        !          1362: #define Thing  "Long double"
        !          1363: #define thing  "long double"
        !          1364: #define Fname  "LDBL"
        !          1365: #define FPROP  ldprop
        !          1366: #define Store  ldStore
        !          1367: #define Sum    ldSum
        !          1368: #define Diff   ldDiff
        !          1369: #define Mul    ldMul
        !          1370: #define Div    ldDiv
        !          1371: #define ZERO   0.0L
        !          1372: #define HALF   0.5L
        !          1373: #define ONE    1.0L
        !          1374: #define TWO    2.0L
        !          1375: #define THREE  3.0L
        !          1376: #define FOUR   4.0L
        !          1377: #define Self   ldSelf
        !          1378: #define F_check        ldCheck
        !          1379: #define MARK   "L"
        !          1380: #ifdef VERIFY
        !          1381: #define Validate(prec, val, req, same) ldValidate(prec, val, req, same)
        !          1382: #endif
        !          1383: 
        !          1384: #define EPROP  eldprop
        !          1385: 
        !          1386: #define Integer        long
        !          1387: #define INT    "long"
        !          1388: #define IPROP  lprop
        !          1389: #define Iname  "LONG"
        !          1390: #ifndef NO_UI
        !          1391: #define OK_UI  1
        !          1392: #endif
        !          1393: #define IMARK  "L"
        !          1394: 
        !          1395: #define UPROP  ulprop
        !          1396: #define Uname  "ULONG"
        !          1397: 
        !          1398: #ifdef VERIFY
        !          1399: #ifdef LONG_MAX
        !          1400: #define I_MAX  LONG_MAX
        !          1401: #endif
        !          1402: #ifdef LONG_MIN
        !          1403: #define I_MIN  LONG_MIN
        !          1404: #endif
        !          1405: #ifdef ULONG_MAX
        !          1406: #define U_MAX  ULONG_MAX
        !          1407: #endif
        !          1408: 
        !          1409: #ifdef LDBL_MANT_DIG
        !          1410: #define F_MANT_DIG     LDBL_MANT_DIG
        !          1411: #endif
        !          1412: #ifdef LDBL_DIG
        !          1413: #define F_DIG          LDBL_DIG
        !          1414: #endif
        !          1415: #ifdef LDBL_EPSILON
        !          1416: #define F_EPSILON      LDBL_EPSILON
        !          1417: #endif
        !          1418: #ifdef LDBL_MIN_EXP
        !          1419: #define F_MIN_EXP      LDBL_MIN_EXP
        !          1420: #endif
        !          1421: #ifdef LDBL_MIN
        !          1422: #define F_MIN          LDBL_MIN
        !          1423: #endif
        !          1424: #ifdef LDBL_MIN_10_EXP
        !          1425: #define F_MIN_10_EXP   LDBL_MIN_10_EXP
        !          1426: #endif
        !          1427: #ifdef LDBL_MAX_EXP
        !          1428: #define F_MAX_EXP      LDBL_MAX_EXP
        !          1429: #endif
        !          1430: #ifdef LDBL_MAX
        !          1431: #define F_MAX          LDBL_MAX
        !          1432: #endif
        !          1433: #ifdef LDBL_MAX_10_EXP
        !          1434: #define F_MAX_10_EXP   LDBL_MAX_10_EXP
        !          1435: #endif
        !          1436: #endif /* VERIFY */
        !          1437: 
        !          1438: #endif /* PASS3 */
        !          1439: 
        !          1440: #ifndef I_MAX
        !          1441: #define I_MAX  int_max
        !          1442: #endif
        !          1443: #ifndef I_MIN
        !          1444: #define I_MIN  int_min
        !          1445: #endif
        !          1446: #ifndef U_MAX
        !          1447: #define U_MAX  int_max
        !          1448: #endif
        !          1449: 
        !          1450: #ifndef F_RADIX
        !          1451: #define F_RADIX                f_radix
        !          1452: #endif
        !          1453: #ifndef F_MANT_DIG
        !          1454: #define F_MANT_DIG     f_mant_dig
        !          1455: #endif
        !          1456: #ifndef F_DIG
        !          1457: #define F_DIG          f_dig
        !          1458: #endif
        !          1459: #ifndef F_ROUNDS
        !          1460: #define F_ROUNDS       f_rounds
        !          1461: #endif
        !          1462: #ifndef F_EPSILON
        !          1463: #define F_EPSILON      f_epsilon
        !          1464: #endif
        !          1465: #ifndef F_MIN_EXP
        !          1466: #define F_MIN_EXP      f_min_exp
        !          1467: #endif
        !          1468: #ifndef F_MIN
        !          1469: #define F_MIN          f_min
        !          1470: #endif
        !          1471: #ifndef F_MIN_10_EXP
        !          1472: #define F_MIN_10_EXP   f_min_10_exp
        !          1473: #endif
        !          1474: #ifndef F_MAX_EXP
        !          1475: #define F_MAX_EXP      f_max_exp
        !          1476: #endif
        !          1477: #ifndef F_MAX
        !          1478: #define F_MAX          f_max
        !          1479: #endif
        !          1480: #ifndef F_MAX_10_EXP
        !          1481: #define F_MAX_10_EXP   f_max_10_exp
        !          1482: #endif
        !          1483: 
        !          1484: #ifndef VERIFY
        !          1485: #define Validate(prec, val, req, same) {;}
        !          1486: #endif
        !          1487: 
        !          1488: #ifdef Integer
        !          1489: 
        !          1490: Procedure IPROP() {
        !          1491:        /* the properties of short, int, and long */
        !          1492:        Volatile Integer newi, int_max, maxeri, int_min, minneri;
        !          1493:        Volatile int ibits, ipower, two=2;
        !          1494: 
        !          1495:        /* Calculate max short/int/long ***********************************/
        !          1496:        /* Calculate 2**n-1 until overflow - then use the previous value  */
        !          1497: 
        !          1498:        newi=1; int_max=0;
        !          1499: 
        !          1500:        if (setjmp(lab)==0) { /* Yields int_max */
        !          1501:                for(ipower=0; newi>int_max; ipower++) {
        !          1502:                        int_max=newi;
        !          1503:                        newi=newi*two+1;
        !          1504:                }
        !          1505:                Vprintf("%sOverflow of a%s %s does not generate a trap%s\n",
        !          1506:                        co, INT[0]=='i'?"n":"", INT, oc);
        !          1507:        } else {
        !          1508:                Vprintf("%sOverflow of a%s %s generates a trap%s\n",
        !          1509:                        co, INT[0]=='i'?"n":"", INT, oc);
        !          1510:        }
        !          1511:        Unexpected(7);
        !          1512: 
        !          1513:        /* Minimum value: assume either two's or one's complement *********/
        !          1514:        int_min= -int_max;
        !          1515:        if (setjmp(lab)==0) { /* Yields int_min */
        !          1516:                if (int_min-1 < int_min) int_min--;
        !          1517:        }
        !          1518:        Unexpected(8);
        !          1519: 
        !          1520:        /* Now for those daft Cybers: */
        !          1521: 
        !          1522:        maxeri=0; newi=int_max;
        !          1523: 
        !          1524:        if (setjmp(lab)==0) { /* Yields maxeri */
        !          1525:                for(ibits=ipower; newi>maxeri; ibits++) {
        !          1526:                        maxeri=newi;
        !          1527:                        newi=newi+newi+1;
        !          1528:                }
        !          1529:        }
        !          1530:        Unexpected(9);
        !          1531: 
        !          1532:        minneri= -maxeri;
        !          1533:        if (setjmp(lab)==0) { /* Yields minneri */
        !          1534:                if (minneri-1 < minneri) minneri--;
        !          1535:        }
        !          1536:        Unexpected(10);
        !          1537: 
        !          1538:        Vprintf("%sMaximum %s = %ld (= 2**%d-1)%s\n",
        !          1539:                co, INT, (long)int_max, ipower, oc);
        !          1540:        Vprintf("%sMinimum %s = %ld%s\n", co, INT, (long)int_min, oc);
        !          1541: 
        !          1542:        if (L) i_define(D_INT_MAX, INT,
        !          1543:                        Iname, "_MAX", (long) int_max, (long) I_MAX, IMARK);
        !          1544:        if (L) i_define(D_INT_MIN, INT,
        !          1545:                        Iname, "_MIN", (long) int_min, (long) I_MIN, IMARK);
        !          1546: 
        !          1547:        if (maxeri>int_max) {
        !          1548:                Vprintf("%sThere is a larger %s, %ld (= 2**%d-1), %s %s%s\n",
        !          1549:                        co, INT, (long)maxeri, ibits, 
        !          1550:                        "but only for addition, not multiplication",
        !          1551:                        "(I smell a Cyber!)",
        !          1552:                        oc);
        !          1553:        }
        !          1554: 
        !          1555:        if (minneri<int_min) {
        !          1556:                Vprintf("%sThere is a smaller %s, %ld, %s %s%s\n",
        !          1557:                        co, INT, (long)minneri, 
        !          1558:                        "but only for addition, not multiplication",
        !          1559:                        "(I smell a Cyber!)",
        !          1560:                        oc);
        !          1561:        }
        !          1562: }
        !          1563: 
        !          1564: Procedure UPROP () {
        !          1565:        /* The properties of unsigned short/int/long */
        !          1566: #ifdef OK_UI
        !          1567:        Volatile unsigned Integer int_max, newi, two;
        !          1568:        newi=1; int_max=0; two=2;
        !          1569: 
        !          1570:        if (setjmp(lab)==0) { /* Yields int_max */
        !          1571:                while(newi>int_max) {
        !          1572:                        int_max=newi;
        !          1573:                        newi=newi*two+1;
        !          1574:                }
        !          1575:        }
        !          1576:        Unexpected(11);
        !          1577:        Vprintf("%sMaximum unsigned %s = %lu%s\n",
        !          1578:                co, INT, (unsigned long) int_max, oc);
        !          1579:        if (L) u_define(D_UINT_MAX, INT,
        !          1580:                        Uname, "_MAX", (unsigned long) int_max,
        !          1581:                        (unsigned long) U_MAX, IMARK);
        !          1582: #endif
        !          1583: }
        !          1584: 
        !          1585: #endif /* Integer */
        !          1586: 
        !          1587: #ifdef Number
        !          1588: 
        !          1589: /* The following routines are intended to defeat any attempt at optimisation
        !          1590:    or use of extended precision, and to defeat faulty narrowing casts.
        !          1591:    The weird prototypes are because of widening incompatibilities.
        !          1592: */
        !          1593: #ifdef STDC
        !          1594: #define ARGS1(atype, a) (atype a)
        !          1595: #define ARGS2(atype, a, btype, b) (atype a, btype b)
        !          1596: #else
        !          1597: #define ARGS1(atype, a) (a) atype a;
        !          1598: #define ARGS2(atype, a, btype, b) (a, b) atype a; btype b;
        !          1599: #endif
        !          1600: 
        !          1601: Procedure Store ARGS2(Number, a, Number *, b) { *b=a; }
        !          1602: Number Sum ARGS2(Number, a, Number, b) {Number r; Store(a+b, &r); return (r); }
        !          1603: Number Diff ARGS2(Number, a, Number, b){Number r; Store(a-b, &r); return (r); }
        !          1604: Number Mul ARGS2(Number, a, Number, b) {Number r; Store(a*b, &r); return (r); }
        !          1605: Number Div ARGS2(Number, a, Number, b) {Number r; Store(a/b, &r); return (r); }
        !          1606: Number Self ARGS1(Number, a)          {Number r; Store(a,   &r); return (r); }
        !          1607: 
        !          1608: Procedure F_check ARGS((int precision, Long_double val1));
        !          1609: 
        !          1610: Procedure F_check(precision, val1) int precision; Long_double val1; {
        !          1611:        /* You don't think I'm going to go to all the trouble of writing
        !          1612:           a program that works out what all sorts of values are, only to
        !          1613:           have printf go and print the wrong values out, do you?
        !          1614:           No, you're right, so this function tries to see if printf
        !          1615:           has written the right value, by reading it back again.
        !          1616:           This introduces a new problem of course: suppose printf writes
        !          1617:           the correct value, and scanf reads it back wrong... oh well.
        !          1618:           But I'm adamant about this: the precision given is enough
        !          1619:           to uniquely identify the printed number, therefore I insist
        !          1620:           that sscanf read the number back identically. Harsh yes, but
        !          1621:           sometimes you've got to be cruel to be kind.
        !          1622:        */
        !          1623:        Long_double new1;
        !          1624:        Number val, new, diff;
        !          1625:        double rem;
        !          1626:        int e;
        !          1627:        char *rep;
        !          1628:        char *f2;
        !          1629: 
        !          1630:        if (sizeof(double) == sizeof(Long_double)) {
        !          1631:                /* Assume they're the same, and use non-stdc format */
        !          1632:                /* This is for stdc compilers using non-stdc libraries */
        !          1633:                f2= "%le";   /* Input */
        !          1634:        } else {
        !          1635:                /* It had better support Le then */
        !          1636:                f2= "%Le";
        !          1637:        }
        !          1638:        val= val1;
        !          1639:        rep= f_rep(precision, (Long_double) val);
        !          1640:        if (setjmp(lab)==0) {
        !          1641:                sscanf(rep, f2, &new1);
        !          1642:        } else {
        !          1643:                eek_a_bug("sscanf caused a trap");
        !          1644:                printf("%s    scanning: %s format: %s%s\n\n", co, rep, f2, oc);
        !          1645:                Unexpected(12);
        !          1646:                return;
        !          1647:        }
        !          1648: 
        !          1649:        if (setjmp(lab)==0) { /* See if new is usable */
        !          1650:                new= new1;
        !          1651:                if (new != 0.0) {
        !          1652:                        diff= val/new - 1.0;
        !          1653:                        if (diff < 0.1) diff= 1.0;
        !          1654:                        /* That should be enough to generate a trap */
        !          1655:                }
        !          1656:        } else {
        !          1657:                eek_a_bug("sscanf returned an unusable number");
        !          1658:                printf("%s    scanning: %s with format: %s%s\n\n",
        !          1659:                       co, rep, f2, oc);
        !          1660:                Unexpected(13);
        !          1661:                return;
        !          1662:        }
        !          1663: 
        !          1664:        Unexpected(14);
        !          1665:        if (new != val) {
        !          1666:                eek_a_bug("Possibly bad output from printf above");
        !          1667:                if (!exponent((Long_double)val, &rem, &e)) {
        !          1668:                        printf("%s    but value was an unusable number%s\n\n",
        !          1669:                               co, oc);
        !          1670:                        return;
        !          1671:                }
        !          1672:                printf("%s    expected value around %.*fe%d, bit pattern:\n    ",
        !          1673:                       co, precision, rem, e);
        !          1674:                bitpattern((char *) &val, sizeof(val));
        !          1675:                printf ("%s\n", oc);
        !          1676:                printf("%s    sscanf gave           %s, bit pattern:\n    ",
        !          1677:                       co, f_rep(precision, (Long_double) new));
        !          1678:                bitpattern((char *) &new, sizeof(new));
        !          1679:                printf ("%s\n", oc);
        !          1680:                if (setjmp(lab) == 0) {
        !          1681:                        diff= val-new;
        !          1682:                        printf("%s    difference= %s%s\n\n", 
        !          1683:                               co, f_rep(precision, (Long_double) diff), oc);
        !          1684:                } /* else forget it */
        !          1685:                Unexpected(15);
        !          1686:        }
        !          1687: }
        !          1688: 
        !          1689: #ifdef VERIFY
        !          1690: Procedure Validate(prec, val, req, same) int prec, same; Long_double val, req; {
        !          1691:        /* Check that the compiler has read a #define value correctly */
        !          1692:        Unexpected(16);
        !          1693:        if (!same) {
        !          1694:                printf("%s*** Verify failed for above #define!\n", co);
        !          1695:                if (setjmp(lab) == 0) { /* for the case that req == nan */
        !          1696:                        printf("       Compiler has %s for value%s\n", 
        !          1697:                               f_rep(prec, req), oc);
        !          1698:                } else {
        !          1699:                        printf("       Compiler has %s for value%s\n",
        !          1700:                               "an unusable number", oc);
        !          1701:                }
        !          1702:                if (setjmp(lab) == 0) {
        !          1703:                        F_check(prec, (Long_double) req);
        !          1704:                } /*else forget it*/
        !          1705:                if (setjmp(lab) == 0) {         
        !          1706:                        if (req > 0.0 && val > 0.0) {
        !          1707:                                printf("%s    difference= %s%s\n",
        !          1708:                                       co, f_rep(prec, val-req), oc);
        !          1709:                        }
        !          1710:                } /*else forget it*/
        !          1711:                Unexpected(17);
        !          1712:                printf("\n");
        !          1713:                bugs++;
        !          1714:        } else if (val != req) {
        !          1715:                if (stdc) {
        !          1716:                        printf("%s*** Verify failed for above #define!\n", co);
        !          1717:                        printf("       Constant has the wrong precision%s\n",
        !          1718:                               oc);
        !          1719:                } else eek_a_bug("the cast didn't work");
        !          1720:                printf("\n");
        !          1721:                bugs++;
        !          1722:        }
        !          1723: }
        !          1724: #endif /* VERIFY */
        !          1725: 
        !          1726: int FPROP(bits_per_byte) int bits_per_byte; {
        !          1727:        /* Properties of floating types, using algorithms by Cody and Waite
        !          1728:           from MA Malcolm, as modified by WM Gentleman and SB Marovich.
        !          1729:           Further extended by S Pemberton.
        !          1730: 
        !          1731:           Returns the number of digits in the fraction.
        !          1732:        */
        !          1733: 
        !          1734:        Volatile int
        !          1735:                i, f_radix, iexp, irnd, mrnd, f_rounds, f_mant_dig,
        !          1736:                iz, k, inf, machep, f_max_exp, f_min_exp, mx, negeps,
        !          1737:                mantbits, digs, f_dig, trap,
        !          1738:                hidden, normal, f_min_10_exp, f_max_10_exp;
        !          1739:        Volatile Number
        !          1740:                a, b, base, basein, basem1, f_epsilon, epsneg,
        !          1741:                eps, epsp1, etop, ebot,
        !          1742:                f_max, newxmax, f_min, xminner, y, y1, z, z1, z2;
        !          1743: 
        !          1744:        Unexpected(18);
        !          1745: 
        !          1746:        Vprintf("%sPROPERTIES OF %s:%s\n", co, THING, oc);
        !          1747: 
        !          1748:        /* Base and size of mantissa **************************************/
        !          1749:        /* First repeatedly double until adding 1 has no effect.          */
        !          1750:        /* For instance, if base is 10, with 3 significant digits         */
        !          1751:        /* it will try 1, 2, 4, 8, ... 512, 1024, and stop there,         */
        !          1752:        /* since 1024 is only representable as 1020.                      */
        !          1753:        a=1.0;
        !          1754:        if (setjmp(lab)==0) { /* inexact trap? */
        !          1755:                do { a=Sum(a, a); }
        !          1756:                while (Diff(Diff(Sum(a, ONE), a), ONE) == ZERO);
        !          1757:        } else {
        !          1758:                fprintf(stderr, "*** Program got loss-of-precision trap!\n");
        !          1759:                /* And supporting those is just TOO much trouble! */
        !          1760:                farewell(bugs+1);
        !          1761:        }
        !          1762:        Unexpected(19);
        !          1763:        /* Now double until you find a number that can be added to the    */
        !          1764:        /* above number. For 1020 this is 8 or 16, depending whether the  */
        !          1765:        /* result is rounded or truncated.                                */
        !          1766:        /* In either case the result is 1030. 1030-1020= the base, 10.    */
        !          1767:        b=1.0;
        !          1768:        do { b=Sum(b, b); } while ((base=Diff(Sum(a, b), a)) == ZERO);
        !          1769:        f_radix=base;
        !          1770:        Vprintf("%sBase = %d%s\n", co, f_radix, oc);
        !          1771: 
        !          1772:        /* Sanity check; if base<2, I can't guarantee the rest will work  */
        !          1773:        if (f_radix < 2) {
        !          1774:                eek_a_bug("Function return or parameter passing faulty? (This is a guess.)");
        !          1775:                printf("\n");
        !          1776:                return(0);
        !          1777:        }
        !          1778: 
        !          1779: #ifdef PASS1 /* only for FLT */
        !          1780:        flt_radix= f_radix;
        !          1781:        if (F) i_define(D_FLT_RADIX, "",
        !          1782:                        "FLT", "_RADIX", (long) f_radix, (long) F_RADIX, "");
        !          1783: #else
        !          1784:        if (f_radix != flt_radix) {
        !          1785:                printf("\n%s*** WARNING: %s %s (%d) %s%s\n",
        !          1786:                       co, thing, "arithmetic has a different radix",
        !          1787:                       f_radix, "from float", oc);
        !          1788:                bugs++;
        !          1789:        }
        !          1790: #endif
        !          1791: 
        !          1792:        /* Now the number of digits precision: */
        !          1793:        f_mant_dig=0; b=1.0;
        !          1794:        do { f_mant_dig++; b=Mul(b, base); }
        !          1795:        while (Diff(Diff(Sum(b, ONE), b), ONE) == ZERO);
        !          1796:        f_dig=floor_log(10, (Long_double)(b/base)) + (base==10?1:0);
        !          1797:        Vprintf("%sSignificant base digits = %d %s %d %s%s\n",
        !          1798:                co, f_mant_dig, "(= at least", f_dig, "decimal digits)", oc);
        !          1799:        if (F) i_define(D_MANT_DIG, thing,
        !          1800:                        Fname, "_MANT_DIG", (long) f_mant_dig,
        !          1801:                        (long) F_MANT_DIG, "");
        !          1802:        if (F) i_define(D_DIG, thing,
        !          1803:                        Fname, "_DIG", (long) f_dig, (long) F_DIG, "");
        !          1804:        digs= ceil_log(10, (Long_double)b); /* the number of digits to printf */
        !          1805: 
        !          1806:        /* Rounding *******************************************************/
        !          1807:        basem1=Diff(base, HALF);
        !          1808:        if (Diff(Sum(a, basem1), a) != ZERO) {
        !          1809:                if (f_radix == 2) basem1=0.375;
        !          1810:                else basem1=1.0;
        !          1811:                if (Diff(Sum(a, basem1), a) != ZERO) irnd=2; /* away from 0 */
        !          1812:                else irnd=1; /* to nearest */
        !          1813:        } else irnd=0; /* towards 0 */
        !          1814: 
        !          1815:        basem1=Diff(base, HALF);
        !          1816: 
        !          1817:        if (Diff(Diff(-a, basem1), -a) != ZERO) {
        !          1818:                if (f_radix == 2) basem1=0.375;
        !          1819:                else basem1=1.0;
        !          1820:                if (Diff(Diff(-a, basem1), -a) != ZERO) mrnd=2; /* away from 0*/
        !          1821:                else mrnd=1; /* to nearest */
        !          1822:        } else mrnd=0; /* towards 0 */
        !          1823: 
        !          1824:        f_rounds= -1; /* Unknown rounding */
        !          1825:        if (irnd==0 && mrnd==0) f_rounds=0; /* zero = chops */
        !          1826:        if (irnd==1 && mrnd==1) f_rounds=1; /* nearest */
        !          1827:        if (irnd==2 && mrnd==0) f_rounds=2; /* +inf */
        !          1828:        if (irnd==0 && mrnd==2) f_rounds=3; /* -inf */
        !          1829: 
        !          1830:        if (f_rounds != -1) {
        !          1831:                Vprintf("%sArithmetic rounds towards ", co);
        !          1832:                switch (f_rounds) {
        !          1833:                      case 0: Vprintf("zero (i.e. it chops)"); break;
        !          1834:                      case 1: Vprintf("nearest"); break;
        !          1835:                      case 2: Vprintf("+infinity"); break;
        !          1836:                      case 3: Vprintf("-infinity"); break;
        !          1837:                      default: Vprintf("???"); break;
        !          1838:                }
        !          1839:                Vprintf("%s\n", oc);
        !          1840:        } else { /* Hmm, try to give some help here: */
        !          1841:                Vprintf("%sArithmetic rounds oddly: %s\n", co, oc);
        !          1842:                Vprintf("%s    Negative numbers %s%s\n",
        !          1843:                        co, mrnd==0 ? "towards zero" :
        !          1844:                            mrnd==1 ? "to nearest" :
        !          1845:                                      "away from zero",
        !          1846:                        oc);
        !          1847:                Vprintf("%s    Positive numbers %s%s\n",
        !          1848:                        co, irnd==0 ? "towards zero" :
        !          1849:                            irnd==1 ? "to nearest" :
        !          1850:                                      "away from zero",
        !          1851:                        oc);
        !          1852:        }
        !          1853:        /* An extra goody */
        !          1854:        if (f_radix == 2 && f_rounds == 1) {
        !          1855:                if (Diff(Sum(a, ONE), a) != ZERO) {
        !          1856:                        Vprintf("%s   Tie breaking rounds up%s\n", co, oc);
        !          1857:                } else if (Diff(Sum(a, THREE), a) == FOUR) {
        !          1858:                        Vprintf("%s   Tie breaking rounds to even%s\n", co, oc);
        !          1859:                } else {
        !          1860:                        Vprintf("%s   Tie breaking rounds down%s\n", co, oc);
        !          1861:                }
        !          1862:        }
        !          1863: #ifdef PASS1 /* only for FLT */
        !          1864:        flt_rounds= f_rounds;
        !          1865:        if (F)
        !          1866:          i_define(D_FLT_ROUNDS, "",
        !          1867:                   "FLT", "_ROUNDS", (long) f_rounds, (long) F_ROUNDS, "");
        !          1868: #else
        !          1869:        if (f_rounds != flt_rounds) {
        !          1870:                printf("\n%s*** WARNING: %s %s (%d) %s%s\n",
        !          1871:                       co, thing, "arithmetic rounds differently",
        !          1872:                       f_rounds, "from float", oc);
        !          1873:                bugs++;
        !          1874:        }
        !          1875: #endif
        !          1876: 
        !          1877:        /* Various flavours of epsilon ************************************/
        !          1878:        negeps=f_mant_dig+f_mant_dig;
        !          1879:        basein=1.0/base;
        !          1880:        a=1.0;
        !          1881:        for(i=1; i<=negeps; i++) a*=basein;
        !          1882: 
        !          1883:        b=a;
        !          1884:        while (Diff(Diff(ONE, a), ONE) == ZERO) {
        !          1885:                a*=base;
        !          1886:                negeps--;
        !          1887:        }
        !          1888:        negeps= -negeps;
        !          1889:        Vprintf("%sSmallest x such that 1.0-base**x != 1.0 = %d%s\n",
        !          1890:                co, negeps, oc);
        !          1891: 
        !          1892:        etop = ONE;
        !          1893:        ebot = ZERO;
        !          1894:        eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
        !          1895:        while (eps != ebot && eps != etop) {
        !          1896:                epsp1 = Diff(ONE, eps);
        !          1897:                if (epsp1 < ONE) etop = eps;
        !          1898:                else ebot = eps;
        !          1899:                eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
        !          1900:        }
        !          1901:        /* Sanity check */
        !          1902:        if (Diff(ONE, etop) >= ONE || Diff(ONE, ebot) != ONE) {
        !          1903:                eek_a_bug("internal error calculating epsneg");
        !          1904:        }
        !          1905:        Vprintf("%sSmallest x such that 1.0-x != 1.0 = %s%s\n",
        !          1906:                co, f_rep(digs, (Long_double) eps), oc);
        !          1907:        if (V) F_check(digs, (Long_double) eps);
        !          1908: 
        !          1909:        epsneg=a;
        !          1910:        if ((f_radix!=2) && irnd) {
        !          1911:        /*      a=(a*(1.0+a))/(1.0+1.0); => */
        !          1912:                a=Div(Mul(a, Sum(ONE, a)), Sum(ONE, ONE));
        !          1913:        /*      if ((1.0-a)-1.0 != 0.0) epsneg=a; => */
        !          1914:                if (Diff(Diff(ONE, a), ONE) != ZERO) epsneg=a;
        !          1915:        }
        !          1916:        /* epsneg is used later */
        !          1917:        Unexpected(20);
        !          1918: 
        !          1919:        machep= -f_mant_dig-f_mant_dig;
        !          1920:        a=b;
        !          1921:        while (Diff(Sum(ONE, a), ONE) == ZERO) { a*=base; machep++; }
        !          1922:        Vprintf("%sSmallest x such that 1.0+base**x != 1.0 = %d%s\n",
        !          1923:                co, machep, oc);
        !          1924: 
        !          1925:        etop = ONE;
        !          1926:        ebot = ZERO;
        !          1927:        eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
        !          1928:        while (eps != ebot && eps != etop) {
        !          1929:                epsp1 = Sum(ONE, eps);
        !          1930:                if (epsp1 > ONE) etop = eps;
        !          1931:                else ebot = eps;
        !          1932:                eps = Sum(ebot, Div(Diff(etop, ebot), TWO));
        !          1933:        }
        !          1934:        /* Sanity check */
        !          1935:        if (Sum(ONE, etop) <= ONE || Sum(ONE, ebot) != ONE) {
        !          1936:                eek_a_bug("internal error calculating eps");
        !          1937:        }
        !          1938:        f_epsilon=etop;
        !          1939: 
        !          1940:        Vprintf("%sSmallest x such that 1.0+x != 1.0 = %s%s\n",
        !          1941:                co, f_rep(digs, (Long_double) f_epsilon), oc);
        !          1942:        /* Possible loss of precision warnings here from non-stdc compilers: */
        !          1943:        if (F) f_define(D_EPSILON, thing,
        !          1944:                        Fname, "_EPSILON", digs, (Long_double) f_epsilon, MARK);
        !          1945:        if (V || F) F_check(digs, (Long_double) f_epsilon);
        !          1946:        Unexpected(21);
        !          1947:        if (F) Validate(digs, (Long_double) f_epsilon, (Long_double) F_EPSILON,
        !          1948:                        f_epsilon == Self(F_EPSILON));
        !          1949:        Unexpected(22);
        !          1950: 
        !          1951:        /* Extra chop info *************************************************/
        !          1952:        if (f_rounds == 0) {
        !          1953:                if (Diff(Mul(Sum(ONE,f_epsilon),ONE),ONE) !=  ZERO) {
        !          1954:                        Vprintf("%sAlthough arithmetic chops, it uses guard digits%s\n", co, oc);
        !          1955:                }
        !          1956:        }
        !          1957: 
        !          1958:        /* Size of and minimum normalised exponent ************************/
        !          1959:        y=0; i=0; k=1; z=basein; z1=(1.0+f_epsilon)/base;
        !          1960: 
        !          1961:        /* Coarse search for the largest power of two */
        !          1962:        if (setjmp(lab)==0) { /* for underflow trap */ /* Yields i, k, y, y1 */
        !          1963:                do {
        !          1964:                        y=z; y1=z1;
        !          1965:                        z=Mul(y,y); z1=Mul(z1, y);
        !          1966:                        a=Mul(z,ONE);
        !          1967:                        z2=Div(z1,y);
        !          1968:                        if (z2 != y1) break;
        !          1969:                        if ((Sum(a,a) == ZERO) || (fabs(z) >= y)) break;
        !          1970:                        i++;
        !          1971:                        k+=k;
        !          1972:                } while(1);
        !          1973:        } else {
        !          1974:                Vprintf("%s%s underflow generates a trap%s\n", co, Thing, oc);
        !          1975:        }
        !          1976:        Unexpected(23);
        !          1977: 
        !          1978:        if (f_radix != 10) {
        !          1979:                iexp=i+1; /* for the sign */
        !          1980:                mx=k+k;
        !          1981:        } else {
        !          1982:                iexp=2;
        !          1983:                iz=f_radix;
        !          1984:                while (k >= iz) { iz*=f_radix; iexp++; }
        !          1985:                mx=iz+iz-1;
        !          1986:        }
        !          1987: 
        !          1988:        /* Fine tune starting with y and y1 */
        !          1989:        if (setjmp(lab)==0) { /* for underflow trap */ /* Yields k, f_min */
        !          1990:                do {
        !          1991:                        f_min=y; z1=y1;
        !          1992:                        y=Div(y,base); y1=Div(y1,base);
        !          1993:                        a=Mul(y,ONE);
        !          1994:                        z2=Mul(y1,base);
        !          1995:                        if (z2 != z1) break;
        !          1996:                        if ((Sum(a,a) == ZERO) || (fabs(y) >= f_min)) break;
        !          1997:                        k++;
        !          1998:                } while (1);
        !          1999:        }
        !          2000:        Unexpected(24);
        !          2001: 
        !          2002:        f_min_exp=(-k)+1;
        !          2003: 
        !          2004:        if ((mx <= k+k-3) && (f_radix != 10)) { mx+=mx; iexp+=1; }
        !          2005:        Vprintf("%sNumber of bits used for exponent = %d%s\n", co, iexp, oc);
        !          2006:        Vprintf("%sMinimum normalised exponent = %d%s\n", co, f_min_exp, oc);
        !          2007:        if (F)
        !          2008:          i_define(D_MIN_EXP, thing,
        !          2009:                   Fname, "_MIN_EXP", (long) f_min_exp, (long) F_MIN_EXP, "");
        !          2010: 
        !          2011:        if (setjmp(lab)==0) {
        !          2012:                Vprintf("%sMinimum normalised positive number = %s%s\n",
        !          2013:                        co, f_rep(digs, (Long_double) f_min), oc);
        !          2014:        } else {
        !          2015:                eek_a_bug("printf can't print the smallest normalised number");
        !          2016:                printf("\n");
        !          2017:        }
        !          2018:        Unexpected(25);
        !          2019:        /* Possible loss of precision warnings here from non-stdc compilers: */
        !          2020:        if (setjmp(lab) == 0) {
        !          2021:                if (F) f_define(D_MIN, thing,
        !          2022:                                Fname, "_MIN", digs, (Long_double) f_min, MARK);
        !          2023:                if (V || F) F_check(digs, (Long_double) f_min);
        !          2024:        } else {
        !          2025:                eek_a_bug("xxx_MIN caused a trap");
        !          2026:                printf("\n");
        !          2027:        }
        !          2028: 
        !          2029:        if (setjmp(lab) == 0) {
        !          2030:                if (F) Validate(digs, (Long_double) f_min, (Long_double) F_MIN,
        !          2031:                                f_min == Self(F_MIN));
        !          2032:        } else {
        !          2033:                printf("%s*** Verify failed for above #define!\n    %s %s\n\n",
        !          2034:                       co, "Compiler has an unusable number for value", oc);
        !          2035:                bugs++;
        !          2036:        }
        !          2037:        Unexpected(26);
        !          2038: 
        !          2039:        a=1.0; f_min_10_exp=0;
        !          2040:        while (a > f_min*10.0) { a/=10.0; f_min_10_exp--; }
        !          2041:        if (F) i_define(D_MIN_10_EXP, thing,
        !          2042:                        Fname, "_MIN_10_EXP", (long) f_min_10_exp,
        !          2043:                        (long) F_MIN_10_EXP, "");
        !          2044: 
        !          2045:        /* Minimum exponent ************************************************/
        !          2046:        if (setjmp(lab)==0) { /* for underflow trap */ /* Yields xminner */
        !          2047:                do {
        !          2048:                        xminner=y;
        !          2049:                        y=Div(y,base);
        !          2050:                        a=Mul(y,ONE);
        !          2051:                        if ((Sum(a,a) == ZERO) || (fabs(y) >= xminner)) break;
        !          2052:                } while (1);
        !          2053:        }
        !          2054:        Unexpected(27);
        !          2055: 
        !          2056:        if (xminner != 0.0 && xminner != f_min) {
        !          2057:                normal= 0;
        !          2058:                Vprintf("%sThe smallest numbers are not kept normalised%s\n",
        !          2059:                        co, oc);
        !          2060:                if (setjmp(lab)==0) {
        !          2061:                    Vprintf("%sSmallest unnormalised positive number = %s%s\n",
        !          2062:                            co, f_rep(digs, (Long_double) xminner), oc);
        !          2063:                    if (V) F_check(digs, (Long_double) xminner);
        !          2064:                } else {
        !          2065:                        eek_a_bug("printf can't print the smallest unnormalised number.");
        !          2066:                        printf("\n");
        !          2067:                }
        !          2068:                Unexpected(28);
        !          2069:        } else {
        !          2070:                normal= 1;
        !          2071:                Vprintf("%sThe smallest numbers are normalised%s\n", co, oc);
        !          2072:        }
        !          2073: 
        !          2074:        /* Maximum exponent ************************************************/
        !          2075:        f_max_exp=2; f_max=1.0; newxmax=base+1.0;
        !          2076:        inf=0; trap=0;
        !          2077:        while (f_max<newxmax) {
        !          2078:                f_max=newxmax;
        !          2079:                if (setjmp(lab) == 0) { /* Yields inf, f_max_exp */
        !          2080:                        newxmax=Mul(newxmax, base);
        !          2081:                } else {
        !          2082:                        trap=1;
        !          2083:                        break;
        !          2084:                }
        !          2085:                if (Div(newxmax, base) != f_max) {
        !          2086:                        inf=1; /* ieee infinity */
        !          2087:                        break;
        !          2088:                }
        !          2089:                f_max_exp++;
        !          2090:        }
        !          2091:        Unexpected(29);
        !          2092:        if (trap) {
        !          2093:                Vprintf("%s%s overflow generates a trap%s\n", co, Thing, oc);
        !          2094:        }
        !          2095: 
        !          2096:        if (inf) Vprintf("%sThere is an 'infinite' value%s\n", co, oc);
        !          2097:        Vprintf("%sMaximum exponent = %d%s\n", co, f_max_exp, oc);
        !          2098:        if (F) i_define(D_MAX_EXP, thing,
        !          2099:                        Fname, "_MAX_EXP", (long) f_max_exp,
        !          2100:                        (long) F_MAX_EXP, "");
        !          2101: 
        !          2102:        /* Largest number ***************************************************/
        !          2103:        f_max=Diff(ONE, epsneg);
        !          2104:        if (Mul(f_max,ONE) != f_max) f_max=Diff(ONE, Mul(base,epsneg));
        !          2105:        for (i=1; i<=f_max_exp; i++) f_max=Mul(f_max, base);
        !          2106: 
        !          2107:        if (setjmp(lab)==0) {
        !          2108:                Vprintf("%sMaximum number = %s%s\n",
        !          2109:                        co, f_rep(digs, (Long_double) f_max), oc);
        !          2110:        } else {
        !          2111:                eek_a_bug("printf can't print the largest double.");
        !          2112:                printf("\n");
        !          2113:        }
        !          2114:        if (setjmp(lab)==0) {
        !          2115:        /* Possible loss of precision warnings here from non-stdc compilers: */
        !          2116:                if (F) f_define(D_MAX, thing,
        !          2117:                                Fname, "_MAX", digs, (Long_double) f_max, MARK);
        !          2118:                if (V || F) F_check(digs, (Long_double) f_max);
        !          2119:        } else {
        !          2120:                eek_a_bug("xxx_MAX caused a trap");
        !          2121:                printf("\n");
        !          2122:        }
        !          2123:        if (setjmp(lab)==0) {
        !          2124:                if (F) Validate(digs, (Long_double) f_max, (Long_double) F_MAX,
        !          2125:                                f_max == Self(F_MAX));
        !          2126:        } else {
        !          2127:                printf("%s*** Verify failed for above #define!\n    %s %s\n\n",
        !          2128:                       co, "Compiler has an unusable number for value", oc);
        !          2129:                bugs++;
        !          2130:        }
        !          2131:        Unexpected(30);
        !          2132: 
        !          2133:        a=1.0; f_max_10_exp=0;
        !          2134:        while (a < f_max/10.0) { a*=10.0; f_max_10_exp++; }
        !          2135:        if (F) i_define(D_MAX_10_EXP, thing,
        !          2136:                        Fname, "_MAX_10_EXP", (long) f_max_10_exp,
        !          2137:                        (long) F_MAX_10_EXP, "");
        !          2138: 
        !          2139:        /* Hidden bit + sanity check ****************************************/
        !          2140:        if (f_radix != 10) {
        !          2141:                hidden=0;
        !          2142:                mantbits=floor_log(2, (Long_double)f_radix)*f_mant_dig;
        !          2143:                if (mantbits+iexp == (int)sizeof(Number)*bits_per_byte) {
        !          2144:                        hidden=1;
        !          2145:                        Vprintf("%sArithmetic uses a hidden bit%s\n", co, oc);
        !          2146:                } else if (mantbits+iexp+1 == (int)sizeof(Number)*bits_per_byte) {
        !          2147:                        Vprintf("%sArithmetic doesn't use a hidden bit%s\n",
        !          2148:                                co, oc);
        !          2149:                } else {
        !          2150:                        printf("\n%s%s\n    %s %s %s!%s\n\n",
        !          2151:                               co,
        !          2152:                               "*** Something fishy here!",
        !          2153:                               "Exponent size + mantissa size doesn't match",
        !          2154:                               "with the size of a", thing,
        !          2155:                               oc);
        !          2156:                }
        !          2157:                if (hidden && f_radix == 2 && f_max_exp+f_min_exp==3) {
        !          2158:                        Vprintf("%sIt looks like %s length IEEE format%s\n",
        !          2159:                                co, f_mant_dig==24 ? "single" :
        !          2160:                                    f_mant_dig==53 ? "double" :
        !          2161:                                    f_mant_dig >53 ? "extended" :
        !          2162:                                                "some", oc);
        !          2163:                        if (f_rounds != 1 || normal) {
        !          2164:                                Vprintf("%s   though ", co);
        !          2165:                                if (f_rounds != 1) {
        !          2166:                                        Vprintf("the rounding is unusual");
        !          2167:                                        if (normal) Vprintf(" and ");
        !          2168:                                }
        !          2169:                                if (normal) Vprintf("the normalisation is unusual");
        !          2170:                                Vprintf("%s\n", oc);
        !          2171:                        }
        !          2172:                } else {
        !          2173:                        Vprintf("%sIt doesn't look like IEEE format%s\n",
        !          2174:                                co, oc);
        !          2175:                }
        !          2176:        }
        !          2177:        printf("\n"); /* regardless of verbosity */
        !          2178:        return f_mant_dig;
        !          2179: }
        !          2180: 
        !          2181: Procedure EPROP(fprec, dprec, lprec) int fprec, dprec, lprec; {
        !          2182:        /* See if expressions are evaluated in extended precision.
        !          2183:           Some compilers optimise even if you don't want it,
        !          2184:           and then this function fails to produce the right result.
        !          2185:           We try to diagnose this if it happens.
        !          2186:        */
        !          2187:        Volatile int eprec;
        !          2188:        Volatile double a, b, base, old;
        !          2189:        Volatile Number d, oldd, dbase, one, zero;
        !          2190:        Volatile int bad=0;
        !          2191: 
        !          2192:        /* Size of mantissa **************************************/
        !          2193:        a=1.0;
        !          2194:        if (setjmp(lab) == 0) { /* Yields nothing */
        !          2195:                do { old=a; a=a+a; }
        !          2196:                while ((((a+1.0)-a)-1.0) == 0.0 && a>old);
        !          2197:        } else bad=1;
        !          2198:        if (a <= old) bad=1;
        !          2199: 
        !          2200:        if (!bad) {
        !          2201:                b=1.0;
        !          2202:                if (setjmp(lab) == 0) { /* Yields nothing */
        !          2203:                        do { old=b; b=b+b; }
        !          2204:                        while ((base=((a+b)-a)) == 0.0 && b>old);
        !          2205:                        if (b <= old) bad=1;
        !          2206:                } else bad=1;
        !          2207:        }
        !          2208: 
        !          2209:        if (!bad) {
        !          2210:                eprec=0; d=1.0; dbase=base; one=1.0; zero=0.0;
        !          2211:                if (setjmp(lab) == 0) { /* Yields nothing */
        !          2212:                        do { eprec++; oldd=d; d=d*dbase; }
        !          2213:                        while ((((d+one)-d)-one) == zero && d>oldd);
        !          2214:                        if (d <= oldd) bad=1;
        !          2215:                } else bad=1;
        !          2216:        }
        !          2217: 
        !          2218:        Unexpected(31);
        !          2219: 
        !          2220:        if (bad) {
        !          2221:          Vprintf("%sCan't determine precision for %s expressions:\n%s%s\n", 
        !          2222:                 co, thing, "   check that you compiled without optimisation!",
        !          2223:                 oc);
        !          2224:        } else if (eprec==dprec) {
        !          2225:          Vprintf("%s%s expressions are evaluated in double precision%s\n",
        !          2226:                  co, Thing, oc);
        !          2227:        } else if (eprec==fprec) {
        !          2228:          Vprintf("%s%s expressions are evaluated in float precision%s\n",
        !          2229:                  co, Thing, oc);
        !          2230:        } else if (eprec==lprec) {
        !          2231:          Vprintf("%s%s expressions are evaluated in long double precision%s\n",
        !          2232:                  co, Thing, oc);
        !          2233:        } else {
        !          2234:                Vprintf("%s%s expressions are evaluated in a %s %s %d %s%s\n",
        !          2235:                        co, Thing, eprec>dprec ? "higher" : "lower",
        !          2236:                        "precision than double,\n   using",
        !          2237:                        eprec, "base digits",
        !          2238:                        oc);
        !          2239:        }
        !          2240: }
        !          2241: 
        !          2242: #else /* not Number */
        !          2243: 
        !          2244: #ifdef FPROP
        !          2245: /* ARGSUSED */
        !          2246: int FPROP(bits_per_byte) int bits_per_byte; { return 0; }
        !          2247: #endif
        !          2248: #ifdef EPROP
        !          2249: /* ARGSUSED */
        !          2250: Procedure EPROP(fprec, dprec, lprec) int fprec, dprec, lprec; {}
        !          2251: #endif
        !          2252: 
        !          2253: #endif /* ifdef Number */
        !          2254: 
        !          2255: #ifdef PASS3
        !          2256: #undef PASS
        !          2257: #endif
        !          2258: 
        !          2259: #ifdef PASS2
        !          2260: #undef PASS2
        !          2261: #define PASS3 1
        !          2262: #endif
        !          2263: 
        !          2264: #ifdef PASS1
        !          2265: #undef PASS1
        !          2266: #define PASS2 1
        !          2267: #endif
        !          2268: 
        !          2269: #ifdef PASS0
        !          2270: #undef PASS0
        !          2271: #endif
        !          2272: 
        !          2273: #ifdef PASS /* then rescan this file */
        !          2274: #ifdef NO_FILE
        !          2275: #include "config.c"
        !          2276: #else /* if the next line fails to compile, define NO_FILE */
        !          2277: #include __FILE__
        !          2278: #endif
        !          2279: #endif /* PASS */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.