/* Everything you wanted to know about your machine and C compiler,
- but didn't know who to ask. */
+ but didn't know who to ask. */
#ifndef VERSION
#define VERSION "4.3"
Copyright (c) 1988, 1989, 1990 Steven Pemberton, CWI, Amsterdam.
All rights reserved.
+ Changes by Richard Stallman:
Undef CHAR_BIT, etc., if defined in stdio.h, Richard Stallman, Aug 90.
In EPROP, avoid a <= old if bad is set, Richard Stallman, May 91.
Use gstddef.h, not stddef.h, Richard Stallman, Nov 91.
Don't declare malloc, instead cast the value, Richard Stallman, Nov 91.
+ Include sys/types.h before signal.h, Apr 92.
+ Support NO_LONG_DOUBLE_IO in f_define and f_rep; new fn fake_f_rep, Apr 92.
+ Enclose -f output in #ifndef _FLOAT_H___, Richard Stallman, May 92.
+
+ Change by Jim Wilson:
+ Add #undef before every #define, Dec 92.
+ Use stddef.h not gstddef.h, Mar 94.
+
+ Changes by Paul Eggert, installed Feb 93:
+ (fake_f_rep): Clear all of u, initially. Make the ints in u unsigned.
+ (f_define): Use ordinary constants for long double
+ if it's same width as double. Make __convert_long_double_i unsigned.
+ Richard Stallman, May 93:
+ In F_check, check NO_LONG_DOUBLE_IO.
+
+ Changes by Stephen Moshier, installed Sep 93:
+ (FPROP): Recognize 80387 or 68881 XFmode format.
+
COMPILING
With luck and a following wind, just the following will work:
unsigned short and long -DNO_UI
void -DNO_VOID
signal(), or setjmp/longjmp() -DNO_SIG
+ %Lf in printf -DNO_LONG_DOUBLE_IO
Try to compile first with no flags, and see if you get any errors -
you might be surprised. (Most non-ANSI compilers need -DNO_SC, though.)
#endif /* NO_FILE */
#endif /* FILENAME */
-/* If PASS isn't defined, then this is the first pass over this file. */
+/* If PASS isn't defined, then this is the first pass over this file. */
#ifndef PASS
#ifndef SEP
#define PASS 1
#endif /* STDC */
/* include files */
+/* Stdio.h might include limits.h, and limits.h might include float.h, and
+ float.h is probably the float.h put together by the gcc makefile to
+ cause errors. We use our special define to assure float.h that we don't
+ really need it. */
+#define __GCC_FLOAT_NOT_NEEDED
#include <stdio.h>
#ifdef STDC
#ifndef NO_STDDEF
-#include "gstddef.h" /* for size_t: if this fails, define NO_STDDEF */
+#include <stddef.h> /* for size_t: if this fails, define NO_STDDEF */
#endif
#endif
#ifdef NO_SIG
#define jmp_buf int
#else
+#include <sys/types.h>
#include <signal.h>
#include <setjmp.h>
#endif
-/* Kludge around the possiblity that <stdio.h> includes <limits.h> */
+/* Kludge around the possibility that <stdio.h> includes <limits.h> */
#ifdef CHAR_BIT
#undef CHAR_BIT
#undef CHAR_MAX
Procedure exit ARGS((int status));
char *f_rep ARGS((int precision, Long_double val));
+char *fake_f_rep ARGS((char *type, Long_double val));
int maximum_int NOARGS;
int cprop NOARGS;
farewell(bugs+1); /* An exit isn't essential here, but avoids loops */
}
-/* This is here in case alloca.c is used, which calls this. */
+/* This is here in case alloca.c is used, which calls this. */
char *xmalloc(size) unsigned size; {
char *value = (char *)malloc(size);
if (value == 0) {
int main(argc, argv) int argc; char *argv[]; {
int dprec, fprec, lprec;
- unsigned int size;
- long total;
int i; char *s; int bad;
#ifdef SIGFPE
if (L) printf("%slimits.h%s\n", co, oc);
if (F) printf("%sfloat.h%s\n", co, oc);
+ if (F) {
+ printf ("#ifndef _FLOAT_H___\n");
+ printf ("#define _FLOAT_H___\n");
+ }
#ifdef ID
printf("%sProduced on %s by enquire version %s, CWI, Amsterdam%s\n",
co, ID, VERSION, oc);
}
#ifndef NO_MEM
if (V) {
+ unsigned int size;
+ long total;
/* An extra goody: the approximate amount of data-space */
/* Allocate store until no more available */
/* Different implementations have a different argument type
co, (total+511)/512, oc);
}
#endif
+ if (F) {
+ printf ("#endif %s _FLOAT_H___%s\n", co, oc);
+ }
farewell(bugs);
return bugs; /* To keep compilers and lint happy */
}
char *desc, *extra, *sort, *name; long val, lim, req; char *mark; {
/* Produce a #define for a signed int type */
describe(desc, extra);
+ printf("#undef %s%s\n", sort, name);
if (val >= 0) {
printf("#define %s%s %ld%s\n", sort, name, val, mark);
} else if (val + lim < 0) {
/* We may not produce a constant like -1024 if the max
allowable value is 1023. It has then to be output as
- -1023-1. lim is the max allowable value. */
+ -1023-1. lim is the max allowable value. */
printf("#define %s%s (%ld%s%ld%s)\n",
sort, name, -lim, mark, val+lim, mark);
} else {
char *desc, *extra, *sort, *name; unsigned long val, req; char *mark; {
/* Produce a #define for an unsigned value */
describe(desc, extra);
+ printf("#undef %s%s\n", sort, name);
printf("#define %s%s %lu%s%s\n", sort, name, val, U, mark);
if (val != req) {
printf("%s*** Verify failed for above #define!\n", co);
Long_double val; char *mark; {
/* Produce a #define for a float/double/long double */
describe(desc, extra);
+ printf ("#undef %s%s\n", sort, name);
if (stdc) {
+#ifdef NO_LONG_DOUBLE_IO
+ static int union_defined = 0;
+ if (sizeof(double) != sizeof(Long_double)
+ && !strcmp(sort, "LDBL")) {
+ if (!union_defined) {
+ printf("#ifndef __LDBL_UNION__\n");
+ printf("#define __LDBL_UNION__\n");
+ printf("union __convert_long_double {\n");
+ printf(" unsigned __convert_long_double_i[4];\n");
+ printf(" long double __convert_long_double_d;\n");
+ printf("};\n");
+ printf("#endif\n");
+ union_defined = 1;
+ }
+ printf("#define %s%s %s\n",
+ sort, name, fake_f_rep("long double", val));
+ } else {
+ printf("#define %s%s %s%s\n",
+ sort, name, f_rep(precision, val), mark);
+ }
+#else
printf("#define %s%s %s%s\n",
sort, name, f_rep(precision, val), mark);
+#endif
} else if (*mark == 'F') {
/* non-ANSI C has no float constants, so cast the constant */
printf("#define %s%s ((float)%s)\n",
return 1;
}
+/* Print a value of type TYPE with value VAL,
+ assuming that sprintf can't handle this type properly (without truncation).
+ We create an expression that uses type casting to create the value from
+ a bit pattern. */
+
+char *fake_f_rep(type, val) char *type; Long_double val; {
+ static char buf[1024];
+ union { unsigned int i[4]; Long_double ld;} u;
+ u.i[0] = u.i[1] = u.i[2] = u.i[3] = 0;
+ u.ld = val;
+ sprintf(buf, "(__extension__ ((union __convert_long_double) {__convert_long_double_i: {0x%x, 0x%x, 0x%x, 0x%x}}).__convert_long_double_d)",
+ u.i[0], u.i[1], u.i[2], u.i[3]);
+ return buf;
+}
+
char *f_rep(precision, val) int precision; Long_double val; {
/* Return the floating representation of val */
static char buf[1024];
- char *f1;
- if (sizeof(double) == sizeof(Long_double)) {
+#ifdef NO_LONG_DOUBLE_IO
+ if (1)
+#else
+ if (sizeof(double) == sizeof(Long_double))
+#endif
+ {
+ double d = val;
/* Assume they're the same, and use non-stdc format */
/* This is for stdc compilers using non-stdc libraries */
- f1= "%.*e";
+ sprintf(buf, "%.*e", precision, d);
} else {
/* It had better support Le then */
- f1= "%.*Le";
+ sprintf(buf, "%.*Le", precision, val);
}
- sprintf(buf, f1, precision, val);
return buf;
}
name, ftype_of(esize), ftype_of(size));
}
-promotions() {
- int si; long sl;
+int promotions() {
+ int si = 0; long sl = 0;
unsigned int ui; unsigned long ul;
short ss; unsigned short us;
eek_a_bug("promotions don't work properly in conditional expressions\n");
}
- showtype("unsigned short promotes to", Promoted((unsigned short)0));
+ showtype("unsigned short promotes to", Promoted((unsigned short) 0));
showtype("long+unsigned gives", sl+ui);
+ return 0;
}
#define checktype(x, n, s, t) if((sgn(x)!=s)||(sizeof(x)!=sizeof(t))) typerr(n, s, sizeof(t), sign_of(x), sizeof(x));
usign= Signed;
#else
/* Implementations promote unsigned short differently */
- usign= is_signed((unsigned short)0);
+ usign= is_signed((unsigned short) 0);
#endif
if (L) {
/* Alignment constants ********************************************/
#define alignment(TYPE) \
- ((long)((char *)&((struct{char c; TYPE d;}*)0)->d - (char *)0))
+ ((long)((char *)&((struct{char c; TYPE d;}*)0)->d - (char *) 0))
Vprintf("\n%sALIGNMENTS%s\n", co, oc);
that sscanf read the number back identically. Harsh yes, but
sometimes you've got to be cruel to be kind.
*/
- Long_double new1;
Number val, new, diff;
double rem;
int e;
char *rep;
char *f2;
+#ifdef NO_LONG_DOUBLE_IO
+ double new1;
+ /* On the Sun 3, sscanf clobbers 4 words,
+ which leads to a crash when this function tries to return. */
+ f2= "%le"; /* Input */
+ /* It is no use checking long doubles if we can't
+ read and write them. */
+ if (sizeof (Number) > sizeof(double))
+ return;
+#else
+ Long_double new1;
if (sizeof(double) == sizeof(Long_double)) {
/* Assume they're the same, and use non-stdc format */
/* This is for stdc compilers using non-stdc libraries */
/* It had better support Le then */
f2= "%Le";
}
+#endif
val= val1;
rep= f_rep(precision, (Long_double) val);
if (setjmp(lab)==0) {
if (f_radix != 10) {
hidden=0;
mantbits=floor_log(2, (Long_double)f_radix)*f_mant_dig;
+ if (mantbits == 64
+ && iexp == 15
+ && f_max_exp+f_min_exp > 0 /* ??? f_min_exp may be wrong. */
+ && mantbits+iexp+17 == (int)sizeof(Number)*bits_per_byte) {
+ Vprintf("%sArithmetic probably doesn't use a hidden bit%s\n", co, oc);
+ Vprintf("%sIt's probably 80387 or 68881 extended real%s\n", co, oc);
+ goto is_extended;
+ }
if (mantbits+iexp == (int)sizeof(Number)*bits_per_byte) {
hidden=1;
Vprintf("%sArithmetic uses a hidden bit%s\n", co, oc);
f_mant_dig==53 ? "double" :
f_mant_dig >53 ? "extended" :
"some", oc);
+is_extended:
if (f_rounds != 1 || normal) {
Vprintf("%s though ", co);
if (f_rounds != 1) {