|
|
1.1 ! root 1: /*- ! 2: * Copyright (c) 1990 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms are permitted ! 6: * provided that: (1) source distributions retain this entire copyright ! 7: * notice and comment, and (2) distributions including binaries display ! 8: * the following acknowledgement: ``This product includes software ! 9: * developed by the University of California, Berkeley and its contributors'' ! 10: * in the documentation or other materials provided with the distribution ! 11: * and in all advertising materials mentioning features or use of this ! 12: * software. Neither the name of the University nor the names of its ! 13: * contributors may be used to endorse or promote products derived ! 14: * from this software without specific prior written permission. ! 15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 16: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 18: */ ! 19: ! 20: #if defined(LIBC_SCCS) && !defined(lint) ! 21: static char sccsid[] = "@(#)strtol.c 5.3 (Berkeley) 5/17/90"; ! 22: #endif /* LIBC_SCCS and not lint */ ! 23: ! 24: #include <limits.h> ! 25: #include <ctype.h> ! 26: #include <errno.h> ! 27: #include <stdlib.h> ! 28: ! 29: ! 30: /* ! 31: * Convert a string to a long integer. ! 32: * ! 33: * Ignores `locale' stuff. Assumes that the upper and lower case ! 34: * alphabets and digits are each contiguous. ! 35: */ ! 36: long ! 37: strtol(nptr, endptr, base) ! 38: char *nptr, **endptr; ! 39: register int base; ! 40: { ! 41: register char *s = nptr; ! 42: register unsigned long acc; ! 43: register int c; ! 44: register unsigned long cutoff; ! 45: register int neg = 0, any, cutlim; ! 46: ! 47: /* ! 48: * Skip white space and pick up leading +/- sign if any. ! 49: * If base is 0, allow 0x for hex and 0 for octal, else ! 50: * assume decimal; if base is already 16, allow 0x. ! 51: */ ! 52: do { ! 53: c = *s++; ! 54: } while (isspace(c)); ! 55: if (c == '-') { ! 56: neg = 1; ! 57: c = *s++; ! 58: } else if (c == '+') ! 59: c = *s++; ! 60: if ((base == 0 || base == 16) && ! 61: c == '0' && (*s == 'x' || *s == 'X')) { ! 62: c = s[1]; ! 63: s += 2; ! 64: base = 16; ! 65: } ! 66: if (base == 0) ! 67: base = c == '0' ? 8 : 10; ! 68: ! 69: /* ! 70: * Compute the cutoff value between legal numbers and illegal ! 71: * numbers. That is the largest legal value, divided by the ! 72: * base. An input number that is greater than this value, if ! 73: * followed by a legal input character, is too big. One that ! 74: * is equal to this value may be valid or not; the limit ! 75: * between valid and invalid numbers is then based on the last ! 76: * digit. For instance, if the range for longs is ! 77: * [-2147483648..2147483647] and the input base is 10, ! 78: * cutoff will be set to 214748364 and cutlim to either ! 79: * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated ! 80: * a value > 214748364, or equal but the next digit is > 7 (or 8), ! 81: * the number is too big, and we will return a range error. ! 82: * ! 83: * Set any if any `digits' consumed; make it negative to indicate ! 84: * overflow. ! 85: */ ! 86: cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX; ! 87: cutlim = cutoff % (unsigned long)base; ! 88: cutoff /= (unsigned long)base; ! 89: for (acc = 0, any = 0;; c = *s++) { ! 90: if (isdigit(c)) ! 91: c -= '0'; ! 92: else if (isalpha(c)) ! 93: c -= isupper(c) ? 'A' - 10 : 'a' - 10; ! 94: else ! 95: break; ! 96: if (c >= base) ! 97: break; ! 98: if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) ! 99: any = -1; ! 100: else { ! 101: any = 1; ! 102: acc *= base; ! 103: acc += c; ! 104: } ! 105: } ! 106: if (any < 0) { ! 107: acc = neg ? LONG_MIN : LONG_MAX; ! 108: errno = ERANGE; ! 109: } else if (neg) ! 110: acc = -acc; ! 111: if (endptr != 0) ! 112: *endptr = any ? s - 1 : nptr; ! 113: return (acc); ! 114: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.