| 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;
|
| }
|
|
|