1/*
2 * Copyright (c) 1998-2016 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29/*
30 * Copyright (c) 1995 NeXT Computer, Inc. All rights reserved.
31 *
32 * strol.c - The functions strtol() & strtoul() are exported as public API
33 * via the header file ~driverkit/generalFuncs.h
34 *
35 * HISTORY
36 * 25-Oct-1995 Dean Reece at NeXT
37 * Created based on BSD4.4's strtol.c & strtoul.c.
38 * Removed dependency on _ctype_ by static versions of isupper()...
39 * Added support for "0b101..." binary constants.
40 * Commented out references to errno.
41 */
42
43/*
44 * Copyright (c) 1990, 1993
45 * The Regents of the University of California. All rights reserved.
46 *
47 * Redistribution and use in source and binary forms, with or without
48 * modification, are permitted provided that the following conditions
49 * are met:
50 * 1. Redistributions of source code must retain the above copyright
51 * notice, this list of conditions and the following disclaimer.
52 * 2. Redistributions in binary form must reproduce the above copyright
53 * notice, this list of conditions and the following disclaimer in the
54 * documentation and/or other materials provided with the distribution.
55 * 3. All advertising materials mentioning features or use of this software
56 * must display the following acknowledgement:
57 * This product includes software developed by the University of
58 * California, Berkeley and its contributors.
59 * 4. Neither the name of the University nor the names of its contributors
60 * may be used to endorse or promote products derived from this software
61 * without specific prior written permission.
62 *
63 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
64 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
65 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
66 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
67 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
68 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
69 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
70 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
71 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
72 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
73 * SUCH DAMAGE.
74 */
75
76/*
77 #include <string.h>
78 #include <stdlib.h>
79 #include <limits.h>
80 */
81#include <sys/types.h>
82#include <machine/limits.h>
83
84
85long strtol(const char *nptr, char **endptr, int base);
86unsigned long strtoul(const char *nptr, char **endptr, int base);
87quad_t strtoq(const char *nptr, char **endptr, int base);
88u_quad_t strtouq(const char *nptr, char **endptr, int base);
89
90
91typedef int BOOL;
92
93static inline BOOL
94isupper(char c)
95{
96 return c >= 'A' && c <= 'Z';
97}
98
99static inline BOOL
100isalpha(char c)
101{
102 return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
103}
104
105
106static inline BOOL
107isspace(char c)
108{
109 return c == ' ' || c == '\t' || c == '\n' || c == '\12';
110}
111
112static inline BOOL
113isdigit(char c)
114{
115 return c >= '0' && c <= '9';
116}
117
118/*
119 * Convert a string to a long integer.
120 *
121 * Ignores `locale' stuff. Assumes that the upper and lower case
122 * alphabets and digits are each contiguous.
123 */
124long
125strtol(const char *nptr, char **endptr, int base)
126{
127 const char *s = nptr;
128 unsigned long acc;
129 char c;
130 unsigned long cutoff;
131 int neg = 0, any, cutlim;
132
133 /*
134 * Skip white space and pick up leading +/- sign if any.
135 * If base is 0, allow 0x for hex and 0 for octal, else
136 * assume decimal; if base is already 16, allow 0x.
137 */
138 do {
139 c = *s++;
140 } while (isspace(c));
141 if (c == '-') {
142 neg = 1;
143 c = *s++;
144 } else if (c == '+') {
145 c = *s++;
146 }
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 }
161
162 /*
163 * Compute the cutoff value between legal numbers and illegal
164 * numbers. That is the largest legal value, divided by the
165 * base. An input number that is greater than this value, if
166 * followed by a legal input character, is too big. One that
167 * is equal to this value may be valid or not; the limit
168 * between valid and invalid numbers is then based on the last
169 * digit. For instance, if the range for longs is
170 * [-2147483648..2147483647] and the input base is 10,
171 * cutoff will be set to 214748364 and cutlim to either
172 * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
173 * a value > 214748364, or equal but the next digit is > 7 (or 8),
174 * the number is too big, and we will return a range error.
175 *
176 * Set any if any `digits' consumed; make it negative to indicate
177 * overflow.
178 */
179 cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
180 cutlim = ((int)(cutoff % (unsigned long)base));
181 cutoff /= (unsigned long)base;
182 for (acc = 0, any = 0;; c = *s++) {
183 if (isdigit(c)) {
184 c -= '0';
185 } else if (isalpha(c)) {
186 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
187 } else {
188 break;
189 }
190 if (c >= base) {
191 break;
192 }
193 if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) {
194 any = -1;
195 } else {
196 any = 1;
197 acc *= base;
198 acc += c;
199 }
200 }
201 if (any < 0) {
202 acc = neg ? LONG_MIN : LONG_MAX;
203// errno = ERANGE;
204 } else if (neg) {
205 acc = -acc;
206 }
207 if (endptr != 0) {
208 if (any) {
209 *endptr = __CAST_AWAY_QUALIFIER(s - 1, const, char *);
210 } else {
211 *endptr = __CAST_AWAY_QUALIFIER(nptr, const, char *);
212 }
213 }
214 return acc;
215}
216
217unsigned long
218strtoul(const char *nptr, char **endptr, int base)
219{
220 const char *s = nptr;
221 unsigned long acc;
222 char c;
223 unsigned long cutoff;
224 int neg = 0, any, cutlim;
225
226 /*
227 * See strtol for comments as to the logic used.
228 */
229 do {
230 c = *s++;
231 } while (isspace(c));
232 if (c == '-') {
233 neg = 1;
234 c = *s++;
235 } else if (c == '+') {
236 c = *s++;
237 }
238 if ((base == 0 || base == 16) &&
239 c == '0' && (*s == 'x' || *s == 'X')) {
240 c = s[1];
241 s += 2;
242 base = 16;
243 } else if ((base == 0 || base == 2) &&
244 c == '0' && (*s == 'b' || *s == 'B')) {
245 c = s[1];
246 s += 2;
247 base = 2;
248 }
249 if (base == 0) {
250 base = c == '0' ? 8 : 10;
251 }
252 cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
253 cutlim = ((int)((unsigned long)ULONG_MAX % (unsigned long)base));
254 for (acc = 0, any = 0;; c = *s++) {
255 if (isdigit(c)) {
256 c -= '0';
257 } else if (isalpha(c)) {
258 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
259 } else {
260 break;
261 }
262 if (c >= base) {
263 break;
264 }
265 if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) {
266 any = -1;
267 } else {
268 any = 1;
269 acc *= base;
270 acc += c;
271 }
272 }
273 if (any < 0) {
274 acc = ULONG_MAX;
275// errno = ERANGE;
276 } else if (neg) {
277 acc = -acc;
278 }
279 if (endptr != 0) {
280 if (any) {
281 *endptr = __CAST_AWAY_QUALIFIER(s - 1, const, char *);
282 } else {
283 *endptr = __CAST_AWAY_QUALIFIER(nptr, const, char *);
284 }
285 }
286
287 return acc;
288}
289
290/*
291 * Convert a string to a quad integer.
292 *
293 * Ignores `locale' stuff. Assumes that the upper and lower case
294 * alphabets and digits are each contiguous.
295 */
296quad_t
297strtoq(const char *nptr, char **endptr, int base)
298{
299 const char *s;
300 u_quad_t acc;
301 char c;
302 u_quad_t qbase, cutoff;
303 int neg, any, cutlim;
304
305 /*
306 * Skip white space and pick up leading +/- sign if any.
307 * If base is 0, allow 0x for hex and 0 for octal, else
308 * assume decimal; if base is already 16, allow 0x.
309 */
310 s = nptr;
311 do {
312 c = *s++;
313 } while (isspace(c));
314 if (c == '-') {
315 neg = 1;
316 c = *s++;
317 } else {
318 neg = 0;
319 if (c == '+') {
320 c = *s++;
321 }
322 }
323 if ((base == 0 || base == 16) &&
324 c == '0' && (*s == 'x' || *s == 'X')) {
325 c = s[1];
326 s += 2;
327 base = 16;
328 }
329 if (base == 0) {
330 base = c == '0' ? 8 : 10;
331 }
332
333 /*
334 * Compute the cutoff value between legal numbers and illegal
335 * numbers. That is the largest legal value, divided by the
336 * base. An input number that is greater than this value, if
337 * followed by a legal input character, is too big. One that
338 * is equal to this value may be valid or not; the limit
339 * between valid and invalid numbers is then based on the last
340 * digit. For instance, if the range for quads is
341 * [-9223372036854775808..9223372036854775807] and the input base
342 * is 10, cutoff will be set to 922337203685477580 and cutlim to
343 * either 7 (neg==0) or 8 (neg==1), meaning that if we have
344 * accumulated a value > 922337203685477580, or equal but the
345 * next digit is > 7 (or 8), the number is too big, and we will
346 * return a range error.
347 *
348 * Set any if any `digits' consumed; make it negative to indicate
349 * overflow.
350 */
351 qbase = (unsigned)base;
352 cutoff = neg ? -(u_quad_t)QUAD_MIN : QUAD_MAX;
353 cutlim = ((int)(cutoff % qbase));
354 cutoff /= qbase;
355 for (acc = 0, any = 0;; c = *s++) {
356 if (isdigit(c)) {
357 c -= '0';
358 } else if (isalpha(c)) {
359 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
360 } else {
361 break;
362 }
363 if (c >= base) {
364 break;
365 }
366 if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) {
367 any = -1;
368 } else {
369 any = 1;
370 acc *= qbase;
371 acc += c;
372 }
373 }
374 if (any < 0) {
375 acc = neg ? QUAD_MIN : QUAD_MAX;
376// errno = ERANGE;
377 } else if (neg) {
378 acc = -acc;
379 }
380 if (endptr != 0) {
381 if (any) {
382 *endptr = __CAST_AWAY_QUALIFIER(s - 1, const, char *);
383 } else {
384 *endptr = __CAST_AWAY_QUALIFIER(nptr, const, char *);
385 }
386 }
387
388 return acc;
389}
390
391
392/*
393 * Convert a string to an unsigned quad integer.
394 *
395 * Ignores `locale' stuff. Assumes that the upper and lower case
396 * alphabets and digits are each contiguous.
397 */
398u_quad_t
399strtouq(const char *nptr,
400 char **endptr,
401 int base)
402{
403 const char *s = nptr;
404 u_quad_t acc;
405 char c;
406 u_quad_t qbase, cutoff;
407 int neg, any, cutlim;
408
409 /*
410 * See strtoq for comments as to the logic used.
411 */
412 s = nptr;
413 do {
414 c = *s++;
415 } while (isspace(c));
416 if (c == '-') {
417 neg = 1;
418 c = *s++;
419 } else {
420 neg = 0;
421 if (c == '+') {
422 c = *s++;
423 }
424 }
425 if ((base == 0 || base == 16) &&
426 c == '0' && (*s == 'x' || *s == 'X')) {
427 c = s[1];
428 s += 2;
429 base = 16;
430 }
431 if (base == 0) {
432 base = c == '0' ? 8 : 10;
433 }
434 qbase = (unsigned)base;
435 cutoff = (u_quad_t)UQUAD_MAX / qbase;
436 cutlim = ((int)((u_quad_t)UQUAD_MAX % qbase));
437 for (acc = 0, any = 0;; c = *s++) {
438 if (isdigit(c)) {
439 c -= '0';
440 } else if (isalpha(c)) {
441 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
442 } else {
443 break;
444 }
445 if (c >= base) {
446 break;
447 }
448 if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) {
449 any = -1;
450 } else {
451 any = 1;
452 acc *= qbase;
453 acc += c;
454 }
455 }
456 if (any < 0) {
457 acc = UQUAD_MAX;
458// errno = ERANGE;
459 } else if (neg) {
460 acc = -acc;
461 }
462 if (endptr != 0) {
463 if (any) {
464 *endptr = __CAST_AWAY_QUALIFIER(s - 1, const, char *);
465 } else {
466 *endptr = __CAST_AWAY_QUALIFIER(nptr, const, char *);
467 }
468 }
469
470 return acc;
471}
472