From 2214b38cd7b674d48f4de8cda7a16044642adcec Mon Sep 17 00:00:00 2001 From: deraadt <> Date: Thu, 21 Dec 1995 14:58:39 +0000 Subject: [PATCH] from netbsd; Rearrange to avoid sign problems with GCC. --- src/lib/libc/stdlib/strtol.c | 65 +++++++++++++++++++++++------------ src/lib/libc/stdlib/strtoq.c | 54 +++++++++++++++++++---------- src/lib/libc/stdlib/strtoul.c | 39 ++++++++++++--------- src/lib/libc/stdlib/strtouq.c | 30 ++++++++-------- 4 files changed, 115 insertions(+), 73 deletions(-) diff --git a/src/lib/libc/stdlib/strtol.c b/src/lib/libc/stdlib/strtol.c index 6f374abd..021fdc0d 100644 --- a/src/lib/libc/stdlib/strtol.c +++ b/src/lib/libc/stdlib/strtol.c @@ -33,12 +33,12 @@ #if defined(LIBC_SCCS) && !defined(lint) /*static char *sccsid = "from: @(#)strtol.c 5.4 (Berkeley) 2/23/91";*/ -static char *rcsid = "$Id: strtol.c,v 1.1.1.1 1995/10/18 08:42:20 deraadt Exp $"; +static char *rcsid = "$Id: strtol.c,v 1.2 1995/12/21 14:58:36 deraadt Exp $"; #endif /* LIBC_SCCS and not lint */ -#include #include #include +#include #include @@ -54,25 +54,28 @@ strtol(nptr, endptr, base) char **endptr; register int base; { - register const char *s = nptr; - register unsigned long acc; + register const char *s; + register long acc, cutoff; register int c; - register unsigned long cutoff; - register int neg = 0, any, cutlim; + register int neg, any, cutlim; /* * Skip white space and pick up leading +/- sign if any. * If base is 0, allow 0x for hex and 0 for octal, else * assume decimal; if base is already 16, allow 0x. */ + s = nptr; do { c = *s++; } while (isspace(c)); if (c == '-') { neg = 1; c = *s++; - } else if (c == '+') - c = *s++; + } else { + neg = 0; + if (c == '+') + c = *s++; + } if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) { c = s[1]; @@ -99,9 +102,16 @@ strtol(nptr, endptr, base) * Set any if any `digits' consumed; make it negative to indicate * overflow. */ - cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX; - cutlim = cutoff % (unsigned long)base; - cutoff /= (unsigned long)base; + cutoff = neg ? LONG_MIN : LONG_MAX; + cutlim = cutoff % base; + cutoff /= base; + if (neg) { + if (cutlim > 0) { + cutlim -= base; + cutoff += 1; + } + cutlim = -cutlim; + } for (acc = 0, any = 0;; c = *s++) { if (isdigit(c)) c -= '0'; @@ -111,19 +121,30 @@ strtol(nptr, endptr, base) break; if (c >= base) break; - if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) - any = -1; - else { - any = 1; - acc *= base; - acc += c; + if (any < 0) + continue; + if (neg) { + if (acc < cutoff || acc == cutoff && c > cutlim) { + any = -1; + acc = LONG_MIN; + errno = ERANGE; + } else { + any = 1; + acc *= base; + acc -= c; + } + } else { + if (acc > cutoff || acc == cutoff && c > cutlim) { + any = -1; + acc = LONG_MAX; + errno = ERANGE; + } else { + any = 1; + acc *= base; + acc += c; + } } } - if (any < 0) { - acc = neg ? LONG_MIN : LONG_MAX; - errno = ERANGE; - } else if (neg) - acc = -acc; if (endptr != 0) *endptr = (char *) (any ? s - 1 : nptr); return (acc); diff --git a/src/lib/libc/stdlib/strtoq.c b/src/lib/libc/stdlib/strtoq.c index fc559e9d..003c020d 100644 --- a/src/lib/libc/stdlib/strtoq.c +++ b/src/lib/libc/stdlib/strtoq.c @@ -37,9 +37,9 @@ static char sccsid[] = "@(#)strtoq.c 5.1 (Berkeley) 6/26/92"; #include -#include -#include #include +#include +#include #include /* @@ -55,9 +55,8 @@ strtoq(nptr, endptr, base) register int base; { register const char *s; - register u_quad_t acc; + register quad_t acc, cutoff; register int c; - register u_quad_t qbase, cutoff; register int neg, any, cutlim; /* @@ -104,10 +103,16 @@ strtoq(nptr, endptr, base) * Set any if any `digits' consumed; make it negative to indicate * overflow. */ - qbase = (unsigned)base; - cutoff = neg ? -(u_quad_t)QUAD_MIN : QUAD_MAX; - cutlim = cutoff % qbase; - cutoff /= qbase; + cutoff = neg ? QUAD_MIN : QUAD_MAX; + cutlim = cutoff % base; + cutoff /= base; + if (neg) { + if (cutlim > 0) { + cutlim -= base; + cutoff += 1; + } + cutlim = -cutlim; + } for (acc = 0, any = 0;; c = *s++) { if (isdigit(c)) c -= '0'; @@ -117,19 +122,30 @@ strtoq(nptr, endptr, base) break; if (c >= base) break; - if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) - any = -1; - else { - any = 1; - acc *= qbase; - acc += c; + if (any < 0) + continue; + if (neg) { + if (acc < cutoff || acc == cutoff && c > cutlim) { + any = -1; + acc = QUAD_MIN; + errno = ERANGE; + } else { + any = 1; + acc *= base; + acc -= c; + } + } else { + if (acc > cutoff || acc == cutoff && c > cutlim) { + any = -1; + acc = QUAD_MAX; + errno = ERANGE; + } else { + any = 1; + acc *= base; + acc += c; + } } } - if (any < 0) { - acc = neg ? QUAD_MIN : QUAD_MAX; - errno = ERANGE; - } else if (neg) - acc = -acc; if (endptr != 0) *endptr = (char *) (any ? s - 1 : nptr); return (acc); diff --git a/src/lib/libc/stdlib/strtoul.c b/src/lib/libc/stdlib/strtoul.c index 00f7210f..1522bec5 100644 --- a/src/lib/libc/stdlib/strtoul.c +++ b/src/lib/libc/stdlib/strtoul.c @@ -33,12 +33,12 @@ #if defined(LIBC_SCCS) && !defined(lint) /*static char *sccsid = "from: @(#)strtoul.c 5.3 (Berkeley) 2/23/91";*/ -static char *rcsid = "$Id: strtoul.c,v 1.1.1.1 1995/10/18 08:42:20 deraadt Exp $"; +static char *rcsid = "$Id: strtoul.c,v 1.2 1995/12/21 14:58:38 deraadt Exp $"; #endif /* LIBC_SCCS and not lint */ -#include #include #include +#include #include /* @@ -53,23 +53,26 @@ strtoul(nptr, endptr, base) char **endptr; register int base; { - register const char *s = nptr; - register unsigned long acc; + register const char *s; + register unsigned long acc, cutoff; register int c; - register unsigned long cutoff; - register int neg = 0, any, cutlim; + register int neg, any, cutlim; /* * See strtol for comments as to the logic used. */ + s = nptr; do { c = *s++; } while (isspace(c)); if (c == '-') { neg = 1; c = *s++; - } else if (c == '+') - c = *s++; + } else { + neg = 0; + if (c == '+') + c = *s++; + } if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) { c = s[1]; @@ -78,8 +81,9 @@ strtoul(nptr, endptr, base) } if (base == 0) base = c == '0' ? 8 : 10; - cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; - cutlim = (unsigned long)ULONG_MAX % (unsigned long)base; + + cutoff = ULONG_MAX / (unsigned long)base; + cutlim = ULONG_MAX % (unsigned long)base; for (acc = 0, any = 0;; c = *s++) { if (isdigit(c)) c -= '0'; @@ -89,18 +93,19 @@ strtoul(nptr, endptr, base) break; if (c >= base) break; - if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) + if (any < 0) + continue; + if (acc > cutoff || acc == cutoff && c > cutlim) { any = -1; - else { + acc = ULONG_MAX; + errno = ERANGE; + } else { any = 1; - acc *= base; + acc *= (unsigned long)base; acc += c; } } - if (any < 0) { - acc = ULONG_MAX; - errno = ERANGE; - } else if (neg) + if (neg && any > 0) acc = -acc; if (endptr != 0) *endptr = (char *) (any ? s - 1 : nptr); diff --git a/src/lib/libc/stdlib/strtouq.c b/src/lib/libc/stdlib/strtouq.c index cc647d8d..3ab2c232 100644 --- a/src/lib/libc/stdlib/strtouq.c +++ b/src/lib/libc/stdlib/strtouq.c @@ -37,9 +37,9 @@ static char sccsid[] = "@(#)strtouq.c 5.1 (Berkeley) 6/26/92"; #include -#include -#include #include +#include +#include #include /* @@ -54,10 +54,9 @@ strtouq(nptr, endptr, base) char **endptr; register int base; { - register const char *s = nptr; - register u_quad_t acc; + register const char *s; + register u_quad_t acc, cutoff; register int c; - register u_quad_t qbase, cutoff; register int neg, any, cutlim; /* @@ -83,9 +82,9 @@ strtouq(nptr, endptr, base) } if (base == 0) base = c == '0' ? 8 : 10; - qbase = (unsigned)base; - cutoff = (u_quad_t)UQUAD_MAX / qbase; - cutlim = (u_quad_t)UQUAD_MAX % qbase; + + cutoff = UQUAD_MAX / (u_quad_t)base; + cutlim = UQUAD_MAX % (u_quad_t)base; for (acc = 0, any = 0;; c = *s++) { if (isdigit(c)) c -= '0'; @@ -95,18 +94,19 @@ strtouq(nptr, endptr, base) break; if (c >= base) break; - if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) + if (any < 0) + continue; + if (acc > cutoff || acc == cutoff && c > cutlim) { any = -1; - else { + acc = UQUAD_MAX; + errno = ERANGE; + } else { any = 1; - acc *= qbase; + acc *= (u_quad_t)base; acc += c; } } - if (any < 0) { - acc = UQUAD_MAX; - errno = ERANGE; - } else if (neg) + if (neg && any > 0) acc = -acc; if (endptr != 0) *endptr = (char *) (any ? s - 1 : nptr);