Annotation of researchv10no/cmd/lcc/etc/config.c, revision 1.1.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.