From e00f89ea6ff2d11e605f98ec1c36075ab457e6e7 Mon Sep 17 00:00:00 2001 From: eck Date: Mon, 18 Dec 1989 15:14:14 +0000 Subject: [PATCH] made a lot of changes --- lang/cem/libcc.ansi/stdlib/.distr | 27 + lang/cem/libcc.ansi/stdlib/LIST | 5 +- lang/cem/libcc.ansi/stdlib/Makefile | 43 ++ lang/cem/libcc.ansi/stdlib/atexit.c | 17 + lang/cem/libcc.ansi/stdlib/atof.c | 10 +- lang/cem/libcc.ansi/stdlib/atoi.c | 7 +- lang/cem/libcc.ansi/stdlib/atol.c | 8 +- lang/cem/libcc.ansi/stdlib/bsearch.c | 10 +- lang/cem/libcc.ansi/stdlib/exit.c | 23 +- lang/cem/libcc.ansi/stdlib/ext_comp.c | 688 ++++++++++++++++++++++++++ lang/cem/libcc.ansi/stdlib/ext_fmt.h | 13 + lang/cem/libcc.ansi/stdlib/getenv.c | 14 +- lang/cem/libcc.ansi/stdlib/mblen.c | 12 +- lang/cem/libcc.ansi/stdlib/mbstowcs.c | 14 +- lang/cem/libcc.ansi/stdlib/mbtowc.c | 16 +- lang/cem/libcc.ansi/stdlib/qsort.c | 22 +- lang/cem/libcc.ansi/stdlib/rand.c | 2 +- lang/cem/libcc.ansi/stdlib/strtod.c | 102 +--- lang/cem/libcc.ansi/stdlib/strtol.c | 121 +++-- lang/cem/libcc.ansi/stdlib/wcstombs.c | 12 +- lang/cem/libcc.ansi/stdlib/wctomb.c | 10 +- 21 files changed, 958 insertions(+), 218 deletions(-) create mode 100644 lang/cem/libcc.ansi/stdlib/.distr create mode 100644 lang/cem/libcc.ansi/stdlib/Makefile create mode 100644 lang/cem/libcc.ansi/stdlib/atexit.c create mode 100644 lang/cem/libcc.ansi/stdlib/ext_comp.c create mode 100644 lang/cem/libcc.ansi/stdlib/ext_fmt.h diff --git a/lang/cem/libcc.ansi/stdlib/.distr b/lang/cem/libcc.ansi/stdlib/.distr new file mode 100644 index 000000000..befcfba1a --- /dev/null +++ b/lang/cem/libcc.ansi/stdlib/.distr @@ -0,0 +1,27 @@ +LIST +Makefile +abort.c +abs.c +atexit.c +atof.c +atoi.c +atol.c +bsearch.c +div.c +exit.c +ext_comp.c +ext_fmt.h +getenv.c +labs.c +ldiv.c +mblen.c +mbstowcs.c +mbtowc.c +qsort.c +rand.c +strtod.c +strtol.c +system.c +wcstombs.c +wctomb.c +malloc diff --git a/lang/cem/libcc.ansi/stdlib/LIST b/lang/cem/libcc.ansi/stdlib/LIST index a6d62b47b..daa2f1cf2 100644 --- a/lang/cem/libcc.ansi/stdlib/LIST +++ b/lang/cem/libcc.ansi/stdlib/LIST @@ -1,12 +1,12 @@ -slib +ext_fmt.h abort.c abs.c atof.c atoi.c atol.c bsearch.c -calloc.c div.c +atexit.c exit.c getenv.c labs.c @@ -22,3 +22,4 @@ strtol.c system.c wcstombs.c wctomb.c +ext_comp.c diff --git a/lang/cem/libcc.ansi/stdlib/Makefile b/lang/cem/libcc.ansi/stdlib/Makefile new file mode 100644 index 000000000..07fd85d1b --- /dev/null +++ b/lang/cem/libcc.ansi/stdlib/Makefile @@ -0,0 +1,43 @@ +CFLAGS=-L -LIB + +.SUFFIXES: .o .e .c + +.e.o: + $(CC) $(CFLAGS) -c -o $@ $*.e + +clean: + rm -rf abort.o abs.o atof.o atoi.o atol.o bsearch.o div.o \ + atexit.o exit.o getenv.o labs.o ldiv.o malloc.o mblen.o \ + mbstowcs.o mbtowc.o qsort.o rand.o strtod.o strtol.o \ + system.o wcstombs.o wctomb.o ext_comp.o malloc.c OLIST + +malloc/malloc.c: + -(cd malloc; make) + +malloc.c: malloc/malloc.c + -cp malloc/malloc.c malloc.c + +abort.o: +abs.o: +atof.o: +atoi.o: +atol.o: +bsearch.o: +div.o: +atexit.o: +exit.o: +getenv.o: +labs.o: +ldiv.o: +malloc.o: +mblen.o: +mbstowcs.o: +mbtowc.o: +qsort.o: +rand.o: +strtod.o: +strtol.o: +system.o: +wcstombs.o: +wctomb.o: +ext_comp.o: diff --git a/lang/cem/libcc.ansi/stdlib/atexit.c b/lang/cem/libcc.ansi/stdlib/atexit.c new file mode 100644 index 000000000..3f10bdbbe --- /dev/null +++ b/lang/cem/libcc.ansi/stdlib/atexit.c @@ -0,0 +1,17 @@ +/* $Header$ */ + +#include + +#define NEXITS 32 + +extern void (*__functab[NEXITS])(void); +extern int __funccnt; + +int +atexit(void (*func)(void)) +{ + if (__funccnt >= NEXITS) + return 1; + __functab[__funccnt++] = func; + return 0; +} diff --git a/lang/cem/libcc.ansi/stdlib/atof.c b/lang/cem/libcc.ansi/stdlib/atof.c index 20d6c512e..e527b5354 100644 --- a/lang/cem/libcc.ansi/stdlib/atof.c +++ b/lang/cem/libcc.ansi/stdlib/atof.c @@ -4,12 +4,16 @@ */ /* $Header$ */ -#ifndef NOFLOAT #include +#include double atof(const char *nptr) { - return strtod(nptr, (char **) NULL); + double d; + int e = errno; + + d = strtod(nptr, (char **) NULL); + errno = e; + return d; } -#endif /* NOFLOAT */ diff --git a/lang/cem/libcc.ansi/stdlib/atoi.c b/lang/cem/libcc.ansi/stdlib/atoi.c index 020a4581f..e8cdfdc0f 100644 --- a/lang/cem/libcc.ansi/stdlib/atoi.c +++ b/lang/cem/libcc.ansi/stdlib/atoi.c @@ -5,9 +5,14 @@ /* $Header$ */ #include +#include int atoi(const char *nptr) { - return (int)strtol(nptr, (char **)NULL, 10); + int i, e = errno; + + i = (int)strtol(nptr, (char **)NULL, 10); + errno = e; + return i; } diff --git a/lang/cem/libcc.ansi/stdlib/atol.c b/lang/cem/libcc.ansi/stdlib/atol.c index e178007df..41f67b5e7 100644 --- a/lang/cem/libcc.ansi/stdlib/atol.c +++ b/lang/cem/libcc.ansi/stdlib/atol.c @@ -5,9 +5,15 @@ /* $Header$ */ #include +#include long atol(const char *nptr) { - return strtol(nptr, (char **)NULL, 10); + long l; + int e = errno; + + l = strtol(nptr, (char **)NULL, 10); + errno = e; + return l; } diff --git a/lang/cem/libcc.ansi/stdlib/bsearch.c b/lang/cem/libcc.ansi/stdlib/bsearch.c index aeebf3dae..88f35216e 100644 --- a/lang/cem/libcc.ansi/stdlib/bsearch.c +++ b/lang/cem/libcc.ansi/stdlib/bsearch.c @@ -11,18 +11,18 @@ bsearch(register const void *key, register const void *base, register size_t nmemb, register size_t size, int (*compar)(const void *, const void *)) { - register void *mid_point; + register const void *mid_point; register int cmp; while (nmemb > 0) { - mid_point = base + size * (nmemb >> 1); + mid_point = (char *)base + size * (nmemb >> 1); if ((cmp = (*compar)(key, mid_point)) == 0) - return(mid_point); + return (void *)mid_point; if (cmp >= 0) { - base = mid_point + size; + base = (char *)mid_point + size; nmemb = (nmemb - 1) >> 1; } else nmemb >>= 1; } - return((void *)NULL); + return (void *)NULL; } diff --git a/lang/cem/libcc.ansi/stdlib/exit.c b/lang/cem/libcc.ansi/stdlib/exit.c index 8a664a85c..fb7f97cb0 100644 --- a/lang/cem/libcc.ansi/stdlib/exit.c +++ b/lang/cem/libcc.ansi/stdlib/exit.c @@ -4,39 +4,32 @@ */ /* $Header$ */ +#include #include #define NEXITS 32 -static void (*functab[NEXITS])(void); -static int funccnt = 0; +void (*__functab[NEXITS])(void); +int __funccnt = 0; -extern void _cleanup(void); extern void _exit(int); +/* only fflush when there is output */ +int (*_fflush)(FILE *stream) = NULL; static void _calls(void) { - register int i = funccnt; + register int i = __funccnt; /* "Called in reversed order of their registration" */ while (--i >= 0) - (*functab[i])(); + (*__functab[i])(); } void exit(int status) { _calls(); - _cleanup() ; + if (_fflush) _fflush((FILE *)NULL) ; _exit(status) ; } - -int -atexit(void (*func)(void)) -{ - if (funccnt >= NEXITS) - return 1; - functab[funccnt++] = func; - return 0; -} diff --git a/lang/cem/libcc.ansi/stdlib/ext_comp.c b/lang/cem/libcc.ansi/stdlib/ext_comp.c new file mode 100644 index 000000000..ab096e4c7 --- /dev/null +++ b/lang/cem/libcc.ansi/stdlib/ext_comp.c @@ -0,0 +1,688 @@ +/* + (c) copyright 1989 by the Vrije Universiteit, Amsterdam, The Netherlands. + See the copyright notice in the ACK home directory, in the file "Copyright". +*/ + +/* $Header$ */ + +/* extended precision arithmetic for the strtod() and cvt() routines */ + +/* This may require some more work when long doubles get bigger than 8 + bytes. In this case, these routines may become obsolete. ??? +*/ + +#include "ext_fmt.h" +#include +#include +#include + +static int b64_add(struct mantissa *e1, struct mantissa *e2); +static b64_sft(struct mantissa *e1, int n); + +static +mul_ext(struct EXTEND *e1, struct EXTEND *e2, struct EXTEND *e3) +{ + /* Multiply the extended numbers e1 and e2, and put the + result in e3. + */ + register int i,j; /* loop control */ + unsigned short mp[4]; + unsigned short mc[4]; + unsigned short result[8]; /* result */ + + register unsigned short *pres; + + /* first save the sign (XOR) */ + e3->sign = e1->sign ^ e2->sign; + + /* compute new exponent */ + e3->exp = e1->exp + e2->exp + 1; + + /* check for overflow/underflow ??? */ + + /* 128 bit multiply of mantissas */ + + /* assign unknown long formats */ + /* to known unsigned word formats */ + mp[0] = e1->m1 >> 16; + mp[1] = (unsigned short) e1->m1; + mp[2] = e1->m2 >> 16; + mp[3] = (unsigned short) e1->m2; + mc[0] = e2->m1 >> 16; + mc[1] = (unsigned short) e2->m1; + mc[2] = e2->m2 >> 16; + mc[3] = (unsigned short) e2->m2; + for (i = 8; i--;) { + result[i] = 0; + } + /* + * fill registers with their components + */ + for(i=4, pres = &result[4];i--;pres--) if (mp[i]) { + unsigned short k = 0; + unsigned long mpi = mp[i]; + for(j=4;j--;) { + unsigned long tmp = (unsigned long)pres[j] + k; + if (mc[j]) tmp += mpi * mc[j]; + pres[j] = tmp; + k = tmp >> 16; + } + pres[-1] = k; + } + + if (! (result[0] & 0x8000)) { + e3->exp--; + for (i = 0; i <= 3; i++) { + result[i] <<= 1; + if (result[i+1]&0x8000) result[i] |= 1; + } + result[4] <<= 1; + } + /* + * combine the registers to a total + */ + e3->m1 = ((unsigned long)(result[0]) << 16) + result[1]; + e3->m2 = ((unsigned long)(result[2]) << 16) + result[3]; + if (result[4] & 0x8000) { + if (++e3->m2 == 0) { + if (++e3->m1 == 0) { + e3->m1 = 0x80000000; + e3->exp++; + } + } + } +} + +static +add_ext(struct EXTEND *e1, struct EXTEND *e2, struct EXTEND *e3) +{ + /* Add two extended numbers e1 and e2, and put the result + in e3 + */ + struct EXTEND ce2; + int diff; + + if ((e2->m1 | e2->m2) == 0L) { + *e3 = *e1; + return; + } + if ((e1->m1 | e1->m2) == 0L) { + *e3 = *e2; + return; + } + ce2 = *e2; + *e3 = *e1; + e1 = &ce2; + + /* adjust mantissas to equal power */ + diff = e3->exp - e1->exp; + if (diff < 0) { + diff = -diff; + e3->exp += diff; + b64_sft(&(e3->mantissa), diff); + } + else if (diff > 0) { + e1->exp += diff; + b64_sft(&(e1->mantissa), diff); + } + if (e1->sign != e3->sign) { + /* e3 + e1 = e3 - (-e1) */ + if (e1->m1 > e3->m1 || + (e1->m1 == e3->m1 && e1->m2 > e3->m2)) { + /* abs(e1) > abs(e3) */ + if (e3->m2 > e1->m2) { + e1->m1 -= 1; /* carry in */ + } + e1->m1 -= e3->m1; + e1->m2 -= e3->m2; + *e3 = *e1; + } + else { + if (e1->m2 > e3->m2) + e3->m1 -= 1; /* carry in */ + e3->m1 -= e1->m1; + e3->m2 -= e1->m2; + } + } + else { + if (b64_add(&e3->mantissa,&e1->mantissa)) {/* addition carry */ + b64_sft(&e3->mantissa,1);/* shift mantissa one bit RIGHT */ + e3->m1 |= 0x80000000L; /* set max bit */ + e3->exp++; /* increase the exponent */ + } + } + if ((e3->m2 | e3->m1) != 0L) { + /* normalize */ + if (e3->m1 == 0L) { + e3->m1 = e3->m2; e3->m2 = 0L; e3->exp -= 32; + } + if (!(e3->m1 & 0x80000000)) { + unsigned long l = 0x40000000; + int cnt = -1; + + while (! (l & e3->m1)) { + l >>= 1; cnt--; + } + e3->exp += cnt; + b64_sft(&(e3->mantissa), cnt); + } + } +} + +static int +cmp_ext(struct EXTEND *e1, struct EXTEND *e2) +{ + struct EXTEND tmp; + + e2->sign = ! e2->sign; + add_ext(e1, e2, &tmp); + e2->sign = ! e2->sign; + if (tmp.m1 == 0 && tmp.m2 == 0) return 0; + if (tmp.sign) return -1; + return 1; +} + +static +b64_sft(struct mantissa *e1, int n) +{ + if (n > 0) { + if (n > 63) { + e1->l_32 = 0; + e1->h_32 = 0; + return; + } + if (n >= 32) { + e1->l_32 = e1->h_32; + e1->h_32 = 0; + n -= 32; + } + if (n > 0) { + e1->l_32 >>= n; + if (e1->h_32 != 0) { + e1->l_32 |= (e1->h_32 << (32 - n)); + e1->h_32 >>= n; + } + } + return; + } + n = -n; + if (n > 0) { + if (n > 63) { + e1->l_32 = 0; + e1->h_32 = 0; + return; + } + if (n >= 32) { + e1->h_32 = e1->l_32; + e1->l_32 = 0; + n -= 32; + } + if (n > 0) { + e1->h_32 <<= n; + if (e1->l_32 != 0) { + e1->h_32 |= (e1->l_32 >> (32 - n)); + e1->l_32 <<= n; + } + } + } +} + +static int +b64_add(struct mantissa *e1, struct mantissa *e2) + /* + * pointers to 64 bit 'registers' + */ +{ + register int overflow; + int carry; + + /* add higher pair of 32 bits */ + overflow = ((unsigned long) 0xFFFFFFFF - e1->h_32 < e2->h_32); + e1->h_32 += e2->h_32; + + /* add lower pair of 32 bits */ + carry = ((unsigned long) 0xFFFFFFFF - e1->l_32 < e2->l_32); + e1->l_32 += e2->l_32; + if ((carry) && (++e1->h_32 == 0)) + return(1); /* had a 64 bit overflow */ + else + return(overflow); /* return status from higher add */ +} + +/* The following tables can be computed with the following bc(1) + program: + +obase=16 +scale=0 +define t(x){ + auto a, b, c + a=2;b=1;c=2^32;n=1 + while(asign = 0; + e->exp = 0; + e->m1 = e->m2 = 0; + + c = *s; + switch(c) { + case '-': + e->sign = 1; + case '+': + s++; + } + while (c = *s++, isdigit(c) || (c == '.' && ! dotseen++)) { + if (c == '.') continue; + digitseen = 1; + if (e->m1 <= (unsigned long)(0xFFFFFFFF)/10) { + struct mantissa a1; + + a1 = e->mantissa; + b64_sft(&(e->mantissa), -3); + b64_sft(&a1, -1); + b64_add(&(e->mantissa), &a1); + a1.h_32 = 0; + a1.l_32 = c - '0'; + b64_add(&(e->mantissa), &a1); + } + else exp++; + if (dotseen) exp--; + } + if (! digitseen) return; + + if (ss) *ss = s - 1; + + if (c == 'E' || c == 'e') { + int exp1 = 0; + int sign = 1; + + switch(*s) { + case '-': + sign = -1; + case '+': + s++; + } + if (c = *s, isdigit(c)) { + do { + int tmp; + + exp1 = 10 * exp1 + (c - '0'); + if ((tmp = sign * exp1 + exp) > MAX_EXP || + tmp < -MAX_EXP) { + errno = ERANGE; + } + } while (c = *++s, isdigit(c)); + if (ss) *ss = s; + } + exp += sign * exp1; + if (errno == ERANGE) exp = sign * MAX_EXP; + } + if (e->m1 == 0 && e->m2 == 0) return; + e->exp = 63; + while (! (e->m1 & 0x80000000)) { + b64_sft(&(e->mantissa),-1); + e->exp--; + } + add_exponent(e, exp); +} + +#include + +#define NDIGITS 128 + +char * +_ext_str_cvt(struct EXTEND *e, int ndigit, int *decpt, int *sign, int ecvtflag) +{ + /* Like cvt(), but for extended precision */ + + static char buf[NDIGITS+1]; + register char *p = buf; + register char *pe; + + if (ndigit < 0) ndigit = 0; + if (ndigit > NDIGITS) ndigit = NDIGITS; + pe = &buf[ndigit]; + buf[0] = '\0'; + + *sign = 0; + if (e->sign) { + *sign = 1; + e->sign = 0; + } + + *decpt = 0; + if (e->m1 != 0) { + register struct EXTEND *pp = &big_ten_powers[1]; + + while(cmp_ext(e,pp) >= 0) pp++; + pp--; + mul_ext(e,&r_big_ten_powers[pp-big_ten_powers],e); + *decpt += (pp - big_ten_powers) * TP; + pp = &ten_powers[1]; + while(pp < &ten_powers[TP] && cmp_ext(e, pp) >= 0) pp++; + pp--; + mul_ext(e, &r_ten_powers[pp-ten_powers], e); + *decpt += pp - ten_powers; + + if (cmp_ext(e, &ten_powers[0]) < 0) { + pp = &r_big_ten_powers[1]; + while(cmp_ext(e,pp) < 0) pp++; + pp--; + mul_ext(e, &big_ten_powers[pp - r_big_ten_powers], e); + *decpt -= (pp - r_big_ten_powers) * TP; + /* here, value >= 10 ** -28 */ + mul_ext(e, &ten_powers[1], e); + (*decpt)--; + pp = &r_ten_powers[0]; + while(cmp_ext(e, pp) < 0) pp++; + mul_ext(e, &ten_powers[pp - r_ten_powers], e); + *decpt -= pp - r_ten_powers; + } + (*decpt)++; /* because now value in [1.0, 10.0) */ + } + if (! ecvtflag) { + /* for fcvt() we need ndigit digits behind the dot */ + pe += *decpt; + if (pe > &buf[NDIGITS]) pe = &buf[NDIGITS]; + } + while (p <= pe) { + if (e->exp >= 0 && e->m1 != 0) { + struct EXTEND x; + + x.m2 = 0; x.exp = e->exp; + x.sign = 1; + x.m1 = e->m1>>(31-e->exp); + *p++ = (x.m1) + '0'; + if (x.m1) { + x.m1 = x.m1 << (31-e->exp); + add_ext(e, &x, e); + } + } + else *p++ = '0'; + if (e->m1) mul_ext(e, &ten_powers[1], e); + } + if (pe >= buf) { + p = pe; + *p += 5; /* round of at the end */ + while (*p > '9') { + *p = '0'; + if (p > buf) ++*--p; + else { + *p = '1'; + ++*decpt; + if (! ecvtflag) { + /* maybe add another digit at the end, + because the point was shifted right + */ + if (pe > buf) *pe = '0'; + pe++; + } + } + } + *pe = '\0'; + } + return buf; +} + +_dbl_ext_cvt(double value, struct EXTEND *e) +{ + /* Convert double to extended + */ + int exponent; + register int i; + + value = frexp(value, &exponent); + e->sign = value < 0.0; + if (e->sign) value = -value; + e->exp = exponent - 1; + e->m1 = 0; + e->m2 = 0; + for (i = 64; i > 0 && value != 0; i--) { + double ipart; + + b64_sft(&(e->mantissa),-1); + value = modf(2.0*value, &ipart); + if (ipart) { + e->m2 |= 1; + } + } + if (i > 0) b64_sft(&(e->mantissa),-i); +} + +static struct EXTEND max_d; +static struct EXTEND min_d; + +double +_ext_dbl_cvt(struct EXTEND *e) +{ + /* Convert extended to double + */ + double f; + int sign = e->sign; + + e->sign = 0; + if (e->m1 == 0 && e->m2 == 0) { + return 0.0; + } + if (max_d.exp == 0) { + _dbl_ext_cvt(DBL_MAX, &max_d); + _dbl_ext_cvt(DBL_MIN, &min_d); + } + if (cmp_ext(e, &min_d) < 0) { + f = 0.0; + errno = ERANGE; + } + else if (cmp_ext(&max_d, e) < 0) { + f = HUGE_VAL; + errno = ERANGE; + } + else f = ldexp(ldexp((double)e->m1, 32) + (double)e->m2, e->exp-63); + if (sign) f = -f; + return f; +} diff --git a/lang/cem/libcc.ansi/stdlib/ext_fmt.h b/lang/cem/libcc.ansi/stdlib/ext_fmt.h new file mode 100644 index 000000000..e8a5db1b8 --- /dev/null +++ b/lang/cem/libcc.ansi/stdlib/ext_fmt.h @@ -0,0 +1,13 @@ +struct mantissa { + unsigned long h_32; + unsigned long l_32; +}; + +struct EXTEND { + short sign; + short exp; + struct mantissa mantissa; +#define m1 mantissa.h_32 +#define m2 mantissa.l_32 +}; + diff --git a/lang/cem/libcc.ansi/stdlib/getenv.c b/lang/cem/libcc.ansi/stdlib/getenv.c index 0534312a0..d9b5e7f35 100644 --- a/lang/cem/libcc.ansi/stdlib/getenv.c +++ b/lang/cem/libcc.ansi/stdlib/getenv.c @@ -6,23 +6,23 @@ #include -extern char **environ; +extern const char **environ; char * getenv(const char *name) { - register char **v = environ; - register char *p, *q; + register const char **v = environ; + register const char *p, *q; - if (v == (char **)NULL || name == (char *)NULL) + if (v == NULL || name == NULL) return (char *)NULL; - while ((p = *v++) != (char *)NULL) { + while ((p = *v++) != NULL) { q = name; while (*q && (*q++ == *p++)) /* EMPTY */ ; if (*q || (*p != '=')) continue; - return(p+1); + return (char *)p + 1; } - return((char *)NULL); + return (char *)NULL; } diff --git a/lang/cem/libcc.ansi/stdlib/mblen.c b/lang/cem/libcc.ansi/stdlib/mblen.c index 38a901cb4..53b7dc20d 100644 --- a/lang/cem/libcc.ansi/stdlib/mblen.c +++ b/lang/cem/libcc.ansi/stdlib/mblen.c @@ -7,14 +7,12 @@ #include #include +#define CHAR_SHIFT 8 + int mblen(const char *s, size_t n) { - if (s == (char *)NULL) - return 0; - if (*s == '\0') - return 0; - if (n < 1 || n > MB_CUR_MAX) - return -1; - return MB_LEN_MAX; + if (s == (const char *)NULL) return 0; /* no state dependent codings */ + if (n <= 0) return 0; + return (*s != 0); } diff --git a/lang/cem/libcc.ansi/stdlib/mbstowcs.c b/lang/cem/libcc.ansi/stdlib/mbstowcs.c index 0d2c57597..2749cbace 100644 --- a/lang/cem/libcc.ansi/stdlib/mbstowcs.c +++ b/lang/cem/libcc.ansi/stdlib/mbstowcs.c @@ -5,20 +5,16 @@ /* $Header$ */ #include -#include -#include size_t mbstowcs(register wchar_t *pwcs, register const char *s, size_t n) { - register int i = 0; + register int i = n; - while (i < n) { - i++; - *pwcs++ = *s++; - if (*s == '\0') - return i; + while (--i >= 0) { + if (!(*pwcs++ = *s++)) + return n - i - 1; } - return n; + return n - i; } diff --git a/lang/cem/libcc.ansi/stdlib/mbtowc.c b/lang/cem/libcc.ansi/stdlib/mbtowc.c index 6e4a0151e..b5ebd7cb9 100644 --- a/lang/cem/libcc.ansi/stdlib/mbtowc.c +++ b/lang/cem/libcc.ansi/stdlib/mbtowc.c @@ -8,15 +8,11 @@ #include int -mbtowc(register wchar_t *pwc, register const char *s, size_t n) +mbtowc(wchar_t *pwc, register const char *s, size_t n) { - if (s == (char *)NULL) - return 0; - if (*s == '\0') - return 0; - if (n < 1 || n > MB_CUR_MAX) - return -1; - if (pwc != (wchar_t *)NULL) - *pwc = *s; - return MB_CUR_MAX; + if (s == (const char *)NULL) return 0; + if (*s == '\0') return 0; + if (n <= 0) return 0; + if (pwc) *pwc = *s; + return (*s != 0); } diff --git a/lang/cem/libcc.ansi/stdlib/qsort.c b/lang/cem/libcc.ansi/stdlib/qsort.c index 2804ae157..765252a31 100644 --- a/lang/cem/libcc.ansi/stdlib/qsort.c +++ b/lang/cem/libcc.ansi/stdlib/qsort.c @@ -6,24 +6,24 @@ #include -static void qsort1(void *, void *, size_t); -static int (*qcompar)(const void *, const void *); -static void qexchange(void *, void *, size_t); -static void q3exchange(void *, void *, void *, size_t); +static void qsort1(char *, char *, size_t); +static int (*qcompar)(const char *, const char *); +static void qexchange(char *, char *, size_t); +static void q3exchange(char *, char *, char *, size_t); void qsort(void *base, size_t nel, size_t width, int (*compar)(const void *, const void *)) { - qcompar = compar; - qsort1(base, base + (nel - 1) * width, width); + qcompar = (int (*)(const char *, const char *)) compar; + qsort1(base, (char *)base + (nel - 1) * width, width); } static void -qsort1(void *a1, void *a2, register size_t width) +qsort1(char *a1, char *a2, register size_t width) { - register const void *left, *right; - register const void *lefteq, *righteq; + register char *left, *right; + register char *lefteq, *righteq; int cmp; for (;;) { @@ -110,7 +110,7 @@ again: } static void -qexchange(register void *p, register void *q, +qexchange(register char *p, register char *q, register size_t n) { register int c; @@ -123,7 +123,7 @@ qexchange(register void *p, register void *q, } static void -q3exchange(register void *p, register void *q, register void *r, +q3exchange(register char *p, register char *q, register char *r, register size_t n) { register int c; diff --git a/lang/cem/libcc.ansi/stdlib/rand.c b/lang/cem/libcc.ansi/stdlib/rand.c index b510b1e36..dbae2b10e 100644 --- a/lang/cem/libcc.ansi/stdlib/rand.c +++ b/lang/cem/libcc.ansi/stdlib/rand.c @@ -11,7 +11,7 @@ static unsigned long int next = 1; int rand(void) { next = next * 1103515245 + 12345; - return((unsigned int)(next/(2 * (RAND_MAX +1)) % (RAND_MAX+1)); + return (unsigned int)(next/(2 * (RAND_MAX +1)) % (RAND_MAX+1)); } void srand(unsigned int seed) diff --git a/lang/cem/libcc.ansi/stdlib/strtod.c b/lang/cem/libcc.ansi/stdlib/strtod.c index 9a3b0c3f5..3c1c14a1e 100644 --- a/lang/cem/libcc.ansi/stdlib/strtod.c +++ b/lang/cem/libcc.ansi/stdlib/strtod.c @@ -1,103 +1,15 @@ -/* - * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. - * See the copyright notice in the ACK home directory, in the file "Copyright". - */ /* $Header$ */ -#ifndef NOFLOAT -#include -#include -#include -#include +#include "ext_fmt.h" -#define MAX (LONG_MAX/10) +void _str_ext_cvt(char *s, char **ss, struct EXTEND *e); +double _ext_dbl_cvt(struct EXTEND *e); double -strtod(register const char *p, register char **pp) +strtod(char *p, char **pp) { - register int c; - int exp = 0, sign = 1, expsign = 0; - double fl; - long lowl = 0, highl = 0, pos = 1; - int dotseen = 0; - int digit_seen = 0; + struct EXTEND e; - if (pp) *pp = p; - while (isspace(*p)) p++; - c = *p; - - switch (c) { - case '-': - sign = -1; - /* fallthrough */ - case '+': - p++; - } - - while (isdigit(c = *p++) || (c == '.' && ! dotseen++)) { - if (c == '.') continue; - digit_seen = 1; - if (highl < MAX) { - highl = (highl << 3) + (highl << 1) + (c - '0'); - } - else if (pos < MAX) { - pos = (pos << 3) + (pos << 1); - lowl = (lowl << 3) + (lowl << 1) + (c - '0'); - } - else exp++; - if (dotseen) exp--; - } - if (! digit_seen) return 0.0; - fl = highl; - if (pos > 1) { - fl = pos * fl + lowl; - } - - if (pp) *pp = p-1; - - if (c == 'E' || c == 'e') { - int exp1 = 0; - int sign = 1; - - switch (*p) { - case '-': - sign = -1; - /* fallthrough */ - case '+': - p++; - } - if (isdigit(c = *p)) { - do { - exp1 = 10 * exp1 + c - '0'; - } while (isdigit(c = *++p)); - if (pp) *pp = p; - } - exp += sign * exp1; - } - - if (fl == 0.0) return 0.0; - - if (exp < 0) { - expsign = 1; - exp = -exp; - } - - if (exp != 0) { - int oldexp = exp; - double exp5 = 5.0; - double correction = 1.0; - - while (exp) { - if (exp % 2) correction *= exp5; - exp /= 2; - if (exp != 0) exp5 *= exp5; - } - if (expsign) fl = fl / correction; - else fl = fl * correction; - - fl = ldexp(fl, expsign ? -oldexp : oldexp); - } - - return sign * fl; + _str_ext_cvt(p, pp, &e); + return _ext_dbl_cvt(&e); } -#endif diff --git a/lang/cem/libcc.ansi/stdlib/strtol.c b/lang/cem/libcc.ansi/stdlib/strtol.c index e7766f3bb..700b6fe14 100644 --- a/lang/cem/libcc.ansi/stdlib/strtol.c +++ b/lang/cem/libcc.ansi/stdlib/strtol.c @@ -4,50 +4,95 @@ */ /* $Header$ */ -#include #include +#include +#include +#include + +static unsigned long +string2long(register const char *nptr, char **endptr, + int base, int is_signed); long int -strtol(register const char *p, char **pp, int base) +strtol(register const char *nptr, char **endptr, int base) { - register long val, v; - register int c; - int sign = 1; - - if (pp) *pp = p; - while (isspace(*p)) p++; - c = *p; - - switch (c) { - case '-': - sign = -1; - /* fallthrough */ - case '+': - p++; - } - - /* this is bizare */ - if (base==16 && *p=='0' && (*(p+1)=='x' || *(p+1)=='X')) - p += 2; - - while (isdigit(c = *p++) || isalpha(c)) { - if (isalpha(c)) - v = 10 + (isupper(c) ? c - 'A' : c - 'a'); - else - v = c - '0'; - if (v >= base) { - p--; - break; - } - val = (val * base) + v; - } - if (pp) *pp = p-1; - return sign * val; + return (signed long)string2long(nptr, endptr, base, 1); } - unsigned long int -strtoul(register const char *p, char **pp, int base) +strtoul(register const char *nptr, char **endptr, int base) { - return (unsigned long)strtol(p, pp, base); + return (unsigned long)string2long(nptr, endptr, base, 0); +} + +static unsigned long +string2long(register const char *nptr, char ** const endptr, + int base, int is_signed) +{ + register int v; + register unsigned long val = 0; + register int c; + int ovfl = 0, sign = 1; + const char *startnptr = nptr, *nrstart; + + if (endptr) *endptr = (char *)nptr; + while (isspace(*nptr)) nptr++; + c = *nptr; + + if (c == '-' || c == '+') { + if (c == '-') sign = -1; + nptr++; + } + nrstart = nptr; /* start of the number */ + + /* When base is 0, the syntax determines the actual base */ + if (base == 0) + if (*nptr == '0') + if (*++nptr == 'x' || *nptr == 'X') { + base = 16; + nptr++; + } + else base = 8; + else base = 10; + else if (base==16 && *nptr=='0' && (*++nptr =='x' || *nptr =='X')) + nptr++; + + while (isdigit(c = *nptr) || isalpha(c)) { + if (!ovfl) { + if (isalpha(c)) + v = 10 + (isupper(c) ? c - 'A' : c - 'a'); + else + v = c - '0'; + if (v >= base) break; + if (val > (ULONG_MAX - v) / base) ovfl++; + val = (val * base) + v; + } + nptr++; + } + if (endptr) { + if (nrstart == nptr) *endptr = (char *)startnptr; + else *endptr = (char *)nptr; + } + + /* We can't represent a negative unsigned long, nor a long that + * is smaller than LONG_MIN or larger than LONG_MAX. + */ + if (!ovfl) { + if (!is_signed) + if (sign < 0 && val != 0) + ovfl++; + else if (((sign < 0 && val > -LONG_MIN) + || (sign > 0 && val > LONG_MAX))) + ovfl++; + } + + if (ovfl) { + errno = ERANGE; + if (is_signed) + if (sign < 0) return LONG_MIN; + else return LONG_MAX; + else return ULONG_MAX; + } + if (is_signed) return (unsigned long) sign * val; + else return val; } diff --git a/lang/cem/libcc.ansi/stdlib/wcstombs.c b/lang/cem/libcc.ansi/stdlib/wcstombs.c index 8e2e8e774..2edad1d2f 100644 --- a/lang/cem/libcc.ansi/stdlib/wcstombs.c +++ b/lang/cem/libcc.ansi/stdlib/wcstombs.c @@ -11,13 +11,11 @@ size_t wcstombs(register char *s, register const wchar_t *pwcs, size_t n) { - register int i = 0; + register int i = n; - while (i < n) { - i++; - *s++ = *pwcs++; - if (*s == '\0') - return i; + while (--i >= 0) { + if (!(*s++ = *pwcs)) + return n - i - 1; } - return n; + return n - i; } diff --git a/lang/cem/libcc.ansi/stdlib/wctomb.c b/lang/cem/libcc.ansi/stdlib/wctomb.c index bc8defc3e..eda9c1d44 100644 --- a/lang/cem/libcc.ansi/stdlib/wctomb.c +++ b/lang/cem/libcc.ansi/stdlib/wctomb.c @@ -10,10 +10,8 @@ int wctomb(char *s, wchar_t wchar) { - if (s != (char *)NULL) { - *s = wchar; - return MB_LEN_MAX; - } else - return 0; -} + if (!s) return 0; /* no state dependent codings */ + *s = wchar; + return (wchar != 0); +}