Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-4-Clause-UC */
2 : : /*-
3 : : * Copyright (c) 1990, 1993
4 : : * The Regents of the University of California. All rights reserved.
5 : : *
6 : : * Redistribution and use in source and binary forms, with or without
7 : : * modification, are permitted provided that the following conditions
8 : : * are met:
9 : : * 1. Redistributions of source code must retain the above copyright
10 : : * notice, this list of conditions and the following disclaimer.
11 : : * 2. Redistributions in binary form must reproduce the above copyright
12 : : * notice, this list of conditions and the following disclaimer in the
13 : : * documentation and/or other materials provided with the distribution.
14 : : * 3. All advertising materials mentioning features or use of this software
15 : : * must display the following acknowledgement:
16 : : * This product includes software developed by the University of
17 : : * California, Berkeley and its contributors.
18 : : * 4. Neither the name of the University nor the names of its contributors
19 : : * may be used to endorse or promote products derived from this software
20 : : * without specific prior written permission.
21 : : *
22 : : * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 : : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 : : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 : : * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 : : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 : : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 : : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 : : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 : : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 : : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 : : * SUCH DAMAGE.
33 : : */
34 : : #include <limits.h>
35 : : #include <ctype.h>
36 : : #include <errno.h>
37 : : #include <stdlib.h>
38 : :
39 : : /*
40 : : * Convert a string to a long integer.
41 : : *
42 : : * Ignores `locale' stuff. Assumes that the upper and lower case
43 : : * alphabets and digits are each contiguous.
44 : : */
45 : : long strtol(const char *nptr, char **endptr, register int base)
46 : : {
47 : 0 : register const char *s = nptr;
48 : : register unsigned long acc;
49 : : register int c;
50 : : register unsigned long cutoff;
51 : 0 : register int neg = 0, any, cutlim;
52 : :
53 : : /*
54 : : * Skip white space and pick up leading +/- sign if any.
55 : : * If base is 0, allow 0x for hex and 0 for octal, else
56 : : * assume decimal; if base is already 16, allow 0x.
57 : : */
58 : : do {
59 : 0 : c = *s++;
60 [ # # ]: 0 : } while (isspace(c));
61 [ # # ]: 0 : if (c == '-') {
62 : 0 : neg = 1;
63 : 0 : c = *s++;
64 [ # # ]: 0 : } else if (c == '+') {
65 : 0 : c = *s++;
66 : : }
67 : :
68 [ # # # # : 0 : if ((base == 0 || base == 16) &&
# # ]
69 [ # # # # ]: 0 : c == '0' && (*s == 'x' || *s == 'X')) {
70 : 0 : c = s[1];
71 : 0 : s += 2;
72 : 0 : base = 16;
73 : : }
74 : :
75 [ # # ]: 0 : if (base == 0) {
76 [ # # ]: 0 : base = c == '0' ? 8 : 10;
77 : : }
78 : :
79 : : /*
80 : : * Compute the cutoff value between legal numbers and illegal
81 : : * numbers. That is the largest legal value, divided by the
82 : : * base. An input number that is greater than this value, if
83 : : * followed by a legal input character, is too big. One that
84 : : * is equal to this value may be valid or not; the limit
85 : : * between valid and invalid numbers is then based on the last
86 : : * digit. For instance, if the range for longs is
87 : : * [-2147483648..2147483647] and the input base is 10,
88 : : * cutoff will be set to 214748364 and cutlim to either
89 : : * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
90 : : * a value > 214748364, or equal but the next digit is > 7 (or 8),
91 : : * the number is too big, and we will return a range error.
92 : : *
93 : : * Set any if any `digits' consumed; make it negative to indicate
94 : : * overflow.
95 : : */
96 [ # # ]: 0 : cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
97 : 0 : cutlim = cutoff % (unsigned long)base;
98 : 0 : cutoff /= (unsigned long)base;
99 : 0 : for (acc = 0, any = 0;; c = *s++) {
100 [ # # ]: 0 : if (isdigit(c)) {
101 : 0 : c -= '0';
102 [ # # ]: 0 : } else if (isalpha(c)) {
103 [ # # ]: 0 : c -= isupper(c) ? 'A' - 10 : 'a' - 10;
104 : : } else {
105 : 0 : break;
106 : : }
107 [ # # ]: 0 : if (c >= base) {
108 : 0 : break;
109 : : }
110 [ # # # # : 0 : if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) {
# # # # ]
111 : 0 : any = -1;
112 : : } else {
113 : 0 : any = 1;
114 : 0 : acc *= base;
115 : 0 : acc += c;
116 : : }
117 : : }
118 : :
119 [ # # ]: 0 : if (any < 0) {
120 [ # # ]: 0 : acc = neg ? LONG_MIN : LONG_MAX;
121 : 0 : errno = ERANGE;
122 [ # # ]: 0 : } else if (neg) {
123 : 0 : acc = -acc;
124 : : }
125 : :
126 [ # # ]: 0 : if (endptr != NULL) {
127 [ # # ]: 0 : *endptr = (char *)(any ? s - 1 : nptr);
128 : : }
129 : 0 : return acc;
130 : : }
|