1570af302Sopenharmony_ci#include <limits.h> 2570af302Sopenharmony_ci#include <errno.h> 3570af302Sopenharmony_ci#include <ctype.h> 4570af302Sopenharmony_ci#include "shgetc.h" 5570af302Sopenharmony_ci 6570af302Sopenharmony_ci/* Lookup table for digit values. -1==255>=36 -> invalid */ 7570af302Sopenharmony_cistatic const unsigned char table[] = { -1, 8570af302Sopenharmony_ci-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 9570af302Sopenharmony_ci-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 10570af302Sopenharmony_ci-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 11570af302Sopenharmony_ci 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1, 12570af302Sopenharmony_ci-1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, 13570af302Sopenharmony_ci25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1, 14570af302Sopenharmony_ci-1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, 15570af302Sopenharmony_ci25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1, 16570af302Sopenharmony_ci-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 17570af302Sopenharmony_ci-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 18570af302Sopenharmony_ci-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 19570af302Sopenharmony_ci-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 20570af302Sopenharmony_ci-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 21570af302Sopenharmony_ci-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 22570af302Sopenharmony_ci-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 23570af302Sopenharmony_ci-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 24570af302Sopenharmony_ci}; 25570af302Sopenharmony_ci 26570af302Sopenharmony_ciunsigned long long __intscan(FILE *f, unsigned base, int pok, unsigned long long lim) 27570af302Sopenharmony_ci{ 28570af302Sopenharmony_ci const unsigned char *val = table+1; 29570af302Sopenharmony_ci int c, neg=0; 30570af302Sopenharmony_ci unsigned x; 31570af302Sopenharmony_ci unsigned long long y; 32570af302Sopenharmony_ci if (base > 36 || base == 1) { 33570af302Sopenharmony_ci errno = EINVAL; 34570af302Sopenharmony_ci return 0; 35570af302Sopenharmony_ci } 36570af302Sopenharmony_ci while (isspace((c=shgetc(f)))); 37570af302Sopenharmony_ci if (c=='+' || c=='-') { 38570af302Sopenharmony_ci neg = -(c=='-'); 39570af302Sopenharmony_ci c = shgetc(f); 40570af302Sopenharmony_ci } 41570af302Sopenharmony_ci if ((base == 0 || base == 16) && c=='0') { 42570af302Sopenharmony_ci c = shgetc(f); 43570af302Sopenharmony_ci if ((c|32)=='x') { 44570af302Sopenharmony_ci c = shgetc(f); 45570af302Sopenharmony_ci if (val[c]>=16) { 46570af302Sopenharmony_ci shunget(f); 47570af302Sopenharmony_ci if (pok) shunget(f); 48570af302Sopenharmony_ci else shlim(f, 0); 49570af302Sopenharmony_ci return 0; 50570af302Sopenharmony_ci } 51570af302Sopenharmony_ci base = 16; 52570af302Sopenharmony_ci } else if (base == 0) { 53570af302Sopenharmony_ci base = 8; 54570af302Sopenharmony_ci } 55570af302Sopenharmony_ci } else { 56570af302Sopenharmony_ci if (base == 0) base = 10; 57570af302Sopenharmony_ci if (val[c] >= base) { 58570af302Sopenharmony_ci shunget(f); 59570af302Sopenharmony_ci shlim(f, 0); 60570af302Sopenharmony_ci errno = EINVAL; 61570af302Sopenharmony_ci return 0; 62570af302Sopenharmony_ci } 63570af302Sopenharmony_ci } 64570af302Sopenharmony_ci if (base == 10) { 65570af302Sopenharmony_ci for (x=0; c-'0'<10U && x<=UINT_MAX/10-1; c=shgetc(f)) 66570af302Sopenharmony_ci x = x*10 + (c-'0'); 67570af302Sopenharmony_ci for (y=x; c-'0'<10U && y<=ULLONG_MAX/10 && 10*y<=ULLONG_MAX-(c-'0'); c=shgetc(f)) 68570af302Sopenharmony_ci y = y*10 + (c-'0'); 69570af302Sopenharmony_ci if (c-'0'>=10U) goto done; 70570af302Sopenharmony_ci } else if (!(base & base-1)) { 71570af302Sopenharmony_ci int bs = "\0\1\2\4\7\3\6\5"[(0x17*base)>>5&7]; 72570af302Sopenharmony_ci for (x=0; val[c]<base && x<=UINT_MAX/32; c=shgetc(f)) 73570af302Sopenharmony_ci x = x<<bs | val[c]; 74570af302Sopenharmony_ci for (y=x; val[c]<base && y<=ULLONG_MAX>>bs; c=shgetc(f)) 75570af302Sopenharmony_ci y = y<<bs | val[c]; 76570af302Sopenharmony_ci } else { 77570af302Sopenharmony_ci for (x=0; val[c]<base && x<=UINT_MAX/36-1; c=shgetc(f)) 78570af302Sopenharmony_ci x = x*base + val[c]; 79570af302Sopenharmony_ci for (y=x; val[c]<base && y<=ULLONG_MAX/base && base*y<=ULLONG_MAX-val[c]; c=shgetc(f)) 80570af302Sopenharmony_ci y = y*base + val[c]; 81570af302Sopenharmony_ci } 82570af302Sopenharmony_ci if (val[c]<base) { 83570af302Sopenharmony_ci for (; val[c]<base; c=shgetc(f)); 84570af302Sopenharmony_ci errno = ERANGE; 85570af302Sopenharmony_ci y = lim; 86570af302Sopenharmony_ci if (lim&1) neg = 0; 87570af302Sopenharmony_ci } 88570af302Sopenharmony_cidone: 89570af302Sopenharmony_ci shunget(f); 90570af302Sopenharmony_ci if (y>=lim) { 91570af302Sopenharmony_ci if (!(lim&1) && !neg) { 92570af302Sopenharmony_ci errno = ERANGE; 93570af302Sopenharmony_ci return lim-1; 94570af302Sopenharmony_ci } else if (y>lim) { 95570af302Sopenharmony_ci errno = ERANGE; 96570af302Sopenharmony_ci return lim; 97570af302Sopenharmony_ci } 98570af302Sopenharmony_ci } 99570af302Sopenharmony_ci return (y^neg)-neg; 100570af302Sopenharmony_ci} 101