Chameleon

Chameleon Svn Source Tree

Root/branches/Chimera/i386/libsa/strtol.c

1/*
2 * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 2.0 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24/*-
25 * Copyright (c) 1990, 1993
26 *The Regents of the University of California. All rights reserved.
27 *
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
30 * are met:
31 * 1. Redistributions of source code must retain the above copyright
32 * notice, this list of conditions and the following disclaimer.
33 * 2. Redistributions in binary form must reproduce the above copyright
34 * notice, this list of conditions and the following disclaimer in the
35 * documentation and/or other materials provided with the distribution.
36 * 3. All advertising materials mentioning features or use of this software
37 * must display the following acknowledgement:
38 *This product includes software developed by the University of
39 *California, Berkeley and its contributors.
40 * 4. Neither the name of the University nor the names of its contributors
41 * may be used to endorse or promote products derived from this software
42 * without specific prior written permission.
43 *
44 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54 * SUCH DAMAGE.
55 */
56
57/* Copyright (c) 1995 NeXT Computer, Inc. All rights reserved.
58 *
59 * HISTORY
60 * Modified by Curtis Galloway at NeXT June 1993,
61 * for use in the standalone library.
62 *
63 * 30-Nov-1995 Dean Reece at NeXT
64 * Created based on BSD4.4's strtol.c & strtoul.c.
65 * Removed dependency on _ctype_ by static versions of isupper()...
66 * Added support for "0b101..." binary constants.
67 * Commented out references to errno.
68 */
69
70#if defined(LIBC_SCCS) && !defined(lint)
71static char sccsid[] = "@(#)strtol.c5.4 (Berkeley) 2/23/91";
72#endif /* LIBC_SCCS and not lint */
73
74#include "libsa.h"
75#include <limits.h>
76
77/*
78 * Convert a string to a long integer.
79 *
80 * Ignores `locale' stuff. Assumes that the upper and lower case
81 * alphabets and digits are each contiguous.
82 */
83long
84strtol(nptr, endptr, base)
85const char *nptr;
86char **endptr;
87register int base;
88{
89register const char *s = nptr;
90register unsigned long acc;
91register int c;
92register unsigned long cutoff;
93register int neg = 0, any, cutlim;
94
95/*
96 * Skip white space and pick up leading +/- sign if any.
97 * If base is 0, allow 0x for hex and 0 for octal, else
98 * assume decimal; if base is already 16, allow 0x.
99 */
100do {
101c = *s++;
102} while (isspace(c));
103if (c == '-') {
104neg = 1;
105c = *s++;
106} else if (c == '+') {
107c = *s++;
108}
109
110if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) {
111c = s[1];
112s += 2;
113base = 16;
114} else if ((base == 0 || base == 2) && c == '0' && (*s == 'b' || *s == 'B')) {
115c = s[1];
116s += 2;
117base = 2;
118}
119if (base == 0) {
120base = c == '0' ? 8 : 10;
121}
122
123/*
124 * Compute the cutoff value between legal numbers and illegal
125 * numbers. That is the largest legal value, divided by the
126 * base. An input number that is greater than this value, if
127 * followed by a legal input character, is too big. One that
128 * is equal to this value may be valid or not; the limit
129 * between valid and invalid numbers is then based on the last
130 * digit. For instance, if the range for longs is
131 * [-2147483648..2147483647] and the input base is 10,
132 * cutoff will be set to 214748364 and cutlim to either
133 * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
134 * a value > 214748364, or equal but the next digit is > 7 (or 8),
135 * the number is too big, and we will return a range error.
136 *
137 * Set any if any `digits' consumed; make it negative to indicate
138 * overflow.
139 */
140cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
141cutlim = cutoff % (unsigned long)base;
142cutoff /= (unsigned long)base;
143for (acc = 0, any = 0;; c = *s++) {
144if (isdigit(c)) {
145c -= '0';
146} else if (isalpha(c)) {
147c -= isupper(c) ? 'A' - 10 : 'a' - 10;
148} else {
149break;
150}
151if (c >= base) {
152break;
153}
154if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) {
155any = -1;
156} else {
157any = 1;
158acc *= base;
159acc += c;
160}
161}
162if (any < 0) {
163acc = neg ? LONG_MIN : LONG_MAX;
164//errno = ERANGE;
165} else if (neg)
166acc = -acc;
167if (endptr != 0) {
168*endptr = (char *)(any ? s - 1 : nptr);
169}
170return (acc);
171}
172
173
174/*
175 * Convert a string to an unsigned long integer.
176 *
177 * Ignores `locale' stuff. Assumes that the upper and lower case
178 * alphabets and digits are each contiguous.
179 */
180unsigned long
181strtoul(nptr, endptr, base)
182const char *nptr;
183char **endptr;
184register int base;
185{
186register const char *s = nptr;
187register unsigned long acc;
188register int c;
189register unsigned long cutoff;
190register int neg = 0, any, cutlim;
191
192/*
193 * See strtol for comments as to the logic used.
194 */
195do {
196c = *s++;
197} while (isspace(c));
198if (c == '-') {
199neg = 1;
200c = *s++;
201} else if (c == '+') {
202c = *s++;
203}
204if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')){
205c = s[1];
206s += 2;
207base = 16;
208} else if ((base == 0 || base == 2) && c == '0' && (*s == 'b' || *s == 'B')) {
209c = s[1];
210s += 2;
211base = 2;
212}
213if (base == 0) {
214base = c == '0' ? 8 : 10;
215}
216cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
217cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
218for (acc = 0, any = 0;; c = *s++) {
219if (isdigit(c)) {
220c -= '0';
221} else if (isalpha(c)) {
222c -= isupper(c) ? 'A' - 10 : 'a' - 10;
223} else {
224break;
225}
226if (c >= base) {
227break;
228}
229if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) {
230any = -1;
231} else {
232any = 1;
233acc *= base;
234acc += c;
235}
236}
237if (any < 0) {
238acc = ULONG_MAX;
239//errno = ERANGE;
240} else if (neg) {
241acc = -acc;
242}
243if (endptr != 0) {
244*endptr = (char *)(any ? s - 1 : nptr);
245}
246return (acc);
247}
248
249/*
250 * Convert a string to an unsigned quad integer.
251 *
252 * Ignores `locale' stuff. Assumes that the upper and lower case
253 * alphabets and digits are each contiguous.
254 */
255unsigned long long
256strtouq(nptr, endptr, base)
257const char *nptr;
258char **endptr;
259register int base;
260{
261register const char *s = nptr;
262register unsigned long long acc;
263register int c;
264register unsigned long long qbase, cutoff;
265register int neg, any, cutlim;
266
267/*
268 * See strtoq for comments as to the logic used.
269 */
270s = nptr;
271do {
272c = *s++;
273} while (isspace(c));
274if (c == '-') {
275neg = 1;
276c = *s++;
277} else {
278neg = 0;
279if (c == '+') {
280c = *s++;
281}
282}
283if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) {
284c = s[1];
285s += 2;
286base = 16;
287}
288if (base == 0) {
289base = c == '0' ? 8 : 10;
290}
291qbase = (unsigned)base;
292cutoff = (unsigned long long)UQUAD_MAX / qbase;
293cutlim = (unsigned long long)UQUAD_MAX % qbase;
294for (acc = 0, any = 0;; c = *s++) {
295if (isdigit(c)) {
296c -= '0';
297} else if (isalpha(c)) {
298c -= isupper(c) ? 'A' - 10 : 'a' - 10;
299} else {
300break;
301}
302if (c >= base) {
303break;
304}
305if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) {
306any = -1;
307} else {
308any = 1;
309acc *= qbase;
310acc += c;
311}
312}
313if (any < 0) {
314acc = UQUAD_MAX;
315//errno = ERANGE;
316} else if (neg) {
317acc = -acc;
318}
319if (endptr != 0) {
320*endptr = (char *)(any ? s - 1 : nptr);
321}
322return (acc);
323}
324

Archive Download this file

Revision: HEAD