| OLD | NEW |
| 1 #include <limits.h> | 1 #include <limits.h> |
| 2 #include <errno.h> | 2 #include <errno.h> |
| 3 #include <ctype.h> | 3 #include <ctype.h> |
| 4 #include "shgetc.h" | 4 #include "shgetc.h" |
| 5 | 5 |
| 6 /* Lookup table for digit values. -1==255>=36 -> invalid */ | 6 /* Lookup table for digit values. -1==255>=36 -> invalid */ |
| 7 static const unsigned char table[] = { -1, | 7 static const unsigned char table[] = { |
| 8 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, | 8 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
| 9 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, | 9 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
| 10 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, | 10 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, |
| 11 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1, | 11 8, 9, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, |
| 12 -1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, | 12 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, |
| 13 25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1, | 13 -1, -1, -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, |
| 14 -1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, | 14 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
| 15 25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1, | 15 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
| 16 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, | 16 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
| 17 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, | 17 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
| 18 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, | 18 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
| 19 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, | 19 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
| 20 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, | 20 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
| 21 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, | 21 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
| 22 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, | |
| 23 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, | |
| 24 }; | 22 }; |
| 25 | 23 |
| 26 unsigned long long __intscan(FILE *f, unsigned base, int pok, unsigned long long
lim) | 24 unsigned long long __intscan(FILE* f, |
| 27 { | 25 unsigned base, |
| 28 » const unsigned char *val = table+1; | 26 int pok, |
| 29 » int c, neg=0; | 27 unsigned long long lim) { |
| 30 » unsigned x; | 28 const unsigned char* val = table + 1; |
| 31 » unsigned long long y; | 29 int c, neg = 0; |
| 32 » if (base > 36) { | 30 unsigned x; |
| 33 » » errno = EINVAL; | 31 unsigned long long y; |
| 34 » » return 0; | 32 if (base > 36) { |
| 35 » } | 33 errno = EINVAL; |
| 36 » while (isspace((c=shgetc(f)))); | 34 return 0; |
| 37 » if (c=='+' || c=='-') { | 35 } |
| 38 » » neg = -(c=='-'); | 36 while (isspace((c = shgetc(f)))) |
| 39 » » c = shgetc(f); | 37 ; |
| 40 » } | 38 if (c == '+' || c == '-') { |
| 41 » if ((base == 0 || base == 16) && c=='0') { | 39 neg = -(c == '-'); |
| 42 » » c = shgetc(f); | 40 c = shgetc(f); |
| 43 » » if ((c|32)=='x') { | 41 } |
| 44 » » » c = shgetc(f); | 42 if ((base == 0 || base == 16) && c == '0') { |
| 45 » » » if (val[c]>=16) { | 43 c = shgetc(f); |
| 46 » » » » shunget(f); | 44 if ((c | 32) == 'x') { |
| 47 » » » » if (pok) shunget(f); | 45 c = shgetc(f); |
| 48 » » » » else shlim(f, 0); | 46 if (val[c] >= 16) { |
| 49 » » » » return 0; | 47 shunget(f); |
| 50 » » » } | 48 if (pok) |
| 51 » » » base = 16; | 49 shunget(f); |
| 52 » » } else if (base == 0) { | 50 else |
| 53 » » » base = 8; | 51 shlim(f, 0); |
| 54 » » } | 52 return 0; |
| 55 » } else { | 53 } |
| 56 » » if (base == 0) base = 10; | 54 base = 16; |
| 57 » » if (val[c] >= base) { | 55 } else if (base == 0) { |
| 58 » » » shunget(f); | 56 base = 8; |
| 59 » » » shlim(f, 0); | 57 } |
| 60 » » » errno = EINVAL; | 58 } else { |
| 61 » » » return 0; | 59 if (base == 0) |
| 62 » » } | 60 base = 10; |
| 63 » } | 61 if (val[c] >= base) { |
| 64 » if (base == 10) { | 62 shunget(f); |
| 65 » » for (x=0; c-'0'<10U && x<=UINT_MAX/10-1; c=shgetc(f)) | 63 shlim(f, 0); |
| 66 » » » x = x*10 + (c-'0'); | 64 errno = EINVAL; |
| 67 » » for (y=x; c-'0'<10U && y<=ULLONG_MAX/10 && 10*y<=ULLONG_MAX-(c-'
0'); c=shgetc(f)) | 65 return 0; |
| 68 » » » y = y*10 + (c-'0'); | 66 } |
| 69 » » if (c-'0'>=10U) goto done; | 67 } |
| 70 » } else if (!(base & base-1)) { | 68 if (base == 10) { |
| 71 » » int bs = "\0\1\2\4\7\3\6\5"[(0x17*base)>>5&7]; | 69 for (x = 0; c - '0' < 10U && x <= UINT_MAX / 10 - 1; c = shgetc(f)) |
| 72 » » for (x=0; val[c]<base && x<=UINT_MAX/32; c=shgetc(f)) | 70 x = x * 10 + (c - '0'); |
| 73 » » » x = x<<bs | val[c]; | 71 for (y = x; c - '0' < 10U && y <= ULLONG_MAX / 10 && |
| 74 » » for (y=x; val[c]<base && y<=ULLONG_MAX>>bs; c=shgetc(f)) | 72 10 * y <= ULLONG_MAX - (c - '0'); |
| 75 » » » y = y<<bs | val[c]; | 73 c = shgetc(f)) |
| 76 » } else { | 74 y = y * 10 + (c - '0'); |
| 77 » » for (x=0; val[c]<base && x<=UINT_MAX/36-1; c=shgetc(f)) | 75 if (c - '0' >= 10U) |
| 78 » » » x = x*base + val[c]; | 76 goto done; |
| 79 » » for (y=x; val[c]<base && y<=ULLONG_MAX/base && base*y<=ULLONG_MA
X-val[c]; c=shgetc(f)) | 77 } else if (!(base & base - 1)) { |
| 80 » » » y = y*base + val[c]; | 78 int bs = "\0\1\2\4\7\3\6\5"[(0x17 * base) >> 5 & 7]; |
| 81 » } | 79 for (x = 0; val[c] < base && x <= UINT_MAX / 32; c = shgetc(f)) |
| 82 » if (val[c]<base) { | 80 x = x << bs | val[c]; |
| 83 » » for (; val[c]<base; c=shgetc(f)); | 81 for (y = x; val[c] < base && y <= ULLONG_MAX >> bs; c = shgetc(f)) |
| 84 » » errno = ERANGE; | 82 y = y << bs | val[c]; |
| 85 » » y = lim; | 83 } else { |
| 86 » » if (lim&1) neg = 0; | 84 for (x = 0; val[c] < base && x <= UINT_MAX / 36 - 1; c = shgetc(f)) |
| 87 » } | 85 x = x * base + val[c]; |
| 86 for (y = x; val[c] < base && y <= ULLONG_MAX / base && |
| 87 base * y <= ULLONG_MAX - val[c]; |
| 88 c = shgetc(f)) |
| 89 y = y * base + val[c]; |
| 90 } |
| 91 if (val[c] < base) { |
| 92 for (; val[c] < base; c = shgetc(f)) |
| 93 ; |
| 94 errno = ERANGE; |
| 95 y = lim; |
| 96 if (lim & 1) |
| 97 neg = 0; |
| 98 } |
| 88 done: | 99 done: |
| 89 » shunget(f); | 100 shunget(f); |
| 90 » if (y>=lim) { | 101 if (y >= lim) { |
| 91 » » if (!(lim&1) && !neg) { | 102 if (!(lim & 1) && !neg) { |
| 92 » » » errno = ERANGE; | 103 errno = ERANGE; |
| 93 » » » return lim-1; | 104 return lim - 1; |
| 94 » » } else if (y>lim) { | 105 } else if (y > lim) { |
| 95 » » » errno = ERANGE; | 106 errno = ERANGE; |
| 96 » » » return lim; | 107 return lim; |
| 97 » » } | 108 } |
| 98 » } | 109 } |
| 99 » return (y^neg)-neg; | 110 return (y ^ neg) - neg; |
| 100 } | 111 } |
| OLD | NEW |