1 static inline int
2 isupper(char c)
3 {
4 return (c >= 'A' && c <= 'Z');
5 }
6
7 static inline int
8 isalpha(char c)
9 {
10 return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'));
11 }
12
13
14 static inline int
15 isspace(char c)
16 {
17 return (c == ' ' || c == '\t' || c == '\n' || c == '\12');
18 }
19
20 static inline int
21 isdigit(char c)
22 {
23 return (c >= '0' && c <= '9');
24 }
25
26 /*
27 * Convert a string to a long integer.
28 *
29 * Ignores `locale' stuff. Assumes that the upper and lower case
30 * alphabets and digits are each contiguous.
31 */
32 long
33 strtol(nptr, endptr, base)
34 const char *nptr;
35 char **endptr;
36 register int base;
37 {
38 register const char *s = nptr;
39 register unsigned long acc;
40 register int c;
41 register unsigned long cutoff;
42 register int neg = 0, any, cutlim;
43
44 /*
45 * Skip white space and pick up leading +/- sign if any.
46 * If base is 0, allow 0x for hex and 0 for octal, else
47 * assume decimal; if base is already 16, allow 0x.
48 */
49 do {
50 c = *s++;
51 } while (isspace(c));
52 if (c == '-') {
53 neg = 1;
54 c = *s++;
55 } else if (c == '+')
56 c = *s++;
57 if ((base == 0 || base == 16) &&
58 c == '0' && (*s == 'x' || *s == 'X')) {
59 c = s[1];
60 s += 2;
61 base = 16;
62 } else if ((base == 0 || base == 2) &&
63 c == '0' && (*s == 'b' || *s == 'B')) {
64 c = s[1];
65 s += 2;
66 base = 2;
67 }
68 if (base == 0)
69 base = c == '0' ? 8 : 10;
70
71 /*
72 * Compute the cutoff value between legal numbers and illegal
73 * numbers. That is the largest legal value, divided by the
74 * base. An input number that is greater than this value, if
75 * followed by a legal input character, is too big. One that
76 * is equal to this value may be valid or not; the limit
77 * between valid and invalid numbers is then based on the last
78 * digit. For instance, if the range for longs is
79 * [-2147483648..2147483647] and the input base is 10,
80 * cutoff will be set to 214748364 and cutlim to either
81 * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
82 * a value > 214748364, or equal but the next digit is > 7 (or 8),
83 * the number is too big, and we will return a range error.
84 *
85 * Set any if any `digits' consumed; make it negative to indicate
86 * overflow.
87 */
88 cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
89 cutlim = cutoff % (unsigned long)base;
90 cutoff /= (unsigned long)base;
91 for (acc = 0, any = 0;; c = *s++) {
92 if (isdigit(c))
93 c -= '0';
94 else if (isalpha(c))
95 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
96 else
97 break;
98 if (c >= base)
99 break;
100 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
101 any = -1;
102 else {
103 any = 1;
104 acc *= base;
105 acc += c;
106 }
107 }
108 if (any < 0) {
109 acc = neg ? LONG_MIN : LONG_MAX;
110 // errno = ERANGE;
111 } else if (neg)
112 acc = -acc;
113 if (endptr != 0)
114 *endptr = (char *)(any ? s - 1 : nptr);
115 return (acc);
116 }
117
118 /*
119 * Convert a string to an unsigned long integer.
120 *
121 * Ignores `locale' stuff. Assumes that the upper and lower case
122 * alphabets and digits are each contiguous.
123 */
124 unsigned long
125 strtoul(nptr, endptr, base)
126 const char *nptr;
127 char **endptr;
128 register int base;
129 {
130 register const char *s = nptr;
131 register unsigned long acc;
132 register int c;
133 register unsigned long cutoff;
134 register int neg = 0, any, cutlim;
135
136 /*
137 * See strtol for comments as to the logic used.
138 */
139 do {
140 c = *s++;
141 } while (isspace(c));
142 if (c == '-') {
143 neg = 1;
144 c = *s++;
145 } else if (c == '+')
146 c = *s++;
147 if ((base == 0 || base == 16) &&
148 c == '0' && (*s == 'x' || *s == 'X')) {
149 c = s[1];
150 s += 2;
151 base = 16;
152 } else if ((base == 0 || base == 2) &&
153 c == '0' && (*s == 'b' || *s == 'B')) {
154 c = s[1];
155 s += 2;
156 base = 2;
157 }
158 if (base == 0)
159 base = c == '0' ? 8 : 10;
160 cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
161 cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
162 for (acc = 0, any = 0;; c = *s++) {
163 if (isdigit(c))
164 c -= '0';
165 else if (isalpha(c))
166 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
167 else
168 break;
169 if (c >= base)
170 break;
171 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
172 any = -1;
173 else {
174 any = 1;
175 acc *= base;
176 acc += c;
177 }
178 }
179 if (any < 0) {
180 acc = ULONG_MAX;
181 // errno = ERANGE;
182 } else if (neg)
183 acc = -acc;
184 if (endptr != 0)
185 *endptr = (char *)(any ? s - 1 : nptr);
186 return (acc);
187 }