14a5d661aSToomas Soome /*- 24a5d661aSToomas Soome * Copyright (c) 1990, 1993 34a5d661aSToomas Soome * The Regents of the University of California. All rights reserved. 44a5d661aSToomas Soome * 54a5d661aSToomas Soome * Redistribution and use in source and binary forms, with or without 64a5d661aSToomas Soome * modification, are permitted provided that the following conditions 74a5d661aSToomas Soome * are met: 84a5d661aSToomas Soome * 1. Redistributions of source code must retain the above copyright 94a5d661aSToomas Soome * notice, this list of conditions and the following disclaimer. 104a5d661aSToomas Soome * 2. Redistributions in binary form must reproduce the above copyright 114a5d661aSToomas Soome * notice, this list of conditions and the following disclaimer in the 124a5d661aSToomas Soome * documentation and/or other materials provided with the distribution. 134a5d661aSToomas Soome * 4. Neither the name of the University nor the names of its contributors 144a5d661aSToomas Soome * may be used to endorse or promote products derived from this software 154a5d661aSToomas Soome * without specific prior written permission. 164a5d661aSToomas Soome * 174a5d661aSToomas Soome * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 184a5d661aSToomas Soome * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 194a5d661aSToomas Soome * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 204a5d661aSToomas Soome * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 214a5d661aSToomas Soome * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 224a5d661aSToomas Soome * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 234a5d661aSToomas Soome * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 244a5d661aSToomas Soome * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 254a5d661aSToomas Soome * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 264a5d661aSToomas Soome * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 274a5d661aSToomas Soome * SUCH DAMAGE. 284a5d661aSToomas Soome */ 294a5d661aSToomas Soome 304a5d661aSToomas Soome #include <sys/cdefs.h> 314a5d661aSToomas Soome __FBSDID("$FreeBSD$"); 324a5d661aSToomas Soome 334a5d661aSToomas Soome #if defined(LIBC_SCCS) && !defined(lint) 344a5d661aSToomas Soome static char sccsid[] = "@(#)strtol.c 8.1 (Berkeley) 6/4/93"; 354a5d661aSToomas Soome #endif /* LIBC_SCCS and not lint */ 364a5d661aSToomas Soome 374a5d661aSToomas Soome #include "stand.h" 384a5d661aSToomas Soome #include <limits.h> 394a5d661aSToomas Soome 404a5d661aSToomas Soome /* 414a5d661aSToomas Soome * Convert a string to a long integer. 424a5d661aSToomas Soome * 434a5d661aSToomas Soome * Ignores `locale' stuff. Assumes that the upper and lower case 444a5d661aSToomas Soome * alphabets and digits are each contiguous. 454a5d661aSToomas Soome */ 464a5d661aSToomas Soome long 474a5d661aSToomas Soome strtol(nptr, endptr, base) 484a5d661aSToomas Soome const char *nptr; 494a5d661aSToomas Soome char **endptr; 504a5d661aSToomas Soome int base; 514a5d661aSToomas Soome { 524a5d661aSToomas Soome const char *s; 534a5d661aSToomas Soome unsigned long acc; 544a5d661aSToomas Soome unsigned char c; 554a5d661aSToomas Soome unsigned long cutoff; 564a5d661aSToomas Soome int neg = 0, any, cutlim; 574a5d661aSToomas Soome 584a5d661aSToomas Soome /* Be sensible about NULL strings */ 594a5d661aSToomas Soome if (nptr == NULL) 604a5d661aSToomas Soome nptr = ""; 614a5d661aSToomas Soome s = nptr; 624a5d661aSToomas Soome 634a5d661aSToomas Soome /* 644a5d661aSToomas Soome * Skip white space and pick up leading +/- sign if any. 654a5d661aSToomas Soome * If base is 0, allow 0x for hex and 0 for octal, else 664a5d661aSToomas Soome * assume decimal; if base is already 16, allow 0x. 674a5d661aSToomas Soome */ 684a5d661aSToomas Soome do { 694a5d661aSToomas Soome c = *s++; 704a5d661aSToomas Soome } while (isspace(c)); 714a5d661aSToomas Soome if (c == '-') { 724a5d661aSToomas Soome neg = 1; 734a5d661aSToomas Soome c = *s++; 744a5d661aSToomas Soome } else if (c == '+') 754a5d661aSToomas Soome c = *s++; 764a5d661aSToomas Soome if ((base == 0 || base == 16) && 774a5d661aSToomas Soome c == '0' && (*s == 'x' || *s == 'X')) { 784a5d661aSToomas Soome c = s[1]; 794a5d661aSToomas Soome s += 2; 804a5d661aSToomas Soome base = 16; 814a5d661aSToomas Soome } 824a5d661aSToomas Soome if (base == 0) 834a5d661aSToomas Soome base = c == '0' ? 8 : 10; 844a5d661aSToomas Soome 854a5d661aSToomas Soome /* 864a5d661aSToomas Soome * Compute the cutoff value between legal numbers and illegal 874a5d661aSToomas Soome * numbers. That is the largest legal value, divided by the 884a5d661aSToomas Soome * base. An input number that is greater than this value, if 894a5d661aSToomas Soome * followed by a legal input character, is too big. One that 904a5d661aSToomas Soome * is equal to this value may be valid or not; the limit 914a5d661aSToomas Soome * between valid and invalid numbers is then based on the last 924a5d661aSToomas Soome * digit. For instance, if the range for longs is 934a5d661aSToomas Soome * [-2147483648..2147483647] and the input base is 10, 944a5d661aSToomas Soome * cutoff will be set to 214748364 and cutlim to either 954a5d661aSToomas Soome * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated 964a5d661aSToomas Soome * a value > 214748364, or equal but the next digit is > 7 (or 8), 974a5d661aSToomas Soome * the number is too big, and we will return a range error. 984a5d661aSToomas Soome * 994a5d661aSToomas Soome * Set any if any `digits' consumed; make it negative to indicate 1004a5d661aSToomas Soome * overflow. 1014a5d661aSToomas Soome */ 1024a5d661aSToomas Soome cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX; 1034a5d661aSToomas Soome cutlim = cutoff % (unsigned long)base; 1044a5d661aSToomas Soome cutoff /= (unsigned long)base; 1054a5d661aSToomas Soome for (acc = 0, any = 0;; c = *s++) { 1064a5d661aSToomas Soome if (!isascii(c)) 1074a5d661aSToomas Soome break; 1084a5d661aSToomas Soome if (isdigit(c)) 1094a5d661aSToomas Soome c -= '0'; 1104a5d661aSToomas Soome else if (isalpha(c)) 1114a5d661aSToomas Soome c -= isupper(c) ? 'A' - 10 : 'a' - 10; 1124a5d661aSToomas Soome else 1134a5d661aSToomas Soome break; 1144a5d661aSToomas Soome if (c >= base) 1154a5d661aSToomas Soome break; 1164a5d661aSToomas Soome if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) 1174a5d661aSToomas Soome any = -1; 1184a5d661aSToomas Soome else { 1194a5d661aSToomas Soome any = 1; 1204a5d661aSToomas Soome acc *= base; 1214a5d661aSToomas Soome acc += c; 1224a5d661aSToomas Soome } 1234a5d661aSToomas Soome } 1244a5d661aSToomas Soome if (any < 0) { 1254a5d661aSToomas Soome acc = neg ? LONG_MIN : LONG_MAX; 1264a5d661aSToomas Soome errno = ERANGE; 1274a5d661aSToomas Soome } else if (neg) 1284a5d661aSToomas Soome acc = -acc; 129*830d404aSToomas Soome if (endptr != NULL) 1304a5d661aSToomas Soome *endptr = (char *)(any ? s - 1 : nptr); 1314a5d661aSToomas Soome return (acc); 1324a5d661aSToomas Soome } 133