summaryrefslogtreecommitdiff
path: root/src/lib/libc/stdlib/strtoq.c
diff options
context:
space:
mode:
authorderaadt <>1995-12-21 14:58:39 +0000
committerderaadt <>1995-12-21 14:58:39 +0000
commit0ec9503a81eeeb5a23e8654cc0e76fca89ab163b (patch)
tree5139e3085b6bfe3f9b0ebfb69133325f13456ead /src/lib/libc/stdlib/strtoq.c
parent0fd8d706013540776674a583d2456224f1631724 (diff)
downloadopenbsd-0ec9503a81eeeb5a23e8654cc0e76fca89ab163b.tar.gz
openbsd-0ec9503a81eeeb5a23e8654cc0e76fca89ab163b.tar.bz2
openbsd-0ec9503a81eeeb5a23e8654cc0e76fca89ab163b.zip
from netbsd; Rearrange to avoid sign problems with GCC.
Diffstat (limited to 'src/lib/libc/stdlib/strtoq.c')
-rw-r--r--src/lib/libc/stdlib/strtoq.c54
1 files changed, 35 insertions, 19 deletions
diff --git a/src/lib/libc/stdlib/strtoq.c b/src/lib/libc/stdlib/strtoq.c
index fc559e9d7f..003c020d71 100644
--- a/src/lib/libc/stdlib/strtoq.c
+++ b/src/lib/libc/stdlib/strtoq.c
@@ -37,9 +37,9 @@ static char sccsid[] = "@(#)strtoq.c 5.1 (Berkeley) 6/26/92";
37 37
38#include <sys/types.h> 38#include <sys/types.h>
39 39
40#include <limits.h>
41#include <errno.h>
42#include <ctype.h> 40#include <ctype.h>
41#include <errno.h>
42#include <limits.h>
43#include <stdlib.h> 43#include <stdlib.h>
44 44
45/* 45/*
@@ -55,9 +55,8 @@ strtoq(nptr, endptr, base)
55 register int base; 55 register int base;
56{ 56{
57 register const char *s; 57 register const char *s;
58 register u_quad_t acc; 58 register quad_t acc, cutoff;
59 register int c; 59 register int c;
60 register u_quad_t qbase, cutoff;
61 register int neg, any, cutlim; 60 register int neg, any, cutlim;
62 61
63 /* 62 /*
@@ -104,10 +103,16 @@ strtoq(nptr, endptr, base)
104 * Set any if any `digits' consumed; make it negative to indicate 103 * Set any if any `digits' consumed; make it negative to indicate
105 * overflow. 104 * overflow.
106 */ 105 */
107 qbase = (unsigned)base; 106 cutoff = neg ? QUAD_MIN : QUAD_MAX;
108 cutoff = neg ? -(u_quad_t)QUAD_MIN : QUAD_MAX; 107 cutlim = cutoff % base;
109 cutlim = cutoff % qbase; 108 cutoff /= base;
110 cutoff /= qbase; 109 if (neg) {
110 if (cutlim > 0) {
111 cutlim -= base;
112 cutoff += 1;
113 }
114 cutlim = -cutlim;
115 }
111 for (acc = 0, any = 0;; c = *s++) { 116 for (acc = 0, any = 0;; c = *s++) {
112 if (isdigit(c)) 117 if (isdigit(c))
113 c -= '0'; 118 c -= '0';
@@ -117,19 +122,30 @@ strtoq(nptr, endptr, base)
117 break; 122 break;
118 if (c >= base) 123 if (c >= base)
119 break; 124 break;
120 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) 125 if (any < 0)
121 any = -1; 126 continue;
122 else { 127 if (neg) {
123 any = 1; 128 if (acc < cutoff || acc == cutoff && c > cutlim) {
124 acc *= qbase; 129 any = -1;
125 acc += c; 130 acc = QUAD_MIN;
131 errno = ERANGE;
132 } else {
133 any = 1;
134 acc *= base;
135 acc -= c;
136 }
137 } else {
138 if (acc > cutoff || acc == cutoff && c > cutlim) {
139 any = -1;
140 acc = QUAD_MAX;
141 errno = ERANGE;
142 } else {
143 any = 1;
144 acc *= base;
145 acc += c;
146 }
126 } 147 }
127 } 148 }
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) 149 if (endptr != 0)
134 *endptr = (char *) (any ? s - 1 : nptr); 150 *endptr = (char *) (any ? s - 1 : nptr);
135 return (acc); 151 return (acc);