[388] | 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 || base == 1) {
|
---|
| 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_MAX-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 | }
|
---|