|
|
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.