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