home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 1 / 1482 < prev    next >
Internet Message Format  |  1990-12-28  |  64KB

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