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