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 90 91 typedef int BOOL; 92 93 static inline BOOL 94 isupper(char c) 95 { 96 return c >= 'A' && c <= 'Z'; 97 } 98 99 static inline BOOL 100 isalpha(char c) 101 { 102 return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); 103 } 104 105 106 static inline BOOL 107 isspace(char c) 108 { 109 return c == ' ' || c == '\t' || c == '\n' || c == '\12'; 110 } 111 112 static inline BOOL 113 isdigit(char c) 114 { 115 return c >= '0' && c <= '9'; 116 } 117 118 /* 119 * Convert a string to a long integer. 120 * 121 * Ignores `locale' stuff. Assumes that the upper and lower case 122 * alphabets and digits are each contiguous. 123 */ 124 long 125 strtol(const char *nptr, char **endptr, int base) 126 { 127 const char *s = nptr; 128 unsigned long acc; 129 char c; 130 unsigned long cutoff; 131 int neg = 0, any, cutlim; 132 133 /* 134 * Skip white space and pick up leading +/- sign if any. 135 * If base is 0, allow 0x for hex and 0 for octal, else 136 * assume decimal; if base is already 16, allow 0x. 137 */ 138 do { 139 c = *s++; 140 } while (isspace(c)); 141 if (c == '-') { 142 neg = 1; 143 c = *s++; 144 } else if (c == '+') { 145 c = *s++; 146 } 147 if ((base == 0 || base == 16) && 148 c == '0' && (*s == 'x' || *s == 'X')) { 149 c = s[1]; 150 s += 2; 151 base = 16; 152 } else if ((base == 0 || base == 2) && 153 c == '0' && (*s == 'b' || *s == 'B')) { 154 c = s[1]; 155 s += 2; 156 base = 2; 157 } 158 if (base == 0) { 159 base = c == '0' ? 8 : 10; 160 } 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 = ((int)(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 } 190 if (c >= base) { 191 break; 192 } 193 if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) { 194 any = -1; 195 } else { 196 any = 1; 197 acc *= base; 198 acc += c; 199 } 200 } 201 if (any < 0) { 202 acc = neg ? LONG_MIN : LONG_MAX; 203 // errno = ERANGE; 204 } else if (neg) { 205 acc = -acc; 206 } 207 if (endptr != 0) { 208 if (any) { 209 *endptr = __CAST_AWAY_QUALIFIER(s - 1, const, char *); 210 } else { 211 *endptr = __CAST_AWAY_QUALIFIER(nptr, const, char *); 212 } 213 } 214 return acc; 215 } 216 217 unsigned long 218 strtoul(const char *nptr, char **endptr, int base) 219 { 220 const char *s = nptr; 221 unsigned long acc; 222 char c; 223 unsigned long cutoff; 224 int neg = 0, any, cutlim; 225 226 /* 227 * See strtol for comments as to the logic used. 228 */ 229 do { 230 c = *s++; 231 } while (isspace(c)); 232 if (c == '-') { 233 neg = 1; 234 c = *s++; 235 } else if (c == '+') { 236 c = *s++; 237 } 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 } 252 cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; 253 cutlim = ((int)((unsigned long)ULONG_MAX % (unsigned long)base)); 254 for (acc = 0, any = 0;; c = *s++) { 255 if (isdigit(c)) { 256 c -= '0'; 257 } else if (isalpha(c)) { 258 c -= isupper(c) ? 'A' - 10 : 'a' - 10; 259 } else { 260 break; 261 } 262 if (c >= base) { 263 break; 264 } 265 if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) { 266 any = -1; 267 } else { 268 any = 1; 269 acc *= base; 270 acc += c; 271 } 272 } 273 if (any < 0) { 274 acc = ULONG_MAX; 275 // errno = ERANGE; 276 } else if (neg) { 277 acc = -acc; 278 } 279 if (endptr != 0) { 280 if (any) { 281 *endptr = __CAST_AWAY_QUALIFIER(s - 1, const, char *); 282 } else { 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 */ 296 quad_t 297 strtoq(const char *nptr, char **endptr, int base) 298 { 299 const char *s; 300 u_quad_t acc; 301 char c; 302 u_quad_t qbase, cutoff; 303 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 } 323 if ((base == 0 || base == 16) && 324 c == '0' && (*s == 'x' || *s == 'X')) { 325 c = s[1]; 326 s += 2; 327 base = 16; 328 } 329 if (base == 0) { 330 base = c == '0' ? 8 : 10; 331 } 332 333 /* 334 * Compute the cutoff value between legal numbers and illegal 335 * numbers. That is the largest legal value, divided by the 336 * base. An input number that is greater than this value, if 337 * followed by a legal input character, is too big. One that 338 * is equal to this value may be valid or not; the limit 339 * between valid and invalid numbers is then based on the last 340 * digit. For instance, if the range for quads is 341 * [-9223372036854775808..9223372036854775807] and the input base 342 * is 10, cutoff will be set to 922337203685477580 and cutlim to 343 * either 7 (neg==0) or 8 (neg==1), meaning that if we have 344 * accumulated a value > 922337203685477580, or equal but the 345 * next digit is > 7 (or 8), the number is too big, and we will 346 * return a range error. 347 * 348 * Set any if any `digits' consumed; make it negative to indicate 349 * overflow. 350 */ 351 qbase = (unsigned)base; 352 cutoff = neg ? -(u_quad_t)QUAD_MIN : QUAD_MAX; 353 cutlim = ((int)(cutoff % qbase)); 354 cutoff /= qbase; 355 for (acc = 0, any = 0;; c = *s++) { 356 if (isdigit(c)) { 357 c -= '0'; 358 } else if (isalpha(c)) { 359 c -= isupper(c) ? 'A' - 10 : 'a' - 10; 360 } else { 361 break; 362 } 363 if (c >= base) { 364 break; 365 } 366 if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) { 367 any = -1; 368 } else { 369 any = 1; 370 acc *= qbase; 371 acc += c; 372 } 373 } 374 if (any < 0) { 375 acc = neg ? QUAD_MIN : QUAD_MAX; 376 // errno = ERANGE; 377 } else if (neg) { 378 acc = -acc; 379 } 380 if (endptr != 0) { 381 if (any) { 382 *endptr = __CAST_AWAY_QUALIFIER(s - 1, const, char *); 383 } else { 384 *endptr = __CAST_AWAY_QUALIFIER(nptr, const, char *); 385 } 386 } 387 388 return acc; 389 } 390 391 392 /* 393 * Convert a string to an unsigned quad integer. 394 * 395 * Ignores `locale' stuff. Assumes that the upper and lower case 396 * alphabets and digits are each contiguous. 397 */ 398 u_quad_t 399 strtouq(const char *nptr, 400 char **endptr, 401 int base) 402 { 403 const char *s = nptr; 404 u_quad_t acc; 405 char c; 406 u_quad_t qbase, cutoff; 407 int neg, any, cutlim; 408 409 /* 410 * See strtoq for comments as to the logic used. 411 */ 412 s = nptr; 413 do { 414 c = *s++; 415 } while (isspace(c)); 416 if (c == '-') { 417 neg = 1; 418 c = *s++; 419 } else { 420 neg = 0; 421 if (c == '+') { 422 c = *s++; 423 } 424 } 425 if ((base == 0 || base == 16) && 426 c == '0' && (*s == 'x' || *s == 'X')) { 427 c = s[1]; 428 s += 2; 429 base = 16; 430 } 431 if (base == 0) { 432 base = c == '0' ? 8 : 10; 433 } 434 qbase = (unsigned)base; 435 cutoff = (u_quad_t)UQUAD_MAX / qbase; 436 cutlim = ((int)((u_quad_t)UQUAD_MAX % qbase)); 437 for (acc = 0, any = 0;; c = *s++) { 438 if (isdigit(c)) { 439 c -= '0'; 440 } else if (isalpha(c)) { 441 c -= isupper(c) ? 'A' - 10 : 'a' - 10; 442 } else { 443 break; 444 } 445 if (c >= base) { 446 break; 447 } 448 if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) { 449 any = -1; 450 } else { 451 any = 1; 452 acc *= qbase; 453 acc += c; 454 } 455 } 456 if (any < 0) { 457 acc = UQUAD_MAX; 458 // errno = ERANGE; 459 } else if (neg) { 460 acc = -acc; 461 } 462 if (endptr != 0) { 463 if (any) { 464 *endptr = __CAST_AWAY_QUALIFIER(s - 1, const, char *); 465 } else { 466 *endptr = __CAST_AWAY_QUALIFIER(nptr, const, char *); 467 } 468 } 469 470 return acc; 471 } 472