|
|
1.1 ! root 1: /* ! 2: * C general utilities library. ! 3: * strtol(), strtoul() ! 4: * ANSI 4.10.1.5, 4.10.1.6. ! 5: * Convert ASCII to long or unsigned long (the System V way). ! 6: * atol() was so simple before System V/ANSI got hold of it... ! 7: */ ! 8: ! 9: #include <stdlib.h> ! 10: #include <ctype.h> ! 11: #include <errno.h> ! 12: #include <limits.h> ! 13: ! 14: extern unsigned long _strtoul(); ! 15: ! 16: long ! 17: strtol(nptr, endptr, base) char *nptr; char **endptr; int base; ! 18: { ! 19: return (long)_strtoul(nptr, endptr, base, 0); ! 20: } ! 21: ! 22: unsigned long ! 23: strtoul(nptr, endptr, base) char *nptr; char **endptr; int base; ! 24: { ! 25: return _strtoul(nptr, endptr, base, 1); ! 26: } ! 27: ! 28: static ! 29: unsigned long ! 30: _strtoul(nptr, endptr, base, uflag) char *nptr; char **endptr; int base, uflag; ! 31: { ! 32: register char *cp; ! 33: register unsigned long val; ! 34: register int c, sign, overflow, pflag, dlimit, ulimit, llimit; ! 35: unsigned long quot, rem; ! 36: ! 37: cp = nptr; ! 38: val = pflag = overflow = sign = 0; ! 39: ! 40: /* Leading white space. */ ! 41: while (isspace(c = *cp++)) ! 42: ; ! 43: ! 44: /* Optional sign. */ ! 45: switch(c) { ! 46: case '-': ! 47: sign = 1; ! 48: /* fall through... */ ! 49: case '+': ! 50: c = *cp++; ! 51: } ! 52: ! 53: /* Determine implicit base. */ ! 54: if (base == 0) { ! 55: if (c == '0') ! 56: base = (*cp == 'x' || *cp == 'X') ? 16 : 8; ! 57: else if (isdigit(c)) ! 58: base = 10; ! 59: else { /* expected form not found */ ! 60: cp = nptr; ! 61: goto done; ! 62: } ! 63: } ! 64: ! 65: /* Skip optional hex base "0x" or "0X". */ ! 66: if (base == 16 && c == '0' && (*cp == 'x' || *cp == 'X')) { ! 67: ++pflag; ! 68: ++cp; ! 69: c = *cp++; ! 70: } ! 71: ! 72: /* Initialize legal character limits. */ ! 73: dlimit = '0' + base; ! 74: ulimit = 'A' + base - 10; ! 75: llimit = 'a' + base - 10; ! 76: ! 77: /* The next character must be a legitimate digit; e.g. " +@" fails. */ ! 78: /* Watch out for e.g. "0xy", which is "0" followed by "xy". */ ! 79: if (!( (isdigit(c) && c < dlimit) ! 80: || (isupper(c) && c < ulimit) ! 81: || (islower(c) && c < llimit))) { ! 82: cp = (pflag) ? cp - 2 : nptr; ! 83: goto done; ! 84: } ! 85: ! 86: /* Determine limits for overflow computation. */ ! 87: /* This would use ldiv() if it worked for unsigned long. */ ! 88: if (uflag) { ! 89: quot = ULONG_MAX / base; ! 90: rem = ULONG_MAX % base; ! 91: } else { ! 92: quot = LONG_MAX / base; ! 93: rem = LONG_MAX % base; ! 94: } ! 95: ! 96: /* Process digit string. */ ! 97: for ( ; ; c = *cp++) { ! 98: if (isdigit(c) && c < dlimit) ! 99: c -= '0'; ! 100: else if (isupper(c) && c < ulimit) ! 101: c -= 'A'-10; ! 102: else if (islower(c) && c < llimit) ! 103: c -= 'a'-10; ! 104: else { ! 105: --cp; ! 106: break; ! 107: } ! 108: if (val < quot || (val == quot && c <= rem)) ! 109: val = val * base + c; ! 110: else ! 111: ++overflow; ! 112: } ! 113: ! 114: done: ! 115: /* Store end pointer and return approriate result. */ ! 116: if (endptr != (char **)NULL) ! 117: *endptr = cp; ! 118: if (overflow) { ! 119: errno = ERANGE; ! 120: if (uflag) ! 121: return ULONG_MAX; ! 122: return (unsigned long)(sign ? LONG_MIN : LONG_MAX); ! 123: } ! 124: return (sign) ? (unsigned long)(-(long)val) : val; ! 125: } ! 126: ! 127: /* end of strtol.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.