master
  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 */
  7static 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,
 1325,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,
 1525,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
 26unsigned 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	}
 88done:
 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}