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 |