summaryrefslogtreecommitdiff
path: root/src/lib/libc/stdlib/strtoul.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/strtoul.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/strtoul.c')
-rw-r--r--src/lib/libc/stdlib/strtoul.c39
1 files changed, 22 insertions, 17 deletions
diff --git a/src/lib/libc/stdlib/strtoul.c b/src/lib/libc/stdlib/strtoul.c
index 00f7210fa1..1522bec584 100644
--- a/src/lib/libc/stdlib/strtoul.c
+++ b/src/lib/libc/stdlib/strtoul.c
@@ -33,12 +33,12 @@
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)strtoul.c 5.3 (Berkeley) 2/23/91";*/ 35/*static char *sccsid = "from: @(#)strtoul.c 5.3 (Berkeley) 2/23/91";*/
36static char *rcsid = "$Id: strtoul.c,v 1.1.1.1 1995/10/18 08:42:20 deraadt Exp $"; 36static char *rcsid = "$Id: strtoul.c,v 1.2 1995/12/21 14:58:38 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 37#endif /* LIBC_SCCS and not lint */
38 38
39#include <limits.h>
40#include <ctype.h> 39#include <ctype.h>
41#include <errno.h> 40#include <errno.h>
41#include <limits.h>
42#include <stdlib.h> 42#include <stdlib.h>
43 43
44/* 44/*
@@ -53,23 +53,26 @@ strtoul(nptr, endptr, base)
53 char **endptr; 53 char **endptr;
54 register int base; 54 register int base;
55{ 55{
56 register const char *s = nptr; 56 register const char *s;
57 register unsigned long acc; 57 register unsigned long acc, cutoff;
58 register int c; 58 register int c;
59 register unsigned long cutoff; 59 register int neg, any, cutlim;
60 register int neg = 0, any, cutlim;
61 60
62 /* 61 /*
63 * See strtol for comments as to the logic used. 62 * See strtol for comments as to the logic used.
64 */ 63 */
64 s = nptr;
65 do { 65 do {
66 c = *s++; 66 c = *s++;
67 } while (isspace(c)); 67 } while (isspace(c));
68 if (c == '-') { 68 if (c == '-') {
69 neg = 1; 69 neg = 1;
70 c = *s++; 70 c = *s++;
71 } else if (c == '+') 71 } else {
72 c = *s++; 72 neg = 0;
73 if (c == '+')
74 c = *s++;
75 }
73 if ((base == 0 || base == 16) && 76 if ((base == 0 || base == 16) &&
74 c == '0' && (*s == 'x' || *s == 'X')) { 77 c == '0' && (*s == 'x' || *s == 'X')) {
75 c = s[1]; 78 c = s[1];
@@ -78,8 +81,9 @@ strtoul(nptr, endptr, base)
78 } 81 }
79 if (base == 0) 82 if (base == 0)
80 base = c == '0' ? 8 : 10; 83 base = c == '0' ? 8 : 10;
81 cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; 84
82 cutlim = (unsigned long)ULONG_MAX % (unsigned long)base; 85 cutoff = ULONG_MAX / (unsigned long)base;
86 cutlim = ULONG_MAX % (unsigned long)base;
83 for (acc = 0, any = 0;; c = *s++) { 87 for (acc = 0, any = 0;; c = *s++) {
84 if (isdigit(c)) 88 if (isdigit(c))
85 c -= '0'; 89 c -= '0';
@@ -89,18 +93,19 @@ strtoul(nptr, endptr, base)
89 break; 93 break;
90 if (c >= base) 94 if (c >= base)
91 break; 95 break;
92 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) 96 if (any < 0)
97 continue;
98 if (acc > cutoff || acc == cutoff && c > cutlim) {
93 any = -1; 99 any = -1;
94 else { 100 acc = ULONG_MAX;
101 errno = ERANGE;
102 } else {
95 any = 1; 103 any = 1;
96 acc *= base; 104 acc *= (unsigned long)base;
97 acc += c; 105 acc += c;
98 } 106 }
99 } 107 }
100 if (any < 0) { 108 if (neg && any > 0)
101 acc = ULONG_MAX;
102 errno = ERANGE;
103 } else if (neg)
104 acc = -acc; 109 acc = -acc;
105 if (endptr != 0) 110 if (endptr != 0)
106 *endptr = (char *) (any ? s - 1 : nptr); 111 *endptr = (char *) (any ? s - 1 : nptr);