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