summaryrefslogtreecommitdiff
path: root/src/lib/libc/stdlib/strtoll.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lib/libc/stdlib/strtoll.c (renamed from src/lib/libc/stdlib/strtoq.c)96
1 files changed, 61 insertions, 35 deletions
diff --git a/src/lib/libc/stdlib/strtoq.c b/src/lib/libc/stdlib/strtoll.c
index fc559e9d7f..ac9353890f 100644
--- a/src/lib/libc/stdlib/strtoq.c
+++ b/src/lib/libc/stdlib/strtoll.c
@@ -10,11 +10,7 @@
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the 11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution. 12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software 13 * 3. Neither the name of the University nor the names of its contributors
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software 14 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission. 15 * without specific prior written permission.
20 * 16 *
@@ -32,33 +28,32 @@
32 */ 28 */
33 29
34#if defined(LIBC_SCCS) && !defined(lint) 30#if defined(LIBC_SCCS) && !defined(lint)
35static char sccsid[] = "@(#)strtoq.c 5.1 (Berkeley) 6/26/92"; 31static const char rcsid[] = "$OpenBSD: strtoll.c,v 1.2 2003/06/02 20:18:38 millert Exp $";
36#endif /* LIBC_SCCS and not lint */ 32#endif /* LIBC_SCCS and not lint */
37 33
38#include <sys/types.h> 34#include <sys/types.h>
39 35
40#include <limits.h>
41#include <errno.h>
42#include <ctype.h> 36#include <ctype.h>
37#include <errno.h>
38#include <limits.h>
43#include <stdlib.h> 39#include <stdlib.h>
44 40
45/* 41/*
46 * Convert a string to a quad integer. 42 * Convert a string to a long long.
47 * 43 *
48 * Ignores `locale' stuff. Assumes that the upper and lower case 44 * Ignores `locale' stuff. Assumes that the upper and lower case
49 * alphabets and digits are each contiguous. 45 * alphabets and digits are each contiguous.
50 */ 46 */
51quad_t 47long long
52strtoq(nptr, endptr, base) 48strtoll(nptr, endptr, base)
53 const char *nptr; 49 const char *nptr;
54 char **endptr; 50 char **endptr;
55 register int base; 51 int base;
56{ 52{
57 register const char *s; 53 const char *s;
58 register u_quad_t acc; 54 long long acc, cutoff;
59 register int c; 55 int c;
60 register u_quad_t qbase, cutoff; 56 int neg, any, cutlim;
61 register int neg, any, cutlim;
62 57
63 /* 58 /*
64 * Skip white space and pick up leading +/- sign if any. 59 * Skip white space and pick up leading +/- sign if any.
@@ -67,7 +62,7 @@ strtoq(nptr, endptr, base)
67 */ 62 */
68 s = nptr; 63 s = nptr;
69 do { 64 do {
70 c = *s++; 65 c = (unsigned char) *s++;
71 } while (isspace(c)); 66 } while (isspace(c));
72 if (c == '-') { 67 if (c == '-') {
73 neg = 1; 68 neg = 1;
@@ -93,7 +88,7 @@ strtoq(nptr, endptr, base)
93 * followed by a legal input character, is too big. One that 88 * followed by a legal input character, is too big. One that
94 * is equal to this value may be valid or not; the limit 89 * is equal to this value may be valid or not; the limit
95 * between valid and invalid numbers is then based on the last 90 * between valid and invalid numbers is then based on the last
96 * digit. For instance, if the range for quads is 91 * digit. For instance, if the range for long longs is
97 * [-9223372036854775808..9223372036854775807] and the input base 92 * [-9223372036854775808..9223372036854775807] and the input base
98 * is 10, cutoff will be set to 922337203685477580 and cutlim to 93 * is 10, cutoff will be set to 922337203685477580 and cutlim to
99 * either 7 (neg==0) or 8 (neg==1), meaning that if we have 94 * either 7 (neg==0) or 8 (neg==1), meaning that if we have
@@ -104,11 +99,17 @@ strtoq(nptr, endptr, base)
104 * Set any if any `digits' consumed; make it negative to indicate 99 * Set any if any `digits' consumed; make it negative to indicate
105 * overflow. 100 * overflow.
106 */ 101 */
107 qbase = (unsigned)base; 102 cutoff = neg ? LLONG_MIN : LLONG_MAX;
108 cutoff = neg ? -(u_quad_t)QUAD_MIN : QUAD_MAX; 103 cutlim = cutoff % base;
109 cutlim = cutoff % qbase; 104 cutoff /= base;
110 cutoff /= qbase; 105 if (neg) {
111 for (acc = 0, any = 0;; c = *s++) { 106 if (cutlim > 0) {
107 cutlim -= base;
108 cutoff += 1;
109 }
110 cutlim = -cutlim;
111 }
112 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
112 if (isdigit(c)) 113 if (isdigit(c))
113 c -= '0'; 114 c -= '0';
114 else if (isalpha(c)) 115 else if (isalpha(c))
@@ -117,20 +118,45 @@ strtoq(nptr, endptr, base)
117 break; 118 break;
118 if (c >= base) 119 if (c >= base)
119 break; 120 break;
120 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) 121 if (any < 0)
121 any = -1; 122 continue;
122 else { 123 if (neg) {
123 any = 1; 124 if (acc < cutoff || (acc == cutoff && c > cutlim)) {
124 acc *= qbase; 125 any = -1;
125 acc += c; 126 acc = LLONG_MIN;
127 errno = ERANGE;
128 } else {
129 any = 1;
130 acc *= base;
131 acc -= c;
132 }
133 } else {
134 if (acc > cutoff || (acc == cutoff && c > cutlim)) {
135 any = -1;
136 acc = LLONG_MAX;
137 errno = ERANGE;
138 } else {
139 any = 1;
140 acc *= base;
141 acc += c;
142 }
126 } 143 }
127 } 144 }
128 if (any < 0) {
129 acc = neg ? QUAD_MIN : QUAD_MAX;
130 errno = ERANGE;
131 } else if (neg)
132 acc = -acc;
133 if (endptr != 0) 145 if (endptr != 0)
134 *endptr = (char *) (any ? s - 1 : nptr); 146 *endptr = (char *) (any ? s - 1 : nptr);
135 return (acc); 147 return (acc);
136} 148}
149
150#ifdef __weak_alias
151__weak_alias(strtoq, strtoll);
152#else
153quad_t
154strtoq(nptr, endptr, base)
155 const char *nptr;
156 char **endptr;
157 int base;
158{
159
160 return ((quad_t)strtoll(nptr, endptr, base);
161}
162#endif