|
@ -33,12 +33,12 @@ |
|
|
|
|
|
|
|
|
#if defined(LIBC_SCCS) && !defined(lint) |
|
|
#if defined(LIBC_SCCS) && !defined(lint) |
|
|
/*static char *sccsid = "from: @(#)strtol.c 5.4 (Berkeley) 2/23/91";*/ |
|
|
/*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 */ |
|
|
#endif /* LIBC_SCCS and not lint */ |
|
|
|
|
|
|
|
|
#include <limits.h> |
|
|
|
|
|
#include <ctype.h> |
|
|
#include <ctype.h> |
|
|
#include <errno.h> |
|
|
#include <errno.h> |
|
|
|
|
|
#include <limits.h> |
|
|
#include <stdlib.h> |
|
|
#include <stdlib.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -54,25 +54,28 @@ strtol(nptr, endptr, base) |
|
|
char **endptr; |
|
|
char **endptr; |
|
|
register int base; |
|
|
register int base; |
|
|
{ |
|
|
{ |
|
|
register const char *s = nptr; |
|
|
|
|
|
register unsigned long acc; |
|
|
|
|
|
|
|
|
register const char *s; |
|
|
|
|
|
register long acc, cutoff; |
|
|
register int c; |
|
|
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. |
|
|
* Skip white space and pick up leading +/- sign if any. |
|
|
* If base is 0, allow 0x for hex and 0 for octal, else |
|
|
* If base is 0, allow 0x for hex and 0 for octal, else |
|
|
* assume decimal; if base is already 16, allow 0x. |
|
|
* assume decimal; if base is already 16, allow 0x. |
|
|
*/ |
|
|
*/ |
|
|
|
|
|
s = nptr; |
|
|
do { |
|
|
do { |
|
|
c = *s++; |
|
|
c = *s++; |
|
|
} while (isspace(c)); |
|
|
} while (isspace(c)); |
|
|
if (c == '-') { |
|
|
if (c == '-') { |
|
|
neg = 1; |
|
|
neg = 1; |
|
|
c = *s++; |
|
|
c = *s++; |
|
|
} else if (c == '+') |
|
|
|
|
|
c = *s++; |
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
neg = 0; |
|
|
|
|
|
if (c == '+') |
|
|
|
|
|
c = *s++; |
|
|
|
|
|
} |
|
|
if ((base == 0 || base == 16) && |
|
|
if ((base == 0 || base == 16) && |
|
|
c == '0' && (*s == 'x' || *s == 'X')) { |
|
|
c == '0' && (*s == 'x' || *s == 'X')) { |
|
|
c = s[1]; |
|
|
c = s[1]; |
|
@ -99,9 +102,16 @@ strtol(nptr, endptr, base) |
|
|
* Set any if any `digits' consumed; make it negative to indicate |
|
|
* Set any if any `digits' consumed; make it negative to indicate |
|
|
* overflow. |
|
|
* 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++) { |
|
|
for (acc = 0, any = 0;; c = *s++) { |
|
|
if (isdigit(c)) |
|
|
if (isdigit(c)) |
|
|
c -= '0'; |
|
|
c -= '0'; |
|
@ -111,19 +121,30 @@ strtol(nptr, endptr, base) |
|
|
break; |
|
|
break; |
|
|
if (c >= base) |
|
|
if (c >= base) |
|
|
break; |
|
|
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) |
|
|
if (endptr != 0) |
|
|
*endptr = (char *) (any ? s - 1 : nptr); |
|
|
*endptr = (char *) (any ? s - 1 : nptr); |
|
|
return (acc); |
|
|
return (acc); |
|
|