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