1 /* 2 * Copyright (c) 1998-2016 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 85 long strtol(const char *nptr, char **endptr, int base); 86 unsigned long strtoul(const char *nptr, char **endptr, int base); 87 quad_t strtoq(const char *nptr, char **endptr, int base); 88 u_quad_t strtouq(const char *nptr, char **endptr, int base); 89 char *strncat(char *s1, const char *s2, unsigned long n); 90 91 92 typedef int BOOL; 93 94 static inline BOOL 95 isupper(char c) 96 { 97 return c >= 'A' && c <= 'Z'; 98 } 99 100 static inline BOOL 101 isalpha(char c) 102 { 103 return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); 104 } 105 106 107 static inline BOOL 108 isspace(char c) 109 { 110 return c == ' ' || c == '\t' || c == '\n' || c == '\12'; 111 } 112 113 static inline BOOL 114 isdigit(char c) 115 { 116 return c >= '0' && c <= '9'; 117 } 118 119 /* 120 * Convert a string to a long integer. 121 * 122 * Ignores `locale' stuff. Assumes that the upper and lower case 123 * alphabets and digits are each contiguous. 124 */ 125 long 126 strtol(const char *nptr, char **endptr, int base) 127 { 128 const char *s = nptr; 129 unsigned long acc; 130 char c; 131 unsigned long cutoff; 132 int neg = 0, any, cutlim; 133 134 /* 135 * Skip white space and pick up leading +/- sign if any. 136 * If base is 0, allow 0x for hex and 0 for octal, else 137 * assume decimal; if base is already 16, allow 0x. 138 */ 139 do { 140 c = *s++; 141 } while (isspace(c)); 142 if (c == '-') { 143 neg = 1; 144 c = *s++; 145 } else if (c == '+') { 146 c = *s++; 147 } 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 /* 164 * Compute the cutoff value between legal numbers and illegal 165 * numbers. That is the largest legal value, divided by the 166 * base. An input number that is greater than this value, if 167 * followed by a legal input character, is too big. One that 168 * is equal to this value may be valid or not; the limit 169 * between valid and invalid numbers is then based on the last 170 * digit. For instance, if the range for longs is 171 * [-2147483648..2147483647] and the input base is 10, 172 * cutoff will be set to 214748364 and cutlim to either 173 * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated 174 * a value > 214748364, or equal but the next digit is > 7 (or 8), 175 * the number is too big, and we will return a range error. 176 * 177 * Set any if any `digits' consumed; make it negative to indicate 178 * overflow. 179 */ 180 cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX; 181 cutlim = ((int)(cutoff % (unsigned long)base)); 182 cutoff /= (unsigned long)base; 183 for (acc = 0, any = 0;; c = *s++) { 184 if (isdigit(c)) { 185 c -= '0'; 186 } else if (isalpha(c)) { 187 c -= isupper(c) ? 'A' - 10 : 'a' - 10; 188 } else { 189 break; 190 } 191 if (c >= base) { 192 break; 193 } 194 if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) { 195 any = -1; 196 } else { 197 any = 1; 198 acc *= base; 199 acc += c; 200 } 201 } 202 if (any < 0) { 203 acc = neg ? LONG_MIN : LONG_MAX; 204 // errno = ERANGE; 205 } else if (neg) { 206 acc = -acc; 207 } 208 if (endptr != 0) { 209 if (any) { 210 *endptr = __CAST_AWAY_QUALIFIER(s - 1, const, char *); 211 } else { 212 *endptr = __CAST_AWAY_QUALIFIER(nptr, const, char *); 213 } 214 } 215 return acc; 216 } 217 218 unsigned long 219 strtoul(const char *nptr, char **endptr, int base) 220 { 221 const char *s = nptr; 222 unsigned long acc; 223 char c; 224 unsigned long cutoff; 225 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 } 239 if ((base == 0 || base == 16) && 240 c == '0' && (*s == 'x' || *s == 'X')) { 241 c = s[1]; 242 s += 2; 243 base = 16; 244 } else if ((base == 0 || base == 2) && 245 c == '0' && (*s == 'b' || *s == 'B')) { 246 c = s[1]; 247 s += 2; 248 base = 2; 249 } 250 if (base == 0) { 251 base = c == '0' ? 8 : 10; 252 } 253 cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; 254 cutlim = ((int)((unsigned long)ULONG_MAX % (unsigned long)base)); 255 for (acc = 0, any = 0;; c = *s++) { 256 if (isdigit(c)) { 257 c -= '0'; 258 } else if (isalpha(c)) { 259 c -= isupper(c) ? 'A' - 10 : 'a' - 10; 260 } else { 261 break; 262 } 263 if (c >= base) { 264 break; 265 } 266 if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) { 267 any = -1; 268 } else { 269 any = 1; 270 acc *= base; 271 acc += c; 272 } 273 } 274 if (any < 0) { 275 acc = ULONG_MAX; 276 // errno = ERANGE; 277 } else if (neg) { 278 acc = -acc; 279 } 280 if (endptr != 0) { 281 if (any) { 282 *endptr = __CAST_AWAY_QUALIFIER(s - 1, const, char *); 283 } else { 284 *endptr = __CAST_AWAY_QUALIFIER(nptr, const, char *); 285 } 286 } 287 288 return acc; 289 } 290 291 /* 292 * Convert a string to a quad integer. 293 * 294 * Ignores `locale' stuff. Assumes that the upper and lower case 295 * alphabets and digits are each contiguous. 296 */ 297 quad_t 298 strtoq(const char *nptr, char **endptr, int base) 299 { 300 const char *s; 301 u_quad_t acc; 302 char c; 303 u_quad_t qbase, cutoff; 304 int neg, any, cutlim; 305 306 /* 307 * Skip white space and pick up leading +/- sign if any. 308 * If base is 0, allow 0x for hex and 0 for octal, else 309 * assume decimal; if base is already 16, allow 0x. 310 */ 311 s = nptr; 312 do { 313 c = *s++; 314 } while (isspace(c)); 315 if (c == '-') { 316 neg = 1; 317 c = *s++; 318 } else { 319 neg = 0; 320 if (c == '+') { 321 c = *s++; 322 } 323 } 324 if ((base == 0 || base == 16) && 325 c == '0' && (*s == 'x' || *s == 'X')) { 326 c = s[1]; 327 s += 2; 328 base = 16; 329 } 330 if (base == 0) { 331 base = c == '0' ? 8 : 10; 332 } 333 334 /* 335 * Compute the cutoff value between legal numbers and illegal 336 * numbers. That is the largest legal value, divided by the 337 * base. An input number that is greater than this value, if 338 * followed by a legal input character, is too big. One that 339 * is equal to this value may be valid or not; the limit 340 * between valid and invalid numbers is then based on the last 341 * digit. For instance, if the range for quads is 342 * [-9223372036854775808..9223372036854775807] and the input base 343 * is 10, cutoff will be set to 922337203685477580 and cutlim to 344 * either 7 (neg==0) or 8 (neg==1), meaning that if we have 345 * accumulated a value > 922337203685477580, or equal but the 346 * next digit is > 7 (or 8), the number is too big, and we will 347 * return a range error. 348 * 349 * Set any if any `digits' consumed; make it negative to indicate 350 * overflow. 351 */ 352 qbase = (unsigned)base; 353 cutoff = neg ? -(u_quad_t)QUAD_MIN : QUAD_MAX; 354 cutlim = ((int)(cutoff % qbase)); 355 cutoff /= qbase; 356 for (acc = 0, any = 0;; c = *s++) { 357 if (isdigit(c)) { 358 c -= '0'; 359 } else if (isalpha(c)) { 360 c -= isupper(c) ? 'A' - 10 : 'a' - 10; 361 } else { 362 break; 363 } 364 if (c >= base) { 365 break; 366 } 367 if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) { 368 any = -1; 369 } else { 370 any = 1; 371 acc *= qbase; 372 acc += c; 373 } 374 } 375 if (any < 0) { 376 acc = neg ? QUAD_MIN : QUAD_MAX; 377 // errno = ERANGE; 378 } else if (neg) { 379 acc = -acc; 380 } 381 if (endptr != 0) { 382 if (any) { 383 *endptr = __CAST_AWAY_QUALIFIER(s - 1, const, char *); 384 } else { 385 *endptr = __CAST_AWAY_QUALIFIER(nptr, const, char *); 386 } 387 } 388 389 return acc; 390 } 391 392 393 /* 394 * Convert a string to an unsigned quad integer. 395 * 396 * Ignores `locale' stuff. Assumes that the upper and lower case 397 * alphabets and digits are each contiguous. 398 */ 399 u_quad_t 400 strtouq(const char *nptr, 401 char **endptr, 402 int base) 403 { 404 const char *s = nptr; 405 u_quad_t acc; 406 char c; 407 u_quad_t qbase, cutoff; 408 int neg, any, cutlim; 409 410 /* 411 * See strtoq for comments as to the logic used. 412 */ 413 s = nptr; 414 do { 415 c = *s++; 416 } while (isspace(c)); 417 if (c == '-') { 418 neg = 1; 419 c = *s++; 420 } else { 421 neg = 0; 422 if (c == '+') { 423 c = *s++; 424 } 425 } 426 if ((base == 0 || base == 16) && 427 c == '0' && (*s == 'x' || *s == 'X')) { 428 c = s[1]; 429 s += 2; 430 base = 16; 431 } 432 if (base == 0) { 433 base = c == '0' ? 8 : 10; 434 } 435 qbase = (unsigned)base; 436 cutoff = (u_quad_t)UQUAD_MAX / qbase; 437 cutlim = ((int)((u_quad_t)UQUAD_MAX % qbase)); 438 for (acc = 0, any = 0;; c = *s++) { 439 if (isdigit(c)) { 440 c -= '0'; 441 } else if (isalpha(c)) { 442 c -= isupper(c) ? 'A' - 10 : 'a' - 10; 443 } else { 444 break; 445 } 446 if (c >= base) { 447 break; 448 } 449 if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) { 450 any = -1; 451 } else { 452 any = 1; 453 acc *= qbase; 454 acc += c; 455 } 456 } 457 if (any < 0) { 458 acc = UQUAD_MAX; 459 // errno = ERANGE; 460 } else if (neg) { 461 acc = -acc; 462 } 463 if (endptr != 0) { 464 if (any) { 465 *endptr = __CAST_AWAY_QUALIFIER(s - 1, const, char *); 466 } else { 467 *endptr = __CAST_AWAY_QUALIFIER(nptr, const, char *); 468 } 469 } 470 471 return acc; 472 } 473 474 475 /* 476 * 477 */ 478 479 char * 480 strncat(char *s1, const char *s2, unsigned long n) 481 { 482 if (n != 0) { 483 char *d = s1; 484 const char *s = s2; 485 486 while (*d != 0) { 487 d++; 488 } 489 do { 490 if ((*d = *s++) == '\0') { 491 break; 492 } 493 d++; 494 } while (--n != 0); 495 *d = '\0'; 496 } 497 return s1; 498 } 499