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