|
|
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.