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