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