Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/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#ifndef UQUAD_MAX
78#define UQUAD_MAX 0xffffffffffffffffUL
79#endif
80
81/*
82 * Convert a string to a long integer.
83 *
84 * Ignores `locale' stuff. Assumes that the upper and lower case
85 * alphabets and digits are each contiguous.
86 */
87long
88strtol(const char *nptr, char **endptr, int base)
89{
90register const char *s = nptr;
91register unsigned long acc;
92register int c;
93register unsigned long cutoff;
94register int neg = 0, any, cutlim;
95
96/*
97 * Skip white space and pick up leading +/- sign if any.
98 * If base is 0, allow 0x for hex and 0 for octal, else
99 * assume decimal; if base is already 16, allow 0x.
100 */
101do {
102c = *s++;
103} while (isspace(c));
104if (c == '-') {
105neg = 1;
106c = *s++;
107} else if (c == '+')
108c = *s++;
109if ((base == 0 || base == 16) &&
110 c == '0' && (*s == 'x' || *s == 'X')) {
111c = s[1];
112s += 2;
113base = 16;
114} else if ((base == 0 || base == 2) &&
115 c == '0' && (*s == 'b' || *s == 'B')) {
116c = s[1];
117s += 2;
118base = 2;
119}
120if (base == 0)
121base = c == '0' ? 8 : 10;
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';
146else if (isalpha(c))
147c -= isupper(c) ? 'A' - 10 : 'a' - 10;
148else
149break;
150if (c >= base)
151break;
152if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim) )
153any = -1;
154else {
155any = 1;
156acc *= base;
157acc += c;
158}
159}
160if (any < 0) {
161acc = neg ? LONG_MIN : LONG_MAX;
162//errno = ERANGE;
163} else if (neg)
164acc = -acc;
165if (endptr != 0)
166{
167if(any)
168{
169*endptr = __CAST_AWAY_QUALIFIER(s - 1, const, char *);
170}
171else
172{
173*endptr = __CAST_AWAY_QUALIFIER(nptr, const, char *);
174}
175}
176return (acc);
177}
178
179
180/*
181 * Convert a string to an unsigned long integer.
182 *
183 * Ignores `locale' stuff. Assumes that the upper and lower case
184 * alphabets and digits are each contiguous.
185 */
186unsigned long
187strtoul(const char *nptr, char **endptr, int base)
188{
189register const char *s = nptr;
190register unsigned long acc;
191register int c;
192register unsigned long cutoff;
193register int neg = 0, any, cutlim;
194
195/*
196 * See strtol for comments as to the logic used.
197 */
198do {
199c = *s++;
200} while (isspace(c));
201if (c == '-') {
202neg = 1;
203c = *s++;
204} else if (c == '+')
205c = *s++;
206if ((base == 0 || base == 16) &&
207 c == '0' && (*s == 'x' || *s == 'X')) {
208c = s[1];
209s += 2;
210base = 16;
211} else if ((base == 0 || base == 2) &&
212 c == '0' && (*s == 'b' || *s == 'B')) {
213c = s[1];
214s += 2;
215base = 2;
216}
217if (base == 0)
218base = c == '0' ? 8 : 10;
219cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
220cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
221for (acc = 0, any = 0;; c = *s++) {
222if (isdigit(c))
223c -= '0';
224else if (isalpha(c))
225c -= isupper(c) ? 'A' - 10 : 'a' - 10;
226else
227break;
228if (c >= base)
229break;
230if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim) )
231any = -1;
232else {
233any = 1;
234acc *= base;
235acc += c;
236}
237}
238if (any < 0) {
239acc = ULONG_MAX;
240//errno = ERANGE;
241} else if (neg)
242acc = -acc;
243if (endptr != 0)
244{
245if(any)
246{
247*endptr = __CAST_AWAY_QUALIFIER(s - 1, const, char *);
248}
249else
250{
251*endptr = __CAST_AWAY_QUALIFIER(nptr, const, char *);
252}
253}
254
255return (acc);
256}
257#if UNUSED
258/*
259 * Convert a string to an unsigned quad integer.
260 *
261 * Ignores `locale' stuff. Assumes that the upper and lower case
262 * alphabets and digits are each contiguous.
263 */
264unsigned long long
265strtouq(const char *nptr,
266char **endptr,
267register int base)
268{
269register const char *s = nptr;
270register unsigned long long acc;
271register int c;
272register unsigned long long qbase, cutoff;
273register int neg, any, cutlim;
274
275/*
276 * See strtoq for comments as to the logic used.
277 */
278s = nptr;
279do {
280c = *s++;
281} while (isspace(c));
282if (c == '-') {
283neg = 1;
284c = *s++;
285} else {
286neg = 0;
287if (c == '+')
288c = *s++;
289}
290if ((base == 0 || base == 16) &&
291 c == '0' && (*s == 'x' || *s == 'X')) {
292c = s[1];
293s += 2;
294base = 16;
295}
296if (base == 0)
297base = c == '0' ? 8 : 10;
298qbase = (unsigned)base;
299cutoff = (unsigned long long)UQUAD_MAX / qbase;
300cutlim = (unsigned long long)UQUAD_MAX % qbase;
301for (acc = 0, any = 0;; c = *s++) {
302if (isdigit(c))
303c -= '0';
304else if (isalpha(c))
305c -= isupper(c) ? 'A' - 10 : 'a' - 10;
306else
307break;
308if (c >= base)
309break;
310if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
311any = -1;
312else {
313any = 1;
314acc *= qbase;
315acc += c;
316}
317}
318if (any < 0) {
319acc = UQUAD_MAX;
320//errno = ERANGE;
321} else if (neg)
322acc = -acc;
323if (endptr != 0)
324{
325if(any)
326{
327*endptr = __CAST_AWAY_QUALIFIER(s - 1, const, char *);
328}
329else
330{
331*endptr = __CAST_AWAY_QUALIFIER(nptr, const, char *);
332}
333}
334
335return (acc);
336}
337#endif
338

Archive Download this file

Revision: 2006