• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
__intscan(FILE * f,unsigned base,int pok,unsigned long long lim)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 }
101