Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 2045