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