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/*
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(const char *nptr, char **endptr, int base)
85{
86register const char *s = nptr;
87register unsigned long acc;
88register int c;
89register unsigned long cutoff;
90register int neg = 0, any, cutlim;
91
92/*
93 * Skip white space and pick up leading +/- sign if any.
94 * If base is 0, allow 0x for hex and 0 for octal, else
95 * assume decimal; if base is already 16, allow 0x.
96 */
97do {
98c = *s++;
99} while (isspace(c));
100if (c == '-') {
101neg = 1;
102c = *s++;
103} else if (c == '+')
104c = *s++;
105if ((base == 0 || base == 16) &&
106 c == '0' && (*s == 'x' || *s == 'X')) {
107c = s[1];
108s += 2;
109base = 16;
110} else if ((base == 0 || base == 2) &&
111 c == '0' && (*s == 'b' || *s == 'B')) {
112c = s[1];
113s += 2;
114base = 2;
115}
116if (base == 0)
117base = c == '0' ? 8 : 10;
118
119/*
120 * Compute the cutoff value between legal numbers and illegal
121 * numbers. That is the largest legal value, divided by the
122 * base. An input number that is greater than this value, if
123 * followed by a legal input character, is too big. One that
124 * is equal to this value may be valid or not; the limit
125 * between valid and invalid numbers is then based on the last
126 * digit. For instance, if the range for longs is
127 * [-2147483648..2147483647] and the input base is 10,
128 * cutoff will be set to 214748364 and cutlim to either
129 * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
130 * a value > 214748364, or equal but the next digit is > 7 (or 8),
131 * the number is too big, and we will return a range error.
132 *
133 * Set any if any `digits' consumed; make it negative to indicate
134 * overflow.
135 */
136cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
137cutlim = cutoff % (unsigned long)base;
138cutoff /= (unsigned long)base;
139for (acc = 0, any = 0;; c = *s++) {
140if (isdigit(c))
141c -= '0';
142else if (isalpha(c))
143c -= isupper(c) ? 'A' - 10 : 'a' - 10;
144else
145break;
146if (c >= base)
147break;
148if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim) )
149any = -1;
150else {
151any = 1;
152acc *= base;
153acc += c;
154}
155}
156if (any < 0) {
157acc = neg ? LONG_MIN : LONG_MAX;
158//errno = ERANGE;
159} else if (neg)
160acc = -acc;
161if (endptr != 0)
162{
163if(any)
164{
165*endptr = __CAST_AWAY_QUALIFIER(s - 1, const, char *);
166}
167else
168{
169*endptr = __CAST_AWAY_QUALIFIER(nptr, const, char *);
170}
171}
172return (acc);
173}
174
175
176/*
177 * Convert a string to an unsigned long integer.
178 *
179 * Ignores `locale' stuff. Assumes that the upper and lower case
180 * alphabets and digits are each contiguous.
181 */
182unsigned long
183strtoul(const char *nptr, char **endptr, int base)
184{
185register const char *s = nptr;
186register unsigned long acc;
187register int c;
188register unsigned long cutoff;
189register int neg = 0, any, cutlim;
190
191/*
192 * See strtol for comments as to the logic used.
193 */
194do {
195c = *s++;
196} while (isspace(c));
197if (c == '-') {
198neg = 1;
199c = *s++;
200} else if (c == '+')
201c = *s++;
202if ((base == 0 || base == 16) &&
203 c == '0' && (*s == 'x' || *s == 'X')) {
204c = s[1];
205s += 2;
206base = 16;
207} else if ((base == 0 || base == 2) &&
208 c == '0' && (*s == 'b' || *s == 'B')) {
209c = s[1];
210s += 2;
211base = 2;
212}
213if (base == 0)
214base = c == '0' ? 8 : 10;
215cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
216cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
217for (acc = 0, any = 0;; c = *s++) {
218if (isdigit(c))
219c -= '0';
220else if (isalpha(c))
221c -= isupper(c) ? 'A' - 10 : 'a' - 10;
222else
223break;
224if (c >= base)
225break;
226if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim) )
227any = -1;
228else {
229any = 1;
230acc *= base;
231acc += c;
232}
233}
234if (any < 0) {
235acc = ULONG_MAX;
236//errno = ERANGE;
237} else if (neg)
238acc = -acc;
239if (endptr != 0)
240{
241if(any)
242{
243*endptr = __CAST_AWAY_QUALIFIER(s - 1, const, char *);
244}
245else
246{
247*endptr = __CAST_AWAY_QUALIFIER(nptr, const, char *);
248}
249}
250
251return (acc);
252}
253
254/*
255 * Convert a string to an unsigned quad integer.
256 *
257 * Ignores `locale' stuff. Assumes that the upper and lower case
258 * alphabets and digits are each contiguous.
259 */
260unsigned long long
261strtouq(const char *nptr,
262char **endptr,
263register int base)
264{
265register const char *s = nptr;
266register unsigned long long acc;
267register int c;
268register unsigned long long qbase, cutoff;
269register int neg, any, cutlim;
270
271/*
272 * See strtoq for comments as to the logic used.
273 */
274s = nptr;
275do {
276c = *s++;
277} while (isspace(c));
278if (c == '-') {
279neg = 1;
280c = *s++;
281} else {
282neg = 0;
283if (c == '+')
284c = *s++;
285}
286if ((base == 0 || base == 16) &&
287 c == '0' && (*s == 'x' || *s == 'X')) {
288c = s[1];
289s += 2;
290base = 16;
291}
292if (base == 0)
293base = c == '0' ? 8 : 10;
294qbase = (unsigned)base;
295cutoff = (unsigned long long)UQUAD_MAX / qbase;
296cutlim = (unsigned long long)UQUAD_MAX % qbase;
297for (acc = 0, any = 0;; c = *s++) {
298if (isdigit(c))
299c -= '0';
300else if (isalpha(c))
301c -= isupper(c) ? 'A' - 10 : 'a' - 10;
302else
303break;
304if (c >= base)
305break;
306if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
307any = -1;
308else {
309any = 1;
310acc *= qbase;
311acc += c;
312}
313}
314if (any < 0) {
315acc = UQUAD_MAX;
316//errno = ERANGE;
317} else if (neg)
318acc = -acc;
319if (endptr != 0)
320{
321if(any)
322{
323*endptr = __CAST_AWAY_QUALIFIER(s - 1, const, char *);
324}
325else
326{
327*endptr = __CAST_AWAY_QUALIFIER(nptr, const, char *);
328}
329}
330
331return (acc);
332}
333

Archive Download this file

Revision: 1804