| #include "os.h" | 
 | #include <mp.h> | 
 | #include "dat.h" | 
 |  | 
 | static struct { | 
 | 	int	inited; | 
 |  | 
 | 	uchar	t64[256]; | 
 | 	uchar	t32[256]; | 
 | 	uchar	t16[256]; | 
 | 	uchar	t10[256]; | 
 | } tab; | 
 |  | 
 | enum { | 
 | 	INVAL=	255 | 
 | }; | 
 |  | 
 | static char set64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | 
 | static char set32[] = "23456789abcdefghijkmnpqrstuvwxyz"; | 
 | static char set16[] = "0123456789ABCDEF0123456789abcdef"; | 
 | static char set10[] = "0123456789"; | 
 |  | 
 | static void | 
 | init(void) | 
 | { | 
 | 	char *p; | 
 |  | 
 | 	memset(tab.t64, INVAL, sizeof(tab.t64)); | 
 | 	memset(tab.t32, INVAL, sizeof(tab.t32)); | 
 | 	memset(tab.t16, INVAL, sizeof(tab.t16)); | 
 | 	memset(tab.t10, INVAL, sizeof(tab.t10)); | 
 |  | 
 | 	for(p = set64; *p; p++) | 
 | 		tab.t64[(uchar)*p] = p-set64; | 
 | 	for(p = set32; *p; p++) | 
 | 		tab.t32[(uchar)*p] = p-set32; | 
 | 	for(p = set16; *p; p++) | 
 | 		tab.t16[(uchar)*p] = (p-set16)%16; | 
 | 	for(p = set10; *p; p++) | 
 | 		tab.t10[(uchar)*p] = (p-set10); | 
 |  | 
 | 	tab.inited = 1; | 
 | } | 
 |  | 
 | static char* | 
 | from16(char *a, mpint *b) | 
 | { | 
 | 	char *p, *next; | 
 | 	int i; | 
 | 	mpdigit x; | 
 |  | 
 | 	b->top = 0; | 
 | 	for(p = a; *p; p++) | 
 | 		if(tab.t16[*(uchar*)p] == INVAL) | 
 | 			break; | 
 | 	mpbits(b, (p-a)*4); | 
 | 	b->top = 0; | 
 | 	next = p; | 
 | 	while(p > a){ | 
 | 		x = 0; | 
 | 		for(i = 0; i < Dbits; i += 4){ | 
 | 			if(p <= a) | 
 | 				break; | 
 | 			x |= tab.t16[*(uchar*)--p]<<i; | 
 | 		} | 
 | 		b->p[b->top++] = x; | 
 | 	} | 
 | 	return next; | 
 | } | 
 |  | 
 | static ulong mppow10[] = { | 
 | 	1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 | 
 | }; | 
 |  | 
 | static char* | 
 | from10(char *a, mpint *b) | 
 | { | 
 | 	ulong x, y; | 
 | 	mpint *pow, *r; | 
 | 	int i; | 
 |  | 
 | 	pow = mpnew(0); | 
 | 	r = mpnew(0); | 
 |  | 
 | 	b->top = 0; | 
 | 	for(;;){ | 
 | 		/* do a billion at a time in native arithmetic */ | 
 | 		x = 0; | 
 | 		for(i = 0; i < 9; i++){ | 
 | 			y = tab.t10[*(uchar*)a]; | 
 | 			if(y == INVAL) | 
 | 				break; | 
 | 			a++; | 
 | 			x *= 10; | 
 | 			x += y; | 
 | 		} | 
 | 		if(i == 0) | 
 | 			break; | 
 |  | 
 | 		/* accumulate into mpint */ | 
 | 		uitomp(mppow10[i], pow); | 
 | 		uitomp(x, r); | 
 | 		mpmul(b, pow, b); | 
 | 		mpadd(b, r, b); | 
 | 		if(i != 9) | 
 | 			break; | 
 | 	} | 
 | 	mpfree(pow); | 
 | 	mpfree(r); | 
 | 	return a; | 
 | } | 
 |  | 
 | static char* | 
 | from64(char *a, mpint *b) | 
 | { | 
 | 	char *buf = a; | 
 | 	uchar *p; | 
 | 	int n, m; | 
 |  | 
 | 	for(; tab.t64[*(uchar*)a] != INVAL; a++) | 
 | 		; | 
 | 	n = a-buf; | 
 | 	mpbits(b, n*6); | 
 | 	p = malloc(n); | 
 | 	if(p == nil) | 
 | 		return a; | 
 | 	m = dec64(p, n, buf, n); | 
 | 	betomp(p, m, b); | 
 | 	free(p); | 
 | 	return a; | 
 | } | 
 |  | 
 | static char* | 
 | from32(char *a, mpint *b) | 
 | { | 
 | 	char *buf = a; | 
 | 	uchar *p; | 
 | 	int n, m; | 
 |  | 
 | 	for(; tab.t64[*(uchar*)a] != INVAL; a++) | 
 | 		; | 
 | 	n = a-buf; | 
 | 	mpbits(b, n*5); | 
 | 	p = malloc(n); | 
 | 	if(p == nil) | 
 | 		return a; | 
 | 	m = dec32(p, n, buf, n); | 
 | 	betomp(p, m, b); | 
 | 	free(p); | 
 | 	return a; | 
 | } | 
 |  | 
 | mpint* | 
 | strtomp(char *a, char **pp, int base, mpint *b) | 
 | { | 
 | 	int sign; | 
 | 	char *e; | 
 |  | 
 | 	if(b == nil) | 
 | 		b = mpnew(0); | 
 |  | 
 | 	if(tab.inited == 0) | 
 | 		init(); | 
 |  | 
 | 	while(*a==' ' || *a=='\t') | 
 | 		a++; | 
 |  | 
 | 	sign = 1; | 
 | 	for(;; a++){ | 
 | 		switch(*a){ | 
 | 		case '-': | 
 | 			sign *= -1; | 
 | 			continue; | 
 | 		} | 
 | 		break; | 
 | 	} | 
 |  | 
 | 	switch(base){ | 
 | 	case 10: | 
 | 		e = from10(a, b); | 
 | 		break; | 
 | 	default: | 
 | 	case 16: | 
 | 		e = from16(a, b); | 
 | 		break; | 
 | 	case 32: | 
 | 		e = from32(a, b); | 
 | 		break; | 
 | 	case 64: | 
 | 		e = from64(a, b); | 
 | 		break; | 
 | 	} | 
 |  | 
 | 	/* if no characters parsed, there wasn't a number to convert */ | 
 | 	if(e == a) | 
 | 		return nil; | 
 |  | 
 | 	mpnorm(b); | 
 | 	b->sign = sign; | 
 | 	if(pp != nil) | 
 | 		*pp = e; | 
 |  | 
 | 	return b; | 
 | } |