1c1dac77fSApple OSS Distributions /*
288cc0b97SApple OSS Distributions * Copyright (c) 1998-2016 Apple Inc. All rights reserved.
3c1dac77fSApple OSS Distributions *
4e13b1fa5SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5c1dac77fSApple OSS Distributions *
6e13b1fa5SApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code
7e13b1fa5SApple OSS Distributions * as defined in and that are subject to the Apple Public Source License
8e13b1fa5SApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in
9e13b1fa5SApple OSS Distributions * compliance with the License. The rights granted to you under the License
10e13b1fa5SApple OSS Distributions * may not be used to create, or enable the creation or redistribution of,
11e13b1fa5SApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to
12e13b1fa5SApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any
13e13b1fa5SApple OSS Distributions * terms of an Apple operating system software license agreement.
14c1dac77fSApple OSS Distributions *
15e13b1fa5SApple OSS Distributions * Please obtain a copy of the License at
16e13b1fa5SApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file.
17e13b1fa5SApple OSS Distributions *
18e13b1fa5SApple OSS Distributions * The Original Code and all software distributed under the License are
19e13b1fa5SApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20c1dac77fSApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21c1dac77fSApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22e13b1fa5SApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23e13b1fa5SApple OSS Distributions * Please see the License for the specific language governing rights and
24e13b1fa5SApple OSS Distributions * limitations under the License.
25c1dac77fSApple OSS Distributions *
26e13b1fa5SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27c1dac77fSApple OSS Distributions */
283ca3bd55SApple OSS Distributions
293ca3bd55SApple OSS Distributions /*
303ca3bd55SApple OSS Distributions * Copyright (c) 1995 NeXT Computer, Inc. All rights reserved.
31c1dac77fSApple OSS Distributions *
32c1dac77fSApple OSS Distributions * strol.c - The functions strtol() & strtoul() are exported as public API
33c1dac77fSApple OSS Distributions * via the header file ~driverkit/generalFuncs.h
34c1dac77fSApple OSS Distributions *
35c1dac77fSApple OSS Distributions * HISTORY
36c1dac77fSApple OSS Distributions * 25-Oct-1995 Dean Reece at NeXT
37c1dac77fSApple OSS Distributions * Created based on BSD4.4's strtol.c & strtoul.c.
38c1dac77fSApple OSS Distributions * Removed dependency on _ctype_ by static versions of isupper()...
39c1dac77fSApple OSS Distributions * Added support for "0b101..." binary constants.
40c1dac77fSApple OSS Distributions * Commented out references to errno.
41c1dac77fSApple OSS Distributions */
42c1dac77fSApple OSS Distributions
433ca3bd55SApple OSS Distributions /*
44c1dac77fSApple OSS Distributions * Copyright (c) 1990, 1993
45c1dac77fSApple OSS Distributions * The Regents of the University of California. All rights reserved.
46c1dac77fSApple OSS Distributions *
47c1dac77fSApple OSS Distributions * Redistribution and use in source and binary forms, with or without
48c1dac77fSApple OSS Distributions * modification, are permitted provided that the following conditions
49c1dac77fSApple OSS Distributions * are met:
50c1dac77fSApple OSS Distributions * 1. Redistributions of source code must retain the above copyright
51c1dac77fSApple OSS Distributions * notice, this list of conditions and the following disclaimer.
52c1dac77fSApple OSS Distributions * 2. Redistributions in binary form must reproduce the above copyright
53c1dac77fSApple OSS Distributions * notice, this list of conditions and the following disclaimer in the
54c1dac77fSApple OSS Distributions * documentation and/or other materials provided with the distribution.
55c1dac77fSApple OSS Distributions * 3. All advertising materials mentioning features or use of this software
56c1dac77fSApple OSS Distributions * must display the following acknowledgement:
57c1dac77fSApple OSS Distributions * This product includes software developed by the University of
58c1dac77fSApple OSS Distributions * California, Berkeley and its contributors.
59c1dac77fSApple OSS Distributions * 4. Neither the name of the University nor the names of its contributors
60c1dac77fSApple OSS Distributions * may be used to endorse or promote products derived from this software
61c1dac77fSApple OSS Distributions * without specific prior written permission.
62c1dac77fSApple OSS Distributions *
63c1dac77fSApple OSS Distributions * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
64c1dac77fSApple OSS Distributions * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
65c1dac77fSApple OSS Distributions * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
66c1dac77fSApple OSS Distributions * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
67c1dac77fSApple OSS Distributions * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
68c1dac77fSApple OSS Distributions * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
69c1dac77fSApple OSS Distributions * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
70c1dac77fSApple OSS Distributions * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
71c1dac77fSApple OSS Distributions * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
72c1dac77fSApple OSS Distributions * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
73c1dac77fSApple OSS Distributions * SUCH DAMAGE.
74c1dac77fSApple OSS Distributions */
75c1dac77fSApple OSS Distributions
76c1dac77fSApple OSS Distributions /*
77c1dac77fSApple OSS Distributions #include <string.h>
78c1dac77fSApple OSS Distributions #include <stdlib.h>
79c1dac77fSApple OSS Distributions #include <limits.h>
80c1dac77fSApple OSS Distributions */
818149afccSApple OSS Distributions #include <sys/types.h>
82c1dac77fSApple OSS Distributions #include <machine/limits.h>
83c1dac77fSApple OSS Distributions
843ca3bd55SApple OSS Distributions
853ca3bd55SApple OSS Distributions long strtol(const char *nptr, char **endptr, int base);
863ca3bd55SApple OSS Distributions unsigned long strtoul(const char *nptr, char **endptr, int base);
873ca3bd55SApple OSS Distributions quad_t strtoq(const char *nptr, char **endptr, int base);
883ca3bd55SApple OSS Distributions u_quad_t strtouq(const char *nptr, char **endptr, int base);
893ca3bd55SApple OSS Distributions
903ca3bd55SApple OSS Distributions
91c1dac77fSApple OSS Distributions typedef int BOOL;
92c1dac77fSApple OSS Distributions
93c1dac77fSApple OSS Distributions static inline BOOL
isupper(char c)94c1dac77fSApple OSS Distributions isupper(char c)
95c1dac77fSApple OSS Distributions {
96a5e72196SApple OSS Distributions return c >= 'A' && c <= 'Z';
97c1dac77fSApple OSS Distributions }
98c1dac77fSApple OSS Distributions
99c1dac77fSApple OSS Distributions static inline BOOL
isalpha(char c)100c1dac77fSApple OSS Distributions isalpha(char c)
101c1dac77fSApple OSS Distributions {
102a5e72196SApple OSS Distributions return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
103c1dac77fSApple OSS Distributions }
104c1dac77fSApple OSS Distributions
105c1dac77fSApple OSS Distributions
106c1dac77fSApple OSS Distributions static inline BOOL
isspace(char c)107c1dac77fSApple OSS Distributions isspace(char c)
108c1dac77fSApple OSS Distributions {
109a5e72196SApple OSS Distributions return c == ' ' || c == '\t' || c == '\n' || c == '\12';
110c1dac77fSApple OSS Distributions }
111c1dac77fSApple OSS Distributions
112c1dac77fSApple OSS Distributions static inline BOOL
isdigit(char c)113c1dac77fSApple OSS Distributions isdigit(char c)
114c1dac77fSApple OSS Distributions {
115a5e72196SApple OSS Distributions return c >= '0' && c <= '9';
116c1dac77fSApple OSS Distributions }
117c1dac77fSApple OSS Distributions
118c1dac77fSApple OSS Distributions /*
119c1dac77fSApple OSS Distributions * Convert a string to a long integer.
120c1dac77fSApple OSS Distributions *
121c1dac77fSApple OSS Distributions * Ignores `locale' stuff. Assumes that the upper and lower case
122c1dac77fSApple OSS Distributions * alphabets and digits are each contiguous.
123c1dac77fSApple OSS Distributions */
124c1dac77fSApple OSS Distributions long
strtol(const char * nptr,char ** endptr,int base)125e13b1fa5SApple OSS Distributions strtol(const char *nptr, char **endptr, int base)
126c1dac77fSApple OSS Distributions {
12788cc0b97SApple OSS Distributions const char *s = nptr;
12888cc0b97SApple OSS Distributions unsigned long acc;
12988cc0b97SApple OSS Distributions char c;
13088cc0b97SApple OSS Distributions unsigned long cutoff;
13188cc0b97SApple OSS Distributions int neg = 0, any, cutlim;
132c1dac77fSApple OSS Distributions
133c1dac77fSApple OSS Distributions /*
134c1dac77fSApple OSS Distributions * Skip white space and pick up leading +/- sign if any.
135c1dac77fSApple OSS Distributions * If base is 0, allow 0x for hex and 0 for octal, else
136c1dac77fSApple OSS Distributions * assume decimal; if base is already 16, allow 0x.
137c1dac77fSApple OSS Distributions */
138c1dac77fSApple OSS Distributions do {
139c1dac77fSApple OSS Distributions c = *s++;
140c1dac77fSApple OSS Distributions } while (isspace(c));
141c1dac77fSApple OSS Distributions if (c == '-') {
142c1dac77fSApple OSS Distributions neg = 1;
143c1dac77fSApple OSS Distributions c = *s++;
144a5e72196SApple OSS Distributions } else if (c == '+') {
145c1dac77fSApple OSS Distributions c = *s++;
146a5e72196SApple OSS Distributions }
147c1dac77fSApple OSS Distributions if ((base == 0 || base == 16) &&
148c1dac77fSApple OSS Distributions c == '0' && (*s == 'x' || *s == 'X')) {
149c1dac77fSApple OSS Distributions c = s[1];
150c1dac77fSApple OSS Distributions s += 2;
151c1dac77fSApple OSS Distributions base = 16;
152c1dac77fSApple OSS Distributions } else if ((base == 0 || base == 2) &&
153c1dac77fSApple OSS Distributions c == '0' && (*s == 'b' || *s == 'B')) {
154c1dac77fSApple OSS Distributions c = s[1];
155c1dac77fSApple OSS Distributions s += 2;
156c1dac77fSApple OSS Distributions base = 2;
157c1dac77fSApple OSS Distributions }
158a5e72196SApple OSS Distributions if (base == 0) {
159c1dac77fSApple OSS Distributions base = c == '0' ? 8 : 10;
160a5e72196SApple OSS Distributions }
161c1dac77fSApple OSS Distributions
162c1dac77fSApple OSS Distributions /*
163c1dac77fSApple OSS Distributions * Compute the cutoff value between legal numbers and illegal
164c1dac77fSApple OSS Distributions * numbers. That is the largest legal value, divided by the
165c1dac77fSApple OSS Distributions * base. An input number that is greater than this value, if
166c1dac77fSApple OSS Distributions * followed by a legal input character, is too big. One that
167c1dac77fSApple OSS Distributions * is equal to this value may be valid or not; the limit
168c1dac77fSApple OSS Distributions * between valid and invalid numbers is then based on the last
169c1dac77fSApple OSS Distributions * digit. For instance, if the range for longs is
170c1dac77fSApple OSS Distributions * [-2147483648..2147483647] and the input base is 10,
171c1dac77fSApple OSS Distributions * cutoff will be set to 214748364 and cutlim to either
172c1dac77fSApple OSS Distributions * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
173c1dac77fSApple OSS Distributions * a value > 214748364, or equal but the next digit is > 7 (or 8),
174c1dac77fSApple OSS Distributions * the number is too big, and we will return a range error.
175c1dac77fSApple OSS Distributions *
176c1dac77fSApple OSS Distributions * Set any if any `digits' consumed; make it negative to indicate
177c1dac77fSApple OSS Distributions * overflow.
178c1dac77fSApple OSS Distributions */
179c1dac77fSApple OSS Distributions cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
180*bb611c8fSApple OSS Distributions cutlim = ((int)(cutoff % (unsigned long)base));
181c1dac77fSApple OSS Distributions cutoff /= (unsigned long)base;
182c1dac77fSApple OSS Distributions for (acc = 0, any = 0;; c = *s++) {
183a5e72196SApple OSS Distributions if (isdigit(c)) {
184c1dac77fSApple OSS Distributions c -= '0';
185a5e72196SApple OSS Distributions } else if (isalpha(c)) {
186c1dac77fSApple OSS Distributions c -= isupper(c) ? 'A' - 10 : 'a' - 10;
187a5e72196SApple OSS Distributions } else {
188c1dac77fSApple OSS Distributions break;
189a5e72196SApple OSS Distributions }
190a5e72196SApple OSS Distributions if (c >= base) {
191c1dac77fSApple OSS Distributions break;
192a5e72196SApple OSS Distributions }
193a5e72196SApple OSS Distributions if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) {
194c1dac77fSApple OSS Distributions any = -1;
195a5e72196SApple OSS Distributions } else {
196c1dac77fSApple OSS Distributions any = 1;
197c1dac77fSApple OSS Distributions acc *= base;
198c1dac77fSApple OSS Distributions acc += c;
199c1dac77fSApple OSS Distributions }
200c1dac77fSApple OSS Distributions }
201c1dac77fSApple OSS Distributions if (any < 0) {
202c1dac77fSApple OSS Distributions acc = neg ? LONG_MIN : LONG_MAX;
203c1dac77fSApple OSS Distributions // errno = ERANGE;
204a5e72196SApple OSS Distributions } else if (neg) {
205c1dac77fSApple OSS Distributions acc = -acc;
2063ca3bd55SApple OSS Distributions }
207a5e72196SApple OSS Distributions if (endptr != 0) {
208a5e72196SApple OSS Distributions if (any) {
209a5e72196SApple OSS Distributions *endptr = __CAST_AWAY_QUALIFIER(s - 1, const, char *);
210a5e72196SApple OSS Distributions } else {
2113ca3bd55SApple OSS Distributions *endptr = __CAST_AWAY_QUALIFIER(nptr, const, char *);
2123ca3bd55SApple OSS Distributions }
2133ca3bd55SApple OSS Distributions }
214a5e72196SApple OSS Distributions return acc;
215c1dac77fSApple OSS Distributions }
216c1dac77fSApple OSS Distributions
217c1dac77fSApple OSS Distributions unsigned long
strtoul(const char * nptr,char ** endptr,int base)218e13b1fa5SApple OSS Distributions strtoul(const char *nptr, char **endptr, int base)
219c1dac77fSApple OSS Distributions {
22088cc0b97SApple OSS Distributions const char *s = nptr;
22188cc0b97SApple OSS Distributions unsigned long acc;
22288cc0b97SApple OSS Distributions char c;
22388cc0b97SApple OSS Distributions unsigned long cutoff;
22488cc0b97SApple OSS Distributions int neg = 0, any, cutlim;
225c1dac77fSApple OSS Distributions
226c1dac77fSApple OSS Distributions /*
227c1dac77fSApple OSS Distributions * See strtol for comments as to the logic used.
228c1dac77fSApple OSS Distributions */
229c1dac77fSApple OSS Distributions do {
230c1dac77fSApple OSS Distributions c = *s++;
231c1dac77fSApple OSS Distributions } while (isspace(c));
232c1dac77fSApple OSS Distributions if (c == '-') {
233c1dac77fSApple OSS Distributions neg = 1;
234c1dac77fSApple OSS Distributions c = *s++;
235a5e72196SApple OSS Distributions } else if (c == '+') {
236c1dac77fSApple OSS Distributions c = *s++;
237a5e72196SApple OSS Distributions }
238c1dac77fSApple OSS Distributions if ((base == 0 || base == 16) &&
239c1dac77fSApple OSS Distributions c == '0' && (*s == 'x' || *s == 'X')) {
240c1dac77fSApple OSS Distributions c = s[1];
241c1dac77fSApple OSS Distributions s += 2;
242c1dac77fSApple OSS Distributions base = 16;
243c1dac77fSApple OSS Distributions } else if ((base == 0 || base == 2) &&
244c1dac77fSApple OSS Distributions c == '0' && (*s == 'b' || *s == 'B')) {
245c1dac77fSApple OSS Distributions c = s[1];
246c1dac77fSApple OSS Distributions s += 2;
247c1dac77fSApple OSS Distributions base = 2;
248c1dac77fSApple OSS Distributions }
249a5e72196SApple OSS Distributions if (base == 0) {
250c1dac77fSApple OSS Distributions base = c == '0' ? 8 : 10;
251a5e72196SApple OSS Distributions }
252c1dac77fSApple OSS Distributions cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
253*bb611c8fSApple OSS Distributions cutlim = ((int)((unsigned long)ULONG_MAX % (unsigned long)base));
254c1dac77fSApple OSS Distributions for (acc = 0, any = 0;; c = *s++) {
255a5e72196SApple OSS Distributions if (isdigit(c)) {
256c1dac77fSApple OSS Distributions c -= '0';
257a5e72196SApple OSS Distributions } else if (isalpha(c)) {
258c1dac77fSApple OSS Distributions c -= isupper(c) ? 'A' - 10 : 'a' - 10;
259a5e72196SApple OSS Distributions } else {
260c1dac77fSApple OSS Distributions break;
261a5e72196SApple OSS Distributions }
262a5e72196SApple OSS Distributions if (c >= base) {
263c1dac77fSApple OSS Distributions break;
264a5e72196SApple OSS Distributions }
265a5e72196SApple OSS Distributions if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) {
266c1dac77fSApple OSS Distributions any = -1;
267a5e72196SApple OSS Distributions } else {
268c1dac77fSApple OSS Distributions any = 1;
269c1dac77fSApple OSS Distributions acc *= base;
270c1dac77fSApple OSS Distributions acc += c;
271c1dac77fSApple OSS Distributions }
272c1dac77fSApple OSS Distributions }
273c1dac77fSApple OSS Distributions if (any < 0) {
274c1dac77fSApple OSS Distributions acc = ULONG_MAX;
275c1dac77fSApple OSS Distributions // errno = ERANGE;
276a5e72196SApple OSS Distributions } else if (neg) {
277c1dac77fSApple OSS Distributions acc = -acc;
2783ca3bd55SApple OSS Distributions }
279a5e72196SApple OSS Distributions if (endptr != 0) {
280a5e72196SApple OSS Distributions if (any) {
281a5e72196SApple OSS Distributions *endptr = __CAST_AWAY_QUALIFIER(s - 1, const, char *);
282a5e72196SApple OSS Distributions } else {
2833ca3bd55SApple OSS Distributions *endptr = __CAST_AWAY_QUALIFIER(nptr, const, char *);
2843ca3bd55SApple OSS Distributions }
2853ca3bd55SApple OSS Distributions }
2863ca3bd55SApple OSS Distributions
287a5e72196SApple OSS Distributions return acc;
288c1dac77fSApple OSS Distributions }
289c1dac77fSApple OSS Distributions
290c1dac77fSApple OSS Distributions /*
2918149afccSApple OSS Distributions * Convert a string to a quad integer.
2928149afccSApple OSS Distributions *
2938149afccSApple OSS Distributions * Ignores `locale' stuff. Assumes that the upper and lower case
2948149afccSApple OSS Distributions * alphabets and digits are each contiguous.
2958149afccSApple OSS Distributions */
2968149afccSApple OSS Distributions quad_t
strtoq(const char * nptr,char ** endptr,int base)297e13b1fa5SApple OSS Distributions strtoq(const char *nptr, char **endptr, int base)
2988149afccSApple OSS Distributions {
29988cc0b97SApple OSS Distributions const char *s;
30088cc0b97SApple OSS Distributions u_quad_t acc;
30188cc0b97SApple OSS Distributions char c;
30288cc0b97SApple OSS Distributions u_quad_t qbase, cutoff;
30388cc0b97SApple OSS Distributions int neg, any, cutlim;
3048149afccSApple OSS Distributions
3058149afccSApple OSS Distributions /*
3068149afccSApple OSS Distributions * Skip white space and pick up leading +/- sign if any.
3078149afccSApple OSS Distributions * If base is 0, allow 0x for hex and 0 for octal, else
3088149afccSApple OSS Distributions * assume decimal; if base is already 16, allow 0x.
3098149afccSApple OSS Distributions */
3108149afccSApple OSS Distributions s = nptr;
3118149afccSApple OSS Distributions do {
3128149afccSApple OSS Distributions c = *s++;
3138149afccSApple OSS Distributions } while (isspace(c));
3148149afccSApple OSS Distributions if (c == '-') {
3158149afccSApple OSS Distributions neg = 1;
3168149afccSApple OSS Distributions c = *s++;
3178149afccSApple OSS Distributions } else {
3188149afccSApple OSS Distributions neg = 0;
319a5e72196SApple OSS Distributions if (c == '+') {
3208149afccSApple OSS Distributions c = *s++;
3218149afccSApple OSS Distributions }
322a5e72196SApple OSS Distributions }
3238149afccSApple OSS Distributions if ((base == 0 || base == 16) &&
3248149afccSApple OSS Distributions c == '0' && (*s == 'x' || *s == 'X')) {
3258149afccSApple OSS Distributions c = s[1];
3268149afccSApple OSS Distributions s += 2;
3278149afccSApple OSS Distributions base = 16;
3288149afccSApple OSS Distributions }
329a5e72196SApple OSS Distributions if (base == 0) {
3308149afccSApple OSS Distributions base = c == '0' ? 8 : 10;
331a5e72196SApple OSS Distributions }
3328149afccSApple OSS Distributions
3338149afccSApple OSS Distributions /*
3348149afccSApple OSS Distributions * Compute the cutoff value between legal numbers and illegal
3358149afccSApple OSS Distributions * numbers. That is the largest legal value, divided by the
3368149afccSApple OSS Distributions * base. An input number that is greater than this value, if
3378149afccSApple OSS Distributions * followed by a legal input character, is too big. One that
3388149afccSApple OSS Distributions * is equal to this value may be valid or not; the limit
3398149afccSApple OSS Distributions * between valid and invalid numbers is then based on the last
3408149afccSApple OSS Distributions * digit. For instance, if the range for quads is
3418149afccSApple OSS Distributions * [-9223372036854775808..9223372036854775807] and the input base
3428149afccSApple OSS Distributions * is 10, cutoff will be set to 922337203685477580 and cutlim to
3438149afccSApple OSS Distributions * either 7 (neg==0) or 8 (neg==1), meaning that if we have
3448149afccSApple OSS Distributions * accumulated a value > 922337203685477580, or equal but the
3458149afccSApple OSS Distributions * next digit is > 7 (or 8), the number is too big, and we will
3468149afccSApple OSS Distributions * return a range error.
3478149afccSApple OSS Distributions *
3488149afccSApple OSS Distributions * Set any if any `digits' consumed; make it negative to indicate
3498149afccSApple OSS Distributions * overflow.
3508149afccSApple OSS Distributions */
3518149afccSApple OSS Distributions qbase = (unsigned)base;
3528149afccSApple OSS Distributions cutoff = neg ? -(u_quad_t)QUAD_MIN : QUAD_MAX;
353*bb611c8fSApple OSS Distributions cutlim = ((int)(cutoff % qbase));
3548149afccSApple OSS Distributions cutoff /= qbase;
3558149afccSApple OSS Distributions for (acc = 0, any = 0;; c = *s++) {
356a5e72196SApple OSS Distributions if (isdigit(c)) {
3578149afccSApple OSS Distributions c -= '0';
358a5e72196SApple OSS Distributions } else if (isalpha(c)) {
3598149afccSApple OSS Distributions c -= isupper(c) ? 'A' - 10 : 'a' - 10;
360a5e72196SApple OSS Distributions } else {
3618149afccSApple OSS Distributions break;
362a5e72196SApple OSS Distributions }
363a5e72196SApple OSS Distributions if (c >= base) {
3648149afccSApple OSS Distributions break;
365a5e72196SApple OSS Distributions }
366a5e72196SApple OSS Distributions if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) {
3678149afccSApple OSS Distributions any = -1;
368a5e72196SApple OSS Distributions } else {
3698149afccSApple OSS Distributions any = 1;
3708149afccSApple OSS Distributions acc *= qbase;
3718149afccSApple OSS Distributions acc += c;
3728149afccSApple OSS Distributions }
3738149afccSApple OSS Distributions }
3748149afccSApple OSS Distributions if (any < 0) {
3758149afccSApple OSS Distributions acc = neg ? QUAD_MIN : QUAD_MAX;
3768149afccSApple OSS Distributions // errno = ERANGE;
377a5e72196SApple OSS Distributions } else if (neg) {
3788149afccSApple OSS Distributions acc = -acc;
3793ca3bd55SApple OSS Distributions }
380a5e72196SApple OSS Distributions if (endptr != 0) {
381a5e72196SApple OSS Distributions if (any) {
382a5e72196SApple OSS Distributions *endptr = __CAST_AWAY_QUALIFIER(s - 1, const, char *);
383a5e72196SApple OSS Distributions } else {
3843ca3bd55SApple OSS Distributions *endptr = __CAST_AWAY_QUALIFIER(nptr, const, char *);
3853ca3bd55SApple OSS Distributions }
3863ca3bd55SApple OSS Distributions }
3873ca3bd55SApple OSS Distributions
388a5e72196SApple OSS Distributions return acc;
3898149afccSApple OSS Distributions }
3908149afccSApple OSS Distributions
3918149afccSApple OSS Distributions
3928149afccSApple OSS Distributions /*
3938149afccSApple OSS Distributions * Convert a string to an unsigned quad integer.
3948149afccSApple OSS Distributions *
3958149afccSApple OSS Distributions * Ignores `locale' stuff. Assumes that the upper and lower case
3968149afccSApple OSS Distributions * alphabets and digits are each contiguous.
3978149afccSApple OSS Distributions */
3988149afccSApple OSS Distributions u_quad_t
strtouq(const char * nptr,char ** endptr,int base)399e13b1fa5SApple OSS Distributions strtouq(const char *nptr,
400e13b1fa5SApple OSS Distributions char **endptr,
40188cc0b97SApple OSS Distributions int base)
4028149afccSApple OSS Distributions {
40388cc0b97SApple OSS Distributions const char *s = nptr;
40488cc0b97SApple OSS Distributions u_quad_t acc;
40588cc0b97SApple OSS Distributions char c;
40688cc0b97SApple OSS Distributions u_quad_t qbase, cutoff;
40788cc0b97SApple OSS Distributions int neg, any, cutlim;
4088149afccSApple OSS Distributions
4098149afccSApple OSS Distributions /*
4108149afccSApple OSS Distributions * See strtoq for comments as to the logic used.
4118149afccSApple OSS Distributions */
4128149afccSApple OSS Distributions s = nptr;
4138149afccSApple OSS Distributions do {
4148149afccSApple OSS Distributions c = *s++;
4158149afccSApple OSS Distributions } while (isspace(c));
4168149afccSApple OSS Distributions if (c == '-') {
4178149afccSApple OSS Distributions neg = 1;
4188149afccSApple OSS Distributions c = *s++;
4198149afccSApple OSS Distributions } else {
4208149afccSApple OSS Distributions neg = 0;
421a5e72196SApple OSS Distributions if (c == '+') {
4228149afccSApple OSS Distributions c = *s++;
4238149afccSApple OSS Distributions }
424a5e72196SApple OSS Distributions }
4258149afccSApple OSS Distributions if ((base == 0 || base == 16) &&
4268149afccSApple OSS Distributions c == '0' && (*s == 'x' || *s == 'X')) {
4278149afccSApple OSS Distributions c = s[1];
4288149afccSApple OSS Distributions s += 2;
4298149afccSApple OSS Distributions base = 16;
4308149afccSApple OSS Distributions }
431a5e72196SApple OSS Distributions if (base == 0) {
4328149afccSApple OSS Distributions base = c == '0' ? 8 : 10;
433a5e72196SApple OSS Distributions }
4348149afccSApple OSS Distributions qbase = (unsigned)base;
4358149afccSApple OSS Distributions cutoff = (u_quad_t)UQUAD_MAX / qbase;
436*bb611c8fSApple OSS Distributions cutlim = ((int)((u_quad_t)UQUAD_MAX % qbase));
4378149afccSApple OSS Distributions for (acc = 0, any = 0;; c = *s++) {
438a5e72196SApple OSS Distributions if (isdigit(c)) {
4398149afccSApple OSS Distributions c -= '0';
440a5e72196SApple OSS Distributions } else if (isalpha(c)) {
4418149afccSApple OSS Distributions c -= isupper(c) ? 'A' - 10 : 'a' - 10;
442a5e72196SApple OSS Distributions } else {
4438149afccSApple OSS Distributions break;
444a5e72196SApple OSS Distributions }
445a5e72196SApple OSS Distributions if (c >= base) {
4468149afccSApple OSS Distributions break;
447a5e72196SApple OSS Distributions }
448a5e72196SApple OSS Distributions if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) {
4498149afccSApple OSS Distributions any = -1;
450a5e72196SApple OSS Distributions } else {
4518149afccSApple OSS Distributions any = 1;
4528149afccSApple OSS Distributions acc *= qbase;
4538149afccSApple OSS Distributions acc += c;
4548149afccSApple OSS Distributions }
4558149afccSApple OSS Distributions }
4568149afccSApple OSS Distributions if (any < 0) {
4578149afccSApple OSS Distributions acc = UQUAD_MAX;
4588149afccSApple OSS Distributions // errno = ERANGE;
459a5e72196SApple OSS Distributions } else if (neg) {
4608149afccSApple OSS Distributions acc = -acc;
4613ca3bd55SApple OSS Distributions }
462a5e72196SApple OSS Distributions if (endptr != 0) {
463a5e72196SApple OSS Distributions if (any) {
464a5e72196SApple OSS Distributions *endptr = __CAST_AWAY_QUALIFIER(s - 1, const, char *);
465a5e72196SApple OSS Distributions } else {
4663ca3bd55SApple OSS Distributions *endptr = __CAST_AWAY_QUALIFIER(nptr, const, char *);
4673ca3bd55SApple OSS Distributions }
4683ca3bd55SApple OSS Distributions }
4693ca3bd55SApple OSS Distributions
470a5e72196SApple OSS Distributions return acc;
4718149afccSApple OSS Distributions }
472