github.com/afumu/libc@v0.0.6/musl/src/internal/intscan.c (about) 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 }