1/*
2 * Copyright (c) 1998-2006 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/*      Copyright (c) 1995 NeXT Computer, Inc.  All rights reserved.
29 *
30 * strol.c - The functions strtol() & strtoul() are exported as public API
31 *           via the header file ~driverkit/generalFuncs.h
32 *
33 * HISTORY
34 * 25-Oct-1995    Dean Reece at NeXT
35 *      Created based on BSD4.4's strtol.c & strtoul.c.
36 *      Removed dependency on _ctype_ by static versions of isupper()...
37 *      Added support for "0b101..." binary constants.
38 *      Commented out references to errno.
39 */
40
41/*-
42 * Copyright (c) 1990, 1993
43 *	The Regents of the University of California.  All rights reserved.
44 *
45 * Redistribution and use in source and binary forms, with or without
46 * modification, are permitted provided that the following conditions
47 * are met:
48 * 1. Redistributions of source code must retain the above copyright
49 *    notice, this list of conditions and the following disclaimer.
50 * 2. Redistributions in binary form must reproduce the above copyright
51 *    notice, this list of conditions and the following disclaimer in the
52 *    documentation and/or other materials provided with the distribution.
53 * 3. All advertising materials mentioning features or use of this software
54 *    must display the following acknowledgement:
55 *	This product includes software developed by the University of
56 *	California, Berkeley and its contributors.
57 * 4. Neither the name of the University nor the names of its contributors
58 *    may be used to endorse or promote products derived from this software
59 *    without specific prior written permission.
60 *
61 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
62 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
63 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
64 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
65 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
66 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
67 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
68 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
69 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
70 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
71 * SUCH DAMAGE.
72 */
73
74/*
75#include <string.h>
76#include <stdlib.h>
77#include <limits.h>
78*/
79#include <sys/types.h>
80#include <machine/limits.h>
81
82typedef int BOOL;
83
84static inline BOOL
85isupper(char c)
86{
87    return (c >= 'A' && c <= 'Z');
88}
89
90static inline BOOL
91isalpha(char c)
92{
93    return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'));
94}
95
96
97static inline BOOL
98isspace(char c)
99{
100    return (c == ' ' || c == '\t' || c == '\n' || c == '\12');
101}
102
103static inline BOOL
104isdigit(char c)
105{
106    return (c >= '0' && c <= '9');
107}
108
109/*
110 * Convert a string to a long integer.
111 *
112 * Ignores `locale' stuff.  Assumes that the upper and lower case
113 * alphabets and digits are each contiguous.
114 */
115long
116strtol(const char *nptr, char **endptr, int base)
117{
118	register const char *s = nptr;
119	register unsigned long acc;
120	register int c;
121	register unsigned long cutoff;
122	register int neg = 0, any, cutlim;
123
124	/*
125	 * Skip white space and pick up leading +/- sign if any.
126	 * If base is 0, allow 0x for hex and 0 for octal, else
127	 * assume decimal; if base is already 16, allow 0x.
128	 */
129	do {
130		c = *s++;
131	} while (isspace(c));
132	if (c == '-') {
133		neg = 1;
134		c = *s++;
135	} else if (c == '+')
136		c = *s++;
137	if ((base == 0 || base == 16) &&
138	    c == '0' && (*s == 'x' || *s == 'X')) {
139		c = s[1];
140		s += 2;
141		base = 16;
142	} else if ((base == 0 || base == 2) &&
143	    c == '0' && (*s == 'b' || *s == 'B')) {
144		c = s[1];
145		s += 2;
146		base = 2;
147	}
148	if (base == 0)
149		base = c == '0' ? 8 : 10;
150
151	/*
152	 * Compute the cutoff value between legal numbers and illegal
153	 * numbers.  That is the largest legal value, divided by the
154	 * base.  An input number that is greater than this value, if
155	 * followed by a legal input character, is too big.  One that
156	 * is equal to this value may be valid or not; the limit
157	 * between valid and invalid numbers is then based on the last
158	 * digit.  For instance, if the range for longs is
159	 * [-2147483648..2147483647] and the input base is 10,
160	 * cutoff will be set to 214748364 and cutlim to either
161	 * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
162	 * a value > 214748364, or equal but the next digit is > 7 (or 8),
163	 * the number is too big, and we will return a range error.
164	 *
165	 * Set any if any `digits' consumed; make it negative to indicate
166	 * overflow.
167	 */
168	cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
169	cutlim = cutoff % (unsigned long)base;
170	cutoff /= (unsigned long)base;
171	for (acc = 0, any = 0;; c = *s++) {
172		if (isdigit(c))
173			c -= '0';
174		else if (isalpha(c))
175			c -= isupper(c) ? 'A' - 10 : 'a' - 10;
176		else
177			break;
178		if (c >= base)
179			break;
180		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim) )
181			any = -1;
182		else {
183			any = 1;
184			acc *= base;
185			acc += c;
186		}
187	}
188	if (any < 0) {
189		acc = neg ? LONG_MIN : LONG_MAX;
190//		errno = ERANGE;
191	} else if (neg)
192		acc = -acc;
193	if (endptr != 0)
194		*endptr = (char *)(any ? s - 1 : nptr);
195	return (acc);
196}
197
198unsigned long
199strtoul(const char *nptr, char **endptr, int base)
200{
201	register const char *s = nptr;
202	register unsigned long acc;
203	register int c;
204	register unsigned long cutoff;
205	register int neg = 0, any, cutlim;
206
207	/*
208	 * See strtol for comments as to the logic used.
209	 */
210	do {
211		c = *s++;
212	} while (isspace(c));
213	if (c == '-') {
214		neg = 1;
215		c = *s++;
216	} else if (c == '+')
217		c = *s++;
218	if ((base == 0 || base == 16) &&
219	    c == '0' && (*s == 'x' || *s == 'X')) {
220		c = s[1];
221		s += 2;
222		base = 16;
223	} else if ((base == 0 || base == 2) &&
224	    c == '0' && (*s == 'b' || *s == 'B')) {
225		c = s[1];
226		s += 2;
227		base = 2;
228	}
229	if (base == 0)
230		base = c == '0' ? 8 : 10;
231	cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
232	cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
233	for (acc = 0, any = 0;; c = *s++) {
234		if (isdigit(c))
235			c -= '0';
236		else if (isalpha(c))
237			c -= isupper(c) ? 'A' - 10 : 'a' - 10;
238		else
239			break;
240		if (c >= base)
241			break;
242		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim) )
243			any = -1;
244		else {
245			any = 1;
246			acc *= base;
247			acc += c;
248		}
249	}
250	if (any < 0) {
251		acc = ULONG_MAX;
252//		errno = ERANGE;
253	} else if (neg)
254		acc = -acc;
255	if (endptr != 0)
256		*endptr = (char *)(any ? s - 1 : nptr);
257	return (acc);
258}
259
260/*
261 * Convert a string to a quad integer.
262 *
263 * Ignores `locale' stuff.  Assumes that the upper and lower case
264 * alphabets and digits are each contiguous.
265 */
266quad_t
267strtoq(const char *nptr, char **endptr, int base)
268{
269	register const char *s;
270	register u_quad_t acc;
271	register int c;
272	register u_quad_t qbase, cutoff;
273	register int neg, any, cutlim;
274
275	/*
276	 * Skip white space and pick up leading +/- sign if any.
277	 * If base is 0, allow 0x for hex and 0 for octal, else
278	 * assume decimal; if base is already 16, allow 0x.
279	 */
280	s = nptr;
281	do {
282		c = *s++;
283	} while (isspace(c));
284	if (c == '-') {
285		neg = 1;
286		c = *s++;
287	} else {
288		neg = 0;
289		if (c == '+')
290			c = *s++;
291	}
292	if ((base == 0 || base == 16) &&
293	    c == '0' && (*s == 'x' || *s == 'X')) {
294		c = s[1];
295		s += 2;
296		base = 16;
297	}
298	if (base == 0)
299		base = c == '0' ? 8 : 10;
300
301	/*
302	 * Compute the cutoff value between legal numbers and illegal
303	 * numbers.  That is the largest legal value, divided by the
304	 * base.  An input number that is greater than this value, if
305	 * followed by a legal input character, is too big.  One that
306	 * is equal to this value may be valid or not; the limit
307	 * between valid and invalid numbers is then based on the last
308	 * digit.  For instance, if the range for quads is
309	 * [-9223372036854775808..9223372036854775807] and the input base
310	 * is 10, cutoff will be set to 922337203685477580 and cutlim to
311	 * either 7 (neg==0) or 8 (neg==1), meaning that if we have
312	 * accumulated a value > 922337203685477580, or equal but the
313	 * next digit is > 7 (or 8), the number is too big, and we will
314	 * return a range error.
315	 *
316	 * Set any if any `digits' consumed; make it negative to indicate
317	 * overflow.
318	 */
319	qbase = (unsigned)base;
320	cutoff = neg ? -(u_quad_t)QUAD_MIN : QUAD_MAX;
321	cutlim = cutoff % qbase;
322	cutoff /= qbase;
323	for (acc = 0, any = 0;; c = *s++) {
324		if (isdigit(c))
325			c -= '0';
326		else if (isalpha(c))
327			c -= isupper(c) ? 'A' - 10 : 'a' - 10;
328		else
329			break;
330		if (c >= base)
331			break;
332		if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
333			any = -1;
334		else {
335			any = 1;
336			acc *= qbase;
337			acc += c;
338		}
339	}
340	if (any < 0) {
341		acc = neg ? QUAD_MIN : QUAD_MAX;
342//		errno = ERANGE;
343	} else if (neg)
344		acc = -acc;
345	if (endptr != 0)
346		*endptr = (char *)(any ? s - 1 : nptr);
347	return (acc);
348}
349
350
351/*
352 * Convert a string to an unsigned quad integer.
353 *
354 * Ignores `locale' stuff.  Assumes that the upper and lower case
355 * alphabets and digits are each contiguous.
356 */
357u_quad_t
358strtouq(const char *nptr,
359	char **endptr,
360	register int base)
361{
362	register const char *s = nptr;
363	register u_quad_t acc;
364	register int c;
365	register u_quad_t qbase, cutoff;
366	register int neg, any, cutlim;
367
368	/*
369	 * See strtoq for comments as to the logic used.
370	 */
371	s = nptr;
372	do {
373		c = *s++;
374	} while (isspace(c));
375	if (c == '-') {
376		neg = 1;
377		c = *s++;
378	} else {
379		neg = 0;
380		if (c == '+')
381			c = *s++;
382	}
383	if ((base == 0 || base == 16) &&
384	    c == '0' && (*s == 'x' || *s == 'X')) {
385		c = s[1];
386		s += 2;
387		base = 16;
388	}
389	if (base == 0)
390		base = c == '0' ? 8 : 10;
391	qbase = (unsigned)base;
392	cutoff = (u_quad_t)UQUAD_MAX / qbase;
393	cutlim = (u_quad_t)UQUAD_MAX % qbase;
394	for (acc = 0, any = 0;; c = *s++) {
395		if (isdigit(c))
396			c -= '0';
397		else if (isalpha(c))
398			c -= isupper(c) ? 'A' - 10 : 'a' - 10;
399		else
400			break;
401		if (c >= base)
402			break;
403		if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
404			any = -1;
405		else {
406			any = 1;
407			acc *= qbase;
408			acc += c;
409		}
410	}
411	if (any < 0) {
412		acc = UQUAD_MAX;
413//		errno = ERANGE;
414	} else if (neg)
415		acc = -acc;
416	if (endptr != 0)
417		*endptr = (char *)(any ? s - 1 : nptr);
418	return (acc);
419}
420
421
422/*
423 *
424 */
425
426char *strchr(const char *str, int ch)
427{
428    do {
429	if (*str == ch)
430	    return((char *)str);
431    } while (*str++);
432    return ((char *) 0);
433}
434
435/*
436 *
437 */
438
439char *
440strncat(char *s1, const char *s2, unsigned long n)
441{
442	char *os1;
443	int i = n;
444
445	os1 = s1;
446	while (*s1++)
447		;
448	--s1;
449	while ((*s1++ = *s2++))
450		if (--i < 0) {
451			*--s1 = '\0';
452			break;
453		}
454	return(os1);
455}
456