Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 2323