📄 enquire.c
字号:
long val, long lim, long req, char *mark));Procedure u_define ARGS((char *desc, char *extra, char *sort, char *name, unsigned long val, unsigned long req, char *mark));#ifdef NO_SIG /* There's no signal(), or setjmp/longjmp() */ /* Dummy routines instead */ int setjmp ARGS((int lab)); int lab=1; int setjmp(lab) int lab; { return(0); } Procedure signal(i, p) int i, (*p)(); {}#else jmp_buf lab; Procedure overflow(sig) int sig; { /* what to do on over/underflow */ signal(sig, overflow); longjmp(lab, 1); }#endif /*NO_SIG*/int V= 0, /* verbose */ L= 0, /* produce limits.h */ F= 0, /* produce float.h */ bugs=0; /* The number of (possible) bugs in the output */char co[4], oc[4]; /* Comment starter and ender symbols */int bits_per_byte; /* the number of bits per unit returned by sizeof() */int flt_rounds; /* The calculated value of FLT_ROUNDS */int flt_radix; /* The calculated value of FLT_RADIX */#ifdef TEST/* Set the fp modes on a SUN with 68881 chip, to check that different rounding modes etc. get properly detected. Compile with -f68881 for cc, -m68881 for gcc, and with additional flag -DTEST. Run with additional parameter +hex-number, to set the 68881 mode register to hex-number*//* Bits 0x30 = rounding mode */#define ROUND_BITS 0x30#define TO_NEAREST 0x00#define TO_ZERO 0x10#define TO_MINUS_INF 0x20#define TO_PLUS_INF 0x30 /* The SUN FP user's guide seems to be wrong here *//* Bits 0xc0 = extended rounding */#define EXT_BITS 0xc0#define ROUND_EXTENDED 0x00#define ROUND_SINGLE 0x40#define ROUND_DOUBLE 0x80/* Enabled traps */#define EXE_INEX1 0x100#define EXE_INEX2 0x200#define EXE_DZ 0x400#define EXE_UNFL 0x800#define EXE_OVFL 0x1000#define EXE_OPERR 0x2000#define EXE_SNAN 0x4000#define EXE_BSUN 0x8000/* Only used for testing, on a Sun with 68881 chip *//* Print the FP mode */printmode(new) unsigned new; { fpmode_(&new); printf("New fp mode:\n"); printf(" Round toward "); switch (new & ROUND_BITS) { case TO_NEAREST: printf("nearest"); break; case TO_ZERO: printf("zero"); break; case TO_MINUS_INF: printf("minus infinity"); break; case TO_PLUS_INF: printf("plus infinity"); break; default: printf("???"); break; } printf("\n Extended rounding precision: "); switch (new & EXT_BITS) { case ROUND_EXTENDED: printf("extended"); break; case ROUND_SINGLE: printf("single"); break; case ROUND_DOUBLE: printf("double"); break; default: printf("???"); break; } printf("\n Enabled exceptions:"); if (new & (unsigned) EXE_INEX1) printf(" inex1"); if (new & (unsigned) EXE_INEX2) printf(" inex2"); if (new & (unsigned) EXE_DZ) printf(" dz"); if (new & (unsigned) EXE_UNFL) printf(" unfl"); if (new & (unsigned) EXE_OVFL) printf(" ovfl"); if (new & (unsigned) EXE_OPERR) printf(" operr"); if (new & (unsigned) EXE_SNAN) printf(" snan"); if (new & (unsigned) EXE_BSUN) printf(" bsun"); printf("\n");}/* Only used for testing, on a Sun with 68881 chip *//* Set the FP mode */int setmode(s) char *s; { unsigned mode=0, dig; char c; while (*s) { c= *s++; if (c>='0' && c<='9') dig= c-'0'; else if (c>='a' && c<='f') dig= c-'a'+10; else if (c>='A' && c<='F') dig= c-'A'+10; else return 1; mode= mode<<4 | dig; } printmode(mode); return 0;}#else/* ARGSUSED */int setmode(s) char *s; { fprintf(stderr, "Can't set mode: not compiled with TEST\n"); return(1);}#endifProcedure farewell(bugs) int bugs; { if (bugs == 0) exit(0); printf("\n%sFor hints on dealing with the ", co); if (bugs == 1) printf("problem"); else printf("%d problems", bugs); printf(" above\n see the section 'TROUBLESHOOTING' in the file "); printf("%s%s\n", FILENAME, oc); exit(bugs);}/* The program has received a signal where it wasn't expecting one */Procedure croak(place) int place; { printf("*** Unexpected signal at point %d\n", place); farewell(bugs+1); /* An exit isn't essential here, but avoids loops */}/* 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) { fprintf(stderr, "Virtual memory exceeded\n"); exit(bugs+1); } return value;}int maxint;int maximum_int() { /* Find the maximum integer */ Volatile int newi, int_max, two=2; /* Calculate maxint ***********************************/ /* Calculate 2**n-1 until overflow - then use the previous value */ newi=1; int_max=0; if (setjmp(lab)==0) { /* Yields int_max */ while(newi>int_max) { int_max=newi; newi=newi*two+1; } } Unexpected(0); return int_max;}int main(argc, argv) int argc; char *argv[]; { int dprec, fprec, lprec; int i; char *s; int bad;#ifdef SIGFPE signal(SIGFPE, overflow);#endif#ifdef SIGOVER signal(SIGOVER, overflow);#endif/* Add more calls as necessary */ Unexpected(1); bad=0; for (i=1; i < argc; i++) { s= argv[i]; if (*s == '-') { s++; while (*s) { switch (*(s++)) { case 'v': V=1; break; case 'l': L=1; break; case 'f': F=1; break; default: bad=1; break; } } } else if (*s == '+') { s++; bad= setmode(s); } else bad= 1; } if (bad) { fprintf(stderr, "Usage: %s [-vlf]\n v=Verbose l=Limits.h f=Float.h\n", argv[0]); exit(1); } if (L || F) { co[0]= '/'; oc[0]= ' '; co[1]= '*'; oc[1]= '*'; co[2]= ' '; oc[2]= '/'; co[3]= '\0'; oc[3]= '\0'; } else { co[0]= '\0'; oc[0]= '\0'; V=1; } 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);#else printf("%sProduced by enquire version %s, CWI, Amsterdam%s\n", co, VERSION, oc);#endif#ifdef VERIFY printf("%sVerification phase%s\n", co, oc);#endif#ifdef NO_SIG Vprintf("%sCompiled without signal(): %s%s\n", co, "there's nothing that can be done if overflow occurs", oc);#endif#ifdef NO_SC Vprintf("%sCompiled without signed char%s\n", co, oc);#endif#ifdef NO_UC Vprintf("%Compiled without unsigned char%s\n", co, oc);#endif#ifdef NO_UI Vprintf("%Compiled without unsigned short or long%s\n", co, oc);#endif#ifdef __STDC__ Vprintf("%sCompiler claims to be ANSI C level %d%s\n", co, __STDC__, oc);#else Vprintf("%sCompiler does not claim to be ANSI C%s\n", co, oc);#endif printf("\n"); check_defines(); maxint= maximum_int(); bits_per_byte= basic(); Vprintf("\n"); if (F||V) { fprec= fprop(bits_per_byte); dprec= dprop(bits_per_byte); lprec= ldprop(bits_per_byte); efprop(fprec, dprec, lprec); edprop(fprec, dprec, lprec); eldprop(fprec, dprec, lprec); }#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 to malloc. Here we assume that it's the same type as that which sizeof() returns */ size=1<<((bits_per_byte*sizeof(int))-2); total=0; while (size!=0) { while ( malloc((false()?sizeof(int):size)) != (char *)NULL ) { total+=(size/2); } size/=2; } Vprintf("%sMemory mallocatable ~= %ld Kbytes%s\n", 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 */}Procedure eek_a_bug(problem) char *problem; { /* The program has discovered a problem */ printf("\n%s*** WARNING: %s%s\n", co, problem, oc); bugs++;}Procedure describe(description, extra) char *description, *extra; { /* Produce the description for a #define */ printf(" %s", co); printf(description, extra); printf("%s\n", oc);}Procedure i_define(desc, extra, sort, name, val, lim, req, mark) 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. */ printf("#define %s%s (%ld%s%ld%s)\n", sort, name, -lim, mark, val+lim, mark); } else { printf("#define %s%s (%ld%s)\n", sort, name, val, mark); } /* If VERIFY is not set, val and req are just the same value; if it is set, val is the value as calculated, and req is the #defined constant */ if (val != req) { printf("%s*** Verify failed for above #define!\n", co); printf(" Compiler has %ld for value%s\n\n", req, oc); bugs++; } Vprintf("\n");}Procedure u_define(desc, extra, sort, name, val, req, mark) 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); printf(" Compiler has %lu for value%s\n\n", req, oc); bugs++; } Vprintf("\n");}Procedure f_define(desc, extra, sort, name, precision, val, mark) char *desc, *extra, *sort, *name; int precision; 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", sort, name, f_rep(precision, val)); } else { printf("#define %s%s %s\n", sort, name, f_rep(precision, val)); } Vprintf("\n");}int floor_log(base, x) int base; Long_double x; { /* return floor(log base(x)) */ int r=0; while (x>=base) { r++; x/=base; } return r;}int ceil_log(base, x) int base; Long_double x; { int r=0; while (x>1.0) { r++; x/=base; } return r;}int exponent(x, fract, exp) Long_double x; double *fract; int *exp; { /* Split x into a fraction and a power of ten; returns 0 if x is unusable, 1 otherwise. Only used for error messages about faulty output. */ int r=0, neg=0; Long_double old; *fract=0.0; *exp=0; if (x<0.0) { x= -x; neg= 1; } if (x==0.0) return 1; if (x>=10.0) { while (x>=10.0) { old=x; r++; x/=10.0; if (old==x) return 0; } } else { while (x<1.0) { old=x; r--; x*=10.0; if (old==x) return 0; } } if (neg) *fract= (double) -x; else *fract=(double) x; *exp=r; 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) {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];#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 */ sprintf(buf, "%.*e", precision, d); } else { /* It had better support Le then */ sprintf(buf, "%.*Le", precision, val); } return buf;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -