Index: fusl/src/internal/intscan.c |
diff --git a/fusl/src/internal/intscan.c b/fusl/src/internal/intscan.c |
index 65d497ec8a6fbabe6dafe65983d79c2bb9b2abf1..6055337a413d35532236210a6d0d6fd2f17a891a 100644 |
--- a/fusl/src/internal/intscan.c |
+++ b/fusl/src/internal/intscan.c |
@@ -4,97 +4,108 @@ |
#include "shgetc.h" |
/* Lookup table for digit values. -1==255>=36 -> invalid */ |
-static const unsigned char table[] = { -1, |
--1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
--1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
--1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1, |
--1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, |
-25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1, |
--1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, |
-25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1, |
--1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
--1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
--1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
--1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
--1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
--1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
--1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
--1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, |
+static const unsigned char table[] = { |
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, |
+ 8, 9, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, |
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, |
+ -1, -1, -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, |
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
}; |
-unsigned long long __intscan(FILE *f, unsigned base, int pok, unsigned long long lim) |
-{ |
- const unsigned char *val = table+1; |
- int c, neg=0; |
- unsigned x; |
- unsigned long long y; |
- if (base > 36) { |
- errno = EINVAL; |
- return 0; |
- } |
- while (isspace((c=shgetc(f)))); |
- if (c=='+' || c=='-') { |
- neg = -(c=='-'); |
- c = shgetc(f); |
- } |
- if ((base == 0 || base == 16) && c=='0') { |
- c = shgetc(f); |
- if ((c|32)=='x') { |
- c = shgetc(f); |
- if (val[c]>=16) { |
- shunget(f); |
- if (pok) shunget(f); |
- else shlim(f, 0); |
- return 0; |
- } |
- base = 16; |
- } else if (base == 0) { |
- base = 8; |
- } |
- } else { |
- if (base == 0) base = 10; |
- if (val[c] >= base) { |
- shunget(f); |
- shlim(f, 0); |
- errno = EINVAL; |
- return 0; |
- } |
- } |
- if (base == 10) { |
- for (x=0; c-'0'<10U && x<=UINT_MAX/10-1; c=shgetc(f)) |
- x = x*10 + (c-'0'); |
- for (y=x; c-'0'<10U && y<=ULLONG_MAX/10 && 10*y<=ULLONG_MAX-(c-'0'); c=shgetc(f)) |
- y = y*10 + (c-'0'); |
- if (c-'0'>=10U) goto done; |
- } else if (!(base & base-1)) { |
- int bs = "\0\1\2\4\7\3\6\5"[(0x17*base)>>5&7]; |
- for (x=0; val[c]<base && x<=UINT_MAX/32; c=shgetc(f)) |
- x = x<<bs | val[c]; |
- for (y=x; val[c]<base && y<=ULLONG_MAX>>bs; c=shgetc(f)) |
- y = y<<bs | val[c]; |
- } else { |
- for (x=0; val[c]<base && x<=UINT_MAX/36-1; c=shgetc(f)) |
- x = x*base + val[c]; |
- for (y=x; val[c]<base && y<=ULLONG_MAX/base && base*y<=ULLONG_MAX-val[c]; c=shgetc(f)) |
- y = y*base + val[c]; |
- } |
- if (val[c]<base) { |
- for (; val[c]<base; c=shgetc(f)); |
- errno = ERANGE; |
- y = lim; |
- if (lim&1) neg = 0; |
- } |
+unsigned long long __intscan(FILE* f, |
+ unsigned base, |
+ int pok, |
+ unsigned long long lim) { |
+ const unsigned char* val = table + 1; |
+ int c, neg = 0; |
+ unsigned x; |
+ unsigned long long y; |
+ if (base > 36) { |
+ errno = EINVAL; |
+ return 0; |
+ } |
+ while (isspace((c = shgetc(f)))) |
+ ; |
+ if (c == '+' || c == '-') { |
+ neg = -(c == '-'); |
+ c = shgetc(f); |
+ } |
+ if ((base == 0 || base == 16) && c == '0') { |
+ c = shgetc(f); |
+ if ((c | 32) == 'x') { |
+ c = shgetc(f); |
+ if (val[c] >= 16) { |
+ shunget(f); |
+ if (pok) |
+ shunget(f); |
+ else |
+ shlim(f, 0); |
+ return 0; |
+ } |
+ base = 16; |
+ } else if (base == 0) { |
+ base = 8; |
+ } |
+ } else { |
+ if (base == 0) |
+ base = 10; |
+ if (val[c] >= base) { |
+ shunget(f); |
+ shlim(f, 0); |
+ errno = EINVAL; |
+ return 0; |
+ } |
+ } |
+ if (base == 10) { |
+ for (x = 0; c - '0' < 10U && x <= UINT_MAX / 10 - 1; c = shgetc(f)) |
+ x = x * 10 + (c - '0'); |
+ for (y = x; c - '0' < 10U && y <= ULLONG_MAX / 10 && |
+ 10 * y <= ULLONG_MAX - (c - '0'); |
+ c = shgetc(f)) |
+ y = y * 10 + (c - '0'); |
+ if (c - '0' >= 10U) |
+ goto done; |
+ } else if (!(base & base - 1)) { |
+ int bs = "\0\1\2\4\7\3\6\5"[(0x17 * base) >> 5 & 7]; |
+ for (x = 0; val[c] < base && x <= UINT_MAX / 32; c = shgetc(f)) |
+ x = x << bs | val[c]; |
+ for (y = x; val[c] < base && y <= ULLONG_MAX >> bs; c = shgetc(f)) |
+ y = y << bs | val[c]; |
+ } else { |
+ for (x = 0; val[c] < base && x <= UINT_MAX / 36 - 1; c = shgetc(f)) |
+ x = x * base + val[c]; |
+ for (y = x; val[c] < base && y <= ULLONG_MAX / base && |
+ base * y <= ULLONG_MAX - val[c]; |
+ c = shgetc(f)) |
+ y = y * base + val[c]; |
+ } |
+ if (val[c] < base) { |
+ for (; val[c] < base; c = shgetc(f)) |
+ ; |
+ errno = ERANGE; |
+ y = lim; |
+ if (lim & 1) |
+ neg = 0; |
+ } |
done: |
- shunget(f); |
- if (y>=lim) { |
- if (!(lim&1) && !neg) { |
- errno = ERANGE; |
- return lim-1; |
- } else if (y>lim) { |
- errno = ERANGE; |
- return lim; |
- } |
- } |
- return (y^neg)-neg; |
+ shunget(f); |
+ if (y >= lim) { |
+ if (!(lim & 1) && !neg) { |
+ errno = ERANGE; |
+ return lim - 1; |
+ } else if (y > lim) { |
+ errno = ERANGE; |
+ return lim; |
+ } |
+ } |
+ return (y ^ neg) - neg; |
} |