1 // ---------------------------------------------------------------------- 2 // Copyright 2005-2014 Rich Felker, et al. 3 // Copyright 2014 The Android Open Source Project. 4 // 5 // Permission is hereby granted, free of charge, to any person obtaining 6 // a copy of this software and associated documentation files (the 7 // "Software"), to deal in the Software without restriction, including 8 // without limitation the rights to use, copy, modify, merge, publish, 9 // distribute, sublicense, and/or sell copies of the Software, and to 10 // permit persons to whom the Software is furnished to do so, subject to 11 // the following conditions: 12 // 13 // The above copyright notice and this permission notice shall be 14 // included in all copies or substantial portions of the Software. 15 // 16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 // ---------------------------------------------------------------------- 24 25 #include <limits.h> 26 #include <errno.h> 27 #include <ctype.h> 28 #include "shgetc.h" 29 30 // ANDROID: Redefine FILE to use our custom stream abstraction. 31 #undef FILE 32 #define FILE struct fake_file_t 33 34 /* Lookup table for digit values. -1==255>=36 -> invalid */ 35 static const unsigned char table[] = { -1, 36 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 37 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 38 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 39 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1, 40 -1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, 41 25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1, 42 -1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, 43 25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1, 44 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 45 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 46 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 47 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 48 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 49 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 50 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 51 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 52 }; 53 54 unsigned long long __intscan(FILE *f, unsigned base, int pok, unsigned long long lim) 55 { 56 const unsigned char *val = table+1; 57 int c, neg=0; 58 unsigned x; 59 unsigned long long y; 60 if (base > 36) { 61 errno = EINVAL; 62 return 0; 63 } 64 while (isspace((c=shgetc(f)))); 65 if (c=='+' || c=='-') { 66 neg = -(c=='-'); 67 c = shgetc(f); 68 } 69 if ((base == 0 || base == 16) && c=='0') { 70 c = shgetc(f); 71 if ((c|32)=='x') { 72 c = shgetc(f); 73 if (val[c]>=16) { 74 shunget(f); 75 if (pok) shunget(f); 76 else shlim(f, 0); 77 return 0; 78 } 79 base = 16; 80 } else if (base == 0) { 81 base = 8; 82 } 83 } else { 84 if (base == 0) base = 10; 85 if (val[c] >= base) { 86 shunget(f); 87 shlim(f, 0); 88 errno = EINVAL; 89 return 0; 90 } 91 } 92 if (base == 10) { 93 for (x=0; c-'0'<10U && x<=UINT_MAX/10-1; c=shgetc(f)) 94 x = x*10 + (c-'0'); 95 for (y=x; c-'0'<10U && y<=ULLONG_MAX/10 && 10*y<=ULLONG_MAX-(c-'0'); c=shgetc(f)) 96 y = y*10 + (c-'0'); 97 if (c-'0'>=10U) goto done; 98 } else if (!(base & base-1)) { 99 int bs = "\0\1\2\4\7\3\6\5"[(0x17*base)>>5&7]; 100 for (x=0; val[c]<base && x<=UINT_MAX/32; c=shgetc(f)) 101 x = x<<bs | val[c]; 102 for (y=x; val[c]<base && y<=ULLONG_MAX>>bs; c=shgetc(f)) 103 y = y<<bs | val[c]; 104 } else { 105 for (x=0; val[c]<base && x<=UINT_MAX/36-1; c=shgetc(f)) 106 x = x*base + val[c]; 107 for (y=x; val[c]<base && y<=ULLONG_MAX/base && base*y<=ULLONG_MAX-val[c]; c=shgetc(f)) 108 y = y*base + val[c]; 109 } 110 if (val[c]<base) { 111 for (; val[c]<base; c=shgetc(f)); 112 errno = ERANGE; 113 y = lim; 114 } 115 done: 116 shunget(f); 117 if (y>=lim) { 118 if (!(lim&1) && !neg) { 119 errno = ERANGE; 120 return lim-1; 121 } else if (y>lim) { 122 errno = ERANGE; 123 return lim; 124 } 125 } 126 return (y^neg)-neg; 127 } 128