xref: /optee_os/lib/libutils/isoc/newlib/strtoul.c (revision b38854bd5efa2eeef5945fa1af011e36103c2222)
1*b38854bdSBryan O'Donoghue // SPDX-License-Identifier: BSD-3-Clause
2*b38854bdSBryan O'Donoghue /*
3*b38854bdSBryan O'Donoghue  * Copyright (c) 1994-2009  Red Hat, Inc.
4*b38854bdSBryan O'Donoghue  * All rights reserved.
5*b38854bdSBryan O'Donoghue  *
6*b38854bdSBryan O'Donoghue  * Redistribution and use in source and binary forms, with or without
7*b38854bdSBryan O'Donoghue  * modification, are permitted provided that the following conditions are met:
8*b38854bdSBryan O'Donoghue  *
9*b38854bdSBryan O'Donoghue  * 1. Redistributions of source code must retain the above copyright notice,
10*b38854bdSBryan O'Donoghue  * this list of conditions and the following disclaimer.
11*b38854bdSBryan O'Donoghue  *
12*b38854bdSBryan O'Donoghue  * 2. Redistributions in binary form must reproduce the above copyright notice,
13*b38854bdSBryan O'Donoghue  * this list of conditions and the following disclaimer in the documentation
14*b38854bdSBryan O'Donoghue  * and/or other materials provided with the distribution.
15*b38854bdSBryan O'Donoghue  *
16*b38854bdSBryan O'Donoghue  * 3. Neither the name of the copyright holder nor the names of its
17*b38854bdSBryan O'Donoghue  * contributors may be used to endorse or promote products derived from this
18*b38854bdSBryan O'Donoghue  * software without specific prior written permission.
19*b38854bdSBryan O'Donoghue  *
20*b38854bdSBryan O'Donoghue  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21*b38854bdSBryan O'Donoghue  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22*b38854bdSBryan O'Donoghue  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23*b38854bdSBryan O'Donoghue  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
24*b38854bdSBryan O'Donoghue  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25*b38854bdSBryan O'Donoghue  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26*b38854bdSBryan O'Donoghue  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27*b38854bdSBryan O'Donoghue  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28*b38854bdSBryan O'Donoghue  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29*b38854bdSBryan O'Donoghue  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30*b38854bdSBryan O'Donoghue  * POSSIBILITY OF SUCH DAMAGE.
31*b38854bdSBryan O'Donoghue  */
32*b38854bdSBryan O'Donoghue 
33*b38854bdSBryan O'Donoghue /*
34*b38854bdSBryan O'Donoghue FUNCTION
35*b38854bdSBryan O'Donoghue 	<<strtoul>>---string to unsigned long
36*b38854bdSBryan O'Donoghue 
37*b38854bdSBryan O'Donoghue INDEX
38*b38854bdSBryan O'Donoghue 	strtoul
39*b38854bdSBryan O'Donoghue INDEX
40*b38854bdSBryan O'Donoghue 	_strtoul_r
41*b38854bdSBryan O'Donoghue 
42*b38854bdSBryan O'Donoghue ANSI_SYNOPSIS
43*b38854bdSBryan O'Donoghue 	#include <stdlib.h>
44*b38854bdSBryan O'Donoghue         unsigned long strtoul(const char *<[s]>, char **<[ptr]>,
45*b38854bdSBryan O'Donoghue                               int <[base]>);
46*b38854bdSBryan O'Donoghue 
47*b38854bdSBryan O'Donoghue         unsigned long _strtoul(const char *<[s]>,
48*b38854bdSBryan O'Donoghue                               char **<[ptr]>, int <[base]>);
49*b38854bdSBryan O'Donoghue 
50*b38854bdSBryan O'Donoghue TRAD_SYNOPSIS
51*b38854bdSBryan O'Donoghue 	#include <stdlib.h>
52*b38854bdSBryan O'Donoghue         unsigned long strtoul(<[s]>, <[ptr]>, <[base]>)
53*b38854bdSBryan O'Donoghue         char *<[s]>;
54*b38854bdSBryan O'Donoghue         char **<[ptr]>;
55*b38854bdSBryan O'Donoghue         int <[base]>;
56*b38854bdSBryan O'Donoghue 
57*b38854bdSBryan O'Donoghue         unsigned long _strtoul(<[s]>, <[ptr]>, <[base]>)
58*b38854bdSBryan O'Donoghue         char *<[s]>;
59*b38854bdSBryan O'Donoghue         char **<[ptr]>;
60*b38854bdSBryan O'Donoghue         int <[base]>;
61*b38854bdSBryan O'Donoghue 
62*b38854bdSBryan O'Donoghue DESCRIPTION
63*b38854bdSBryan O'Donoghue The function <<strtoul>> converts the string <<*<[s]>>> to
64*b38854bdSBryan O'Donoghue an <<unsigned long>>. First, it breaks down the string into three parts:
65*b38854bdSBryan O'Donoghue leading whitespace, which is ignored; a subject string consisting
66*b38854bdSBryan O'Donoghue of the digits meaningful in the radix specified by <[base]>
67*b38854bdSBryan O'Donoghue (for example, <<0>> through <<7>> if the value of <[base]> is 8);
68*b38854bdSBryan O'Donoghue and a trailing portion consisting of one or more unparseable characters,
69*b38854bdSBryan O'Donoghue which always includes the terminating null character. Then, it attempts
70*b38854bdSBryan O'Donoghue to convert the subject string into an unsigned long integer, and returns the
71*b38854bdSBryan O'Donoghue result.
72*b38854bdSBryan O'Donoghue 
73*b38854bdSBryan O'Donoghue If the value of <[base]> is zero, the subject string is expected to look
74*b38854bdSBryan O'Donoghue like a normal C integer constant (save that no optional sign is permitted):
75*b38854bdSBryan O'Donoghue a possible <<0x>> indicating hexadecimal radix, and a number.
76*b38854bdSBryan O'Donoghue If <[base]> is between 2 and 36, the expected form of the subject is a
77*b38854bdSBryan O'Donoghue sequence of digits (which may include letters, depending on the
78*b38854bdSBryan O'Donoghue base) representing an integer in the radix specified by <[base]>.
79*b38854bdSBryan O'Donoghue The letters <<a>>--<<z>> (or <<A>>--<<Z>>) are used as digits valued from
80*b38854bdSBryan O'Donoghue 10 to 35. If <[base]> is 16, a leading <<0x>> is permitted.
81*b38854bdSBryan O'Donoghue 
82*b38854bdSBryan O'Donoghue The subject sequence is the longest initial sequence of the input
83*b38854bdSBryan O'Donoghue string that has the expected form, starting with the first
84*b38854bdSBryan O'Donoghue non-whitespace character.  If the string is empty or consists entirely
85*b38854bdSBryan O'Donoghue of whitespace, or if the first non-whitespace character is not a
86*b38854bdSBryan O'Donoghue permissible digit, the subject string is empty.
87*b38854bdSBryan O'Donoghue 
88*b38854bdSBryan O'Donoghue If the subject string is acceptable, and the value of <[base]> is zero,
89*b38854bdSBryan O'Donoghue <<strtoul>> attempts to determine the radix from the input string. A
90*b38854bdSBryan O'Donoghue string with a leading <<0x>> is treated as a hexadecimal value; a string with
91*b38854bdSBryan O'Donoghue a leading <<0>> and no <<x>> is treated as octal; all other strings are
92*b38854bdSBryan O'Donoghue treated as decimal. If <[base]> is between 2 and 36, it is used as the
93*b38854bdSBryan O'Donoghue conversion radix, as described above. Finally, a pointer to the first
94*b38854bdSBryan O'Donoghue character past the converted subject string is stored in <[ptr]>, if
95*b38854bdSBryan O'Donoghue <[ptr]> is not <<NULL>>.
96*b38854bdSBryan O'Donoghue 
97*b38854bdSBryan O'Donoghue If the subject string is empty (that is, if <<*>><[s]> does not start
98*b38854bdSBryan O'Donoghue with a substring in acceptable form), no conversion
99*b38854bdSBryan O'Donoghue is performed and the value of <[s]> is stored in <[ptr]> (if <[ptr]> is
100*b38854bdSBryan O'Donoghue not <<NULL>>).
101*b38854bdSBryan O'Donoghue 
102*b38854bdSBryan O'Donoghue 
103*b38854bdSBryan O'Donoghue 
104*b38854bdSBryan O'Donoghue RETURNS
105*b38854bdSBryan O'Donoghue <<strtoul>> returns the converted value, if any. If no conversion was
106*b38854bdSBryan O'Donoghue made, <<0>> is returned.
107*b38854bdSBryan O'Donoghue 
108*b38854bdSBryan O'Donoghue <<strtoul>> returns <<ULONG_MAX>> if the magnitude of the converted
109*b38854bdSBryan O'Donoghue value is too large, and sets <<errno>> to <<ERANGE>>.
110*b38854bdSBryan O'Donoghue 
111*b38854bdSBryan O'Donoghue PORTABILITY
112*b38854bdSBryan O'Donoghue <<strtoul>> is ANSI.
113*b38854bdSBryan O'Donoghue 
114*b38854bdSBryan O'Donoghue <<strtoul>> requires no supporting OS subroutines.
115*b38854bdSBryan O'Donoghue */
116*b38854bdSBryan O'Donoghue 
117*b38854bdSBryan O'Donoghue /*
118*b38854bdSBryan O'Donoghue  * Copyright (c) 1990 Regents of the University of California.
119*b38854bdSBryan O'Donoghue  * All rights reserved.
120*b38854bdSBryan O'Donoghue  *
121*b38854bdSBryan O'Donoghue  * Redistribution and use in source and binary forms, with or without
122*b38854bdSBryan O'Donoghue  * modification, are permitted provided that the following conditions
123*b38854bdSBryan O'Donoghue  * are met:
124*b38854bdSBryan O'Donoghue  * 1. Redistributions of source code must retain the above copyright
125*b38854bdSBryan O'Donoghue  *    notice, this list of conditions and the following disclaimer.
126*b38854bdSBryan O'Donoghue  * 2. Redistributions in binary form must reproduce the above copyright
127*b38854bdSBryan O'Donoghue  *    notice, this list of conditions and the following disclaimer in the
128*b38854bdSBryan O'Donoghue  *    documentation and/or other materials provided with the distribution.
129*b38854bdSBryan O'Donoghue  * 3. All advertising materials mentioning features or use of this software
130*b38854bdSBryan O'Donoghue  *    must display the following acknowledgement:
131*b38854bdSBryan O'Donoghue  *	This product includes software developed by the University of
132*b38854bdSBryan O'Donoghue  *	California, Berkeley and its contributors.
133*b38854bdSBryan O'Donoghue  * 4. Neither the name of the University nor the names of its contributors
134*b38854bdSBryan O'Donoghue  *    may be used to endorse or promote products derived from this software
135*b38854bdSBryan O'Donoghue  *    without specific prior written permission.
136*b38854bdSBryan O'Donoghue  *
137*b38854bdSBryan O'Donoghue  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
138*b38854bdSBryan O'Donoghue  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
139*b38854bdSBryan O'Donoghue  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
140*b38854bdSBryan O'Donoghue  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
141*b38854bdSBryan O'Donoghue  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
142*b38854bdSBryan O'Donoghue  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
143*b38854bdSBryan O'Donoghue  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
144*b38854bdSBryan O'Donoghue  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
145*b38854bdSBryan O'Donoghue  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
146*b38854bdSBryan O'Donoghue  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
147*b38854bdSBryan O'Donoghue  * SUCH DAMAGE.
148*b38854bdSBryan O'Donoghue  */
149*b38854bdSBryan O'Donoghue 
150*b38854bdSBryan O'Donoghue #include "_ansi.h"
151*b38854bdSBryan O'Donoghue #include <limits.h>
152*b38854bdSBryan O'Donoghue #include <ctype.h>
153*b38854bdSBryan O'Donoghue #include <stdlib.h>
154*b38854bdSBryan O'Donoghue 
155*b38854bdSBryan O'Donoghue /*
156*b38854bdSBryan O'Donoghue  * Convert a string to an unsigned long integer.
157*b38854bdSBryan O'Donoghue  *
158*b38854bdSBryan O'Donoghue  * Ignores `locale' stuff.  Assumes that the upper and lower case
159*b38854bdSBryan O'Donoghue  * alphabets and digits are each contiguous.
160*b38854bdSBryan O'Donoghue  */
161*b38854bdSBryan O'Donoghue unsigned long
162*b38854bdSBryan O'Donoghue _DEFUN (_strtoul, (nptr, endptr, base),
163*b38854bdSBryan O'Donoghue 	_CONST char *nptr _AND
164*b38854bdSBryan O'Donoghue 	char **endptr _AND
165*b38854bdSBryan O'Donoghue 	int base)
166*b38854bdSBryan O'Donoghue {
167*b38854bdSBryan O'Donoghue 	register const unsigned char *s = (const unsigned char *)nptr;
168*b38854bdSBryan O'Donoghue 	register unsigned long acc;
169*b38854bdSBryan O'Donoghue 	register int c;
170*b38854bdSBryan O'Donoghue 	register unsigned long cutoff;
171*b38854bdSBryan O'Donoghue 	register int neg = 0, any, cutlim;
172*b38854bdSBryan O'Donoghue 
173*b38854bdSBryan O'Donoghue 	/*
174*b38854bdSBryan O'Donoghue 	 * See strtol for comments as to the logic used.
175*b38854bdSBryan O'Donoghue 	 */
176*b38854bdSBryan O'Donoghue 	do {
177*b38854bdSBryan O'Donoghue 		c = *s++;
178*b38854bdSBryan O'Donoghue 	} while (isspace(c));
179*b38854bdSBryan O'Donoghue 	if (c == '-') {
180*b38854bdSBryan O'Donoghue 		neg = 1;
181*b38854bdSBryan O'Donoghue 		c = *s++;
182*b38854bdSBryan O'Donoghue 	} else if (c == '+')
183*b38854bdSBryan O'Donoghue 		c = *s++;
184*b38854bdSBryan O'Donoghue 	if ((base == 0 || base == 16) &&
185*b38854bdSBryan O'Donoghue 	    c == '0' && (*s == 'x' || *s == 'X')) {
186*b38854bdSBryan O'Donoghue 		c = s[1];
187*b38854bdSBryan O'Donoghue 		s += 2;
188*b38854bdSBryan O'Donoghue 		base = 16;
189*b38854bdSBryan O'Donoghue 	}
190*b38854bdSBryan O'Donoghue 	if (base == 0)
191*b38854bdSBryan O'Donoghue 		base = c == '0' ? 8 : 10;
192*b38854bdSBryan O'Donoghue 	cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
193*b38854bdSBryan O'Donoghue 	cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
194*b38854bdSBryan O'Donoghue 	for (acc = 0, any = 0;; c = *s++) {
195*b38854bdSBryan O'Donoghue 		if (isdigit(c))
196*b38854bdSBryan O'Donoghue 			c -= '0';
197*b38854bdSBryan O'Donoghue 		else if (isalpha(c))
198*b38854bdSBryan O'Donoghue 			c -= isupper(c) ? 'A' - 10 : 'a' - 10;
199*b38854bdSBryan O'Donoghue 		else
200*b38854bdSBryan O'Donoghue 			break;
201*b38854bdSBryan O'Donoghue 		if (c >= base)
202*b38854bdSBryan O'Donoghue 			break;
203*b38854bdSBryan O'Donoghue                if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
204*b38854bdSBryan O'Donoghue 			any = -1;
205*b38854bdSBryan O'Donoghue 		else {
206*b38854bdSBryan O'Donoghue 			any = 1;
207*b38854bdSBryan O'Donoghue 			acc *= base;
208*b38854bdSBryan O'Donoghue 			acc += c;
209*b38854bdSBryan O'Donoghue 		}
210*b38854bdSBryan O'Donoghue 	}
211*b38854bdSBryan O'Donoghue 	if (any < 0) {
212*b38854bdSBryan O'Donoghue 		acc = ULONG_MAX;
213*b38854bdSBryan O'Donoghue 	} else if (neg)
214*b38854bdSBryan O'Donoghue 		acc = -acc;
215*b38854bdSBryan O'Donoghue 	if (endptr != 0)
216*b38854bdSBryan O'Donoghue 		*endptr = (char *) (any ? (char *)s - 1 : nptr);
217*b38854bdSBryan O'Donoghue 	return (acc);
218*b38854bdSBryan O'Donoghue }
219*b38854bdSBryan O'Donoghue 
220*b38854bdSBryan O'Donoghue #ifndef _REENT_ONLY
221*b38854bdSBryan O'Donoghue 
222*b38854bdSBryan O'Donoghue unsigned long
223*b38854bdSBryan O'Donoghue _DEFUN (strtoul, (s, ptr, base),
224*b38854bdSBryan O'Donoghue 	_CONST char *s _AND
225*b38854bdSBryan O'Donoghue 	char **ptr _AND
226*b38854bdSBryan O'Donoghue 	int base)
227*b38854bdSBryan O'Donoghue {
228*b38854bdSBryan O'Donoghue 	return _strtoul (s, ptr, base);
229*b38854bdSBryan O'Donoghue }
230*b38854bdSBryan O'Donoghue 
231*b38854bdSBryan O'Donoghue #endif
232