#include <ctype.h>#include <errno.h>#include <limits.h>Include dependency graph for strtol.c:
Go to the source code of this file.
Functions | |
| long | strtol (const char *nptr, char **endptr, register int base) |
|
||||||||||||||||
|
Definition at line 53 of file strtol.c.
00054 {
00055 register const char *s;
00056 register long acc, cutoff;
00057 register int c;
00058 register int neg, any, cutlim;
00059
00060 /*
00061 * Skip white space and pick up leading +/- sign if any.
00062 * If base is 0, allow 0x for hex and 0 for octal, else
00063 * assume decimal; if base is already 16, allow 0x.
00064 */
00065 s = nptr;
00066 do {
00067 c = (unsigned char) *s++;
00068 } while (isspace(c));
00069 if (c == '-') {
00070 neg = 1;
00071 c = *s++;
00072 } else {
00073 neg = 0;
00074 if (c == '+')
00075 c = *s++;
00076 }
00077 if ((base == 0 || base == 16) &&
00078 c == '0' && (*s == 'x' || *s == 'X')) {
00079 c = s[1];
00080 s += 2;
00081 base = 16;
00082 }
00083 if (base == 0)
00084 base = c == '0' ? 8 : 10;
00085
00086 /*
00087 * Compute the cutoff value between legal numbers and illegal
00088 * numbers. That is the largest legal value, divided by the
00089 * base. An input number that is greater than this value, if
00090 * followed by a legal input character, is too big. One that
00091 * is equal to this value may be valid or not; the limit
00092 * between valid and invalid numbers is then based on the last
00093 * digit. For instance, if the range for longs is
00094 * [-2147483648..2147483647] and the input base is 10,
00095 * cutoff will be set to 214748364 and cutlim to either
00096 * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
00097 * a value > 214748364, or equal but the next digit is > 7 (or 8),
00098 * the number is too big, and we will return a range error.
00099 *
00100 * Set any if any `digits' consumed; make it negative to indicate
00101 * overflow.
00102 */
00103 cutoff = neg ? LONG_MIN : LONG_MAX;
00104 cutlim = cutoff % base;
00105 cutoff /= base;
00106 if (neg) {
00107 if (cutlim > 0) {
00108 cutlim -= base;
00109 cutoff += 1;
00110 }
00111 cutlim = -cutlim;
00112 }
00113 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
00114 if (isdigit(c))
00115 c -= '0';
00116 else if (isalpha(c))
00117 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
00118 else
00119 break;
00120 if (c >= base)
00121 break;
00122 if (any < 0)
00123 continue;
00124 if (neg) {
00125 if ((acc < cutoff || acc == cutoff) && c > cutlim) {
00126 any = -1;
00127 acc = LONG_MIN;
00128 errno = ERANGE;
00129 } else {
00130 any = 1;
00131 acc *= base;
00132 acc -= c;
00133 }
00134 } else {
00135 if ((acc > cutoff || acc == cutoff) && c > cutlim) {
00136 any = -1;
00137 acc = LONG_MAX;
00138 errno = ERANGE;
00139 } else {
00140 any = 1;
00141 acc *= base;
00142 acc += c;
00143 }
00144 }
00145 }
00146 if (endptr != 0)
00147 *endptr = (char *) (any ? s - 1 : nptr);
00148 return (acc);
00149 }
|
1.3.4