#include #include #include #include "uwide128.h" #include "shgetc.h" /* Lookup table for digit values. -1==255>=36 -> invalid */ static const unsigned char table[] = { -1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1, -1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, 25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1, -1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, 25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, }; static uwide128 const uwide128_max = { { -1, -1, } }; static uwide128 const uwide128_zero = { { 0, 0, } }; static const uwide128 __uwide128_limit[37] = { comp2(0, 0), comp2(-1, -1), comp2(-1, 9223372036854775807), comp2(6148914691236517205, 6148914691236517205), comp2(-1, 4611686018427387903), comp2(3689348814741910323, 3689348814741910323), comp2(-6148914691236517206, 3074457345618258602), comp2(5270498306774157604, 2635249153387078802), comp2(-1, 2305843009213693951), comp2(-4099276460824344804, 2049638230412172401), comp2(-7378697629483820647, 1844674407370955161), comp2(8384883669867978007, 1676976733973595601), comp2(6148914691236517205, 1537228672809129301), comp2(4256940940086819603, 1418980313362273201), comp2(2635249153387078802, 1317624576693539401), comp2(1229782938247303441, 1229782938247303441), comp2(-1, 1152921504606846975), comp2(1085102592571150095, 1085102592571150095), comp2(-2049638230412172402, 1024819115206086200), comp2(-1941762534074689644, 970881267037344821), comp2(-3689348814741910324, 922337203685477580), comp2(-4392081922311798004, 878416384462359600), comp2(-5030930201920786805, 838488366986797800), comp2(4812194106185100421, 802032351030850070), comp2(-6148914691236517206, 768614336404564650), comp2(-6640827866535438582, 737869762948382064), comp2(-7094901566811366007, 709490156681136600), comp2(-1366425486941448268, 683212743470724133), comp2(-7905747460161236407, 658812288346769700), comp2(-3180473116156819245, 636094623231363848), comp2(-8608480567731124088, 614891469123651720), comp2(-8925843906633654008, 595056260442243600), comp2(-1, 576460752303423487), comp2(8943875914525843207, 558992244657865200), comp2(-8680820740569200761, 542551296285575047), comp2(8432797290838652167, 527049830677415760), comp2(8198552921648689607, 512409557603043100), }; uwide128 __intscan(FILE *f, unsigned base, int pok, uwide128 lim) { const unsigned char *val = table+1; int c, neg=0; unsigned x; uint64_t z; uwide128 y; if (base > 36 || base == 1) { errno = EINVAL; return uwide128_zero; } while (isspace((c=shgetc(f)))); if (c=='+' || c=='-') { neg = -(c=='-'); c = shgetc(f); } if ((base == 0 || base == 2 || base == 16) && c=='0') { c = shgetc(f); if ((c|32)=='x' && base != 2) { c = shgetc(f); if (val[c]>=16) { shunget(f); if (pok) shunget(f); else shlim(f, 0); return uwide128_zero; } base = 16; } else if ((c|32)=='b' && base != 16) { c = shgetc(f); if (val[c]>=2) { shunget(f); if (pok) shunget(f); else shlim(f, 0); return uwide128_zero; } base = 2; } else if (base == 0) { base = 8; } } else { if (base == 0) base = 10; if (val[c] >= base) { shunget(f); shlim(f, 0); errno = EINVAL; return uwide128_zero; } } if (base == 10) { for (x=0; c-'0'<10U && x<=UINT_MAX/10-1; c=shgetc(f)) x = x*10 + (c-'0'); for (z=x; c-'0'<10U && z<=UINT64_MAX/10-1; c=shgetc(f)) z = z*10 + (c-'0'); y=__uwide128_u64(x); if (c-'0'<10U) { uwide128 y10 = __uwide128_mul(y, 10); while (c-'0'<10U && __uwide128_le(y, __uwide128_limit[10]) && __uwide128_le(y10, __uwide128_sub(uwide128_max, (c-'0')))) { y = __uwide128_add(y10, (c-'0')); y10 = __uwide128_mul(y, 10); c=shgetc(f); } } if (c-'0'>=10U) goto done; } else { for (x=0; val[c]