123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- /*
- * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
- * See the copyright notice in the ACK home directory, in the file "Copyright".
- */
- /* $Id$ */
- #include <ctype.h>
- #include <errno.h>
- #include <limits.h>
- #include <stdlib.h>
- static unsigned long
- string2long(register const char *nptr, char **endptr,
- int base, int is_signed);
- long int
- strtol(register const char *nptr, char **endptr, int base)
- {
- return (signed long)string2long(nptr, endptr, base, 1);
- }
- unsigned long int
- strtoul(register const char *nptr, char **endptr, int 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 unsigned 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;
- else val = (val * base) + v;
- }
- nptr++;
- }
- if (endptr) {
- if (nrstart == nptr) *endptr = (char *)startnptr;
- else *endptr = (char *)nptr;
- }
- if (!ovfl) {
- /* Overflow is only possible when converting a signed long.
- * The "-(LONG_MIN+1)+(unsigned long) 1" construction is there
- * to prevent overflow warnings on -LONG_MIN.
- */
- if (is_signed
- && ( (sign < 0 && val > -(LONG_MIN+1)+(unsigned long) 1)
- || (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;
- }
- return (sign * val);
- }
|