17dd7cddfSDavid du Colombier #include "os.h"
27dd7cddfSDavid du Colombier #include <mp.h>
37dd7cddfSDavid du Colombier #include <libsec.h>
47dd7cddfSDavid du Colombier #include "dat.h"
57dd7cddfSDavid du Colombier
67dd7cddfSDavid du Colombier static struct {
77dd7cddfSDavid du Colombier int inited;
87dd7cddfSDavid du Colombier
97dd7cddfSDavid du Colombier uchar t64[256];
107dd7cddfSDavid du Colombier uchar t32[256];
117dd7cddfSDavid du Colombier uchar t16[256];
127dd7cddfSDavid du Colombier uchar t10[256];
137dd7cddfSDavid du Colombier } tab;
147dd7cddfSDavid du Colombier
157dd7cddfSDavid du Colombier enum {
167dd7cddfSDavid du Colombier INVAL= 255
177dd7cddfSDavid du Colombier };
187dd7cddfSDavid du Colombier
197dd7cddfSDavid du Colombier static char set64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
207dd7cddfSDavid du Colombier static char set32[] = "23456789abcdefghijkmnpqrstuvwxyz";
217dd7cddfSDavid du Colombier static char set16[] = "0123456789ABCDEF0123456789abcdef";
227dd7cddfSDavid du Colombier static char set10[] = "0123456789";
237dd7cddfSDavid du Colombier
247dd7cddfSDavid du Colombier static void
init(void)257dd7cddfSDavid du Colombier init(void)
267dd7cddfSDavid du Colombier {
277dd7cddfSDavid du Colombier char *p;
287dd7cddfSDavid du Colombier
297dd7cddfSDavid du Colombier memset(tab.t64, INVAL, sizeof(tab.t64));
307dd7cddfSDavid du Colombier memset(tab.t32, INVAL, sizeof(tab.t32));
317dd7cddfSDavid du Colombier memset(tab.t16, INVAL, sizeof(tab.t16));
327dd7cddfSDavid du Colombier memset(tab.t10, INVAL, sizeof(tab.t10));
337dd7cddfSDavid du Colombier
347dd7cddfSDavid du Colombier for(p = set64; *p; p++)
357dd7cddfSDavid du Colombier tab.t64[*p] = p-set64;
367dd7cddfSDavid du Colombier for(p = set32; *p; p++)
377dd7cddfSDavid du Colombier tab.t32[*p] = p-set32;
387dd7cddfSDavid du Colombier for(p = set16; *p; p++)
397dd7cddfSDavid du Colombier tab.t16[*p] = (p-set16)%16;
407dd7cddfSDavid du Colombier for(p = set10; *p; p++)
417dd7cddfSDavid du Colombier tab.t10[*p] = (p-set10);
427dd7cddfSDavid du Colombier
437dd7cddfSDavid du Colombier tab.inited = 1;
447dd7cddfSDavid du Colombier }
457dd7cddfSDavid du Colombier
467dd7cddfSDavid du Colombier static char*
from16(char * a,mpint * b)477dd7cddfSDavid du Colombier from16(char *a, mpint *b)
487dd7cddfSDavid du Colombier {
497dd7cddfSDavid du Colombier char *p, *next;
507dd7cddfSDavid du Colombier int i;
517dd7cddfSDavid du Colombier mpdigit x;
527dd7cddfSDavid du Colombier
537dd7cddfSDavid du Colombier b->top = 0;
547dd7cddfSDavid du Colombier for(p = a; *p; p++)
55dc5a79c1SDavid du Colombier if(tab.t16[*(uchar*)p] == INVAL)
567dd7cddfSDavid du Colombier break;
5780ee5cbfSDavid du Colombier mpbits(b, (p-a)*4);
5880ee5cbfSDavid du Colombier b->top = 0;
597dd7cddfSDavid du Colombier next = p;
607dd7cddfSDavid du Colombier while(p > a){
617dd7cddfSDavid du Colombier x = 0;
627dd7cddfSDavid du Colombier for(i = 0; i < Dbits; i += 4){
637dd7cddfSDavid du Colombier if(p <= a)
647dd7cddfSDavid du Colombier break;
65dc5a79c1SDavid du Colombier x |= tab.t16[*(uchar*)--p]<<i;
667dd7cddfSDavid du Colombier }
677dd7cddfSDavid du Colombier b->p[b->top++] = x;
687dd7cddfSDavid du Colombier }
697dd7cddfSDavid du Colombier return next;
707dd7cddfSDavid du Colombier }
717dd7cddfSDavid du Colombier
727dd7cddfSDavid du Colombier static ulong mppow10[] = {
737dd7cddfSDavid du Colombier 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000
747dd7cddfSDavid du Colombier };
757dd7cddfSDavid du Colombier
767dd7cddfSDavid du Colombier static char*
from10(char * a,mpint * b)777dd7cddfSDavid du Colombier from10(char *a, mpint *b)
787dd7cddfSDavid du Colombier {
797dd7cddfSDavid du Colombier ulong x, y;
807dd7cddfSDavid du Colombier mpint *pow, *r;
817dd7cddfSDavid du Colombier int i;
827dd7cddfSDavid du Colombier
837dd7cddfSDavid du Colombier pow = mpnew(0);
847dd7cddfSDavid du Colombier r = mpnew(0);
857dd7cddfSDavid du Colombier
867dd7cddfSDavid du Colombier b->top = 0;
877dd7cddfSDavid du Colombier for(;;){
887dd7cddfSDavid du Colombier // do a billion at a time in native arithmetic
897dd7cddfSDavid du Colombier x = 0;
907dd7cddfSDavid du Colombier for(i = 0; i < 9; i++){
91dc5a79c1SDavid du Colombier y = tab.t10[*(uchar*)a];
927dd7cddfSDavid du Colombier if(y == INVAL)
937dd7cddfSDavid du Colombier break;
947dd7cddfSDavid du Colombier a++;
957dd7cddfSDavid du Colombier x *= 10;
967dd7cddfSDavid du Colombier x += y;
977dd7cddfSDavid du Colombier }
987dd7cddfSDavid du Colombier if(i == 0)
997dd7cddfSDavid du Colombier break;
1007dd7cddfSDavid du Colombier
1017dd7cddfSDavid du Colombier // accumulate into mpint
1027dd7cddfSDavid du Colombier uitomp(mppow10[i], pow);
1037dd7cddfSDavid du Colombier uitomp(x, r);
1047dd7cddfSDavid du Colombier mpmul(b, pow, b);
1057dd7cddfSDavid du Colombier mpadd(b, r, b);
1067dd7cddfSDavid du Colombier if(i != 9)
1077dd7cddfSDavid du Colombier break;
1087dd7cddfSDavid du Colombier }
1097dd7cddfSDavid du Colombier mpfree(pow);
1107dd7cddfSDavid du Colombier mpfree(r);
1117dd7cddfSDavid du Colombier return a;
1127dd7cddfSDavid du Colombier }
1137dd7cddfSDavid du Colombier
1147dd7cddfSDavid du Colombier static char*
from64(char * a,mpint * b)1157dd7cddfSDavid du Colombier from64(char *a, mpint *b)
1167dd7cddfSDavid du Colombier {
1177dd7cddfSDavid du Colombier char *buf = a;
1187dd7cddfSDavid du Colombier uchar *p;
1197dd7cddfSDavid du Colombier int n, m;
1207dd7cddfSDavid du Colombier
121dc5a79c1SDavid du Colombier for(; tab.t64[*(uchar*)a] != INVAL; a++)
1227dd7cddfSDavid du Colombier ;
1237dd7cddfSDavid du Colombier n = a-buf;
12480ee5cbfSDavid du Colombier mpbits(b, n*6);
1257dd7cddfSDavid du Colombier p = malloc(n);
1267dd7cddfSDavid du Colombier if(p == nil)
1277dd7cddfSDavid du Colombier return a;
1287dd7cddfSDavid du Colombier m = dec64(p, n, buf, n);
1297dd7cddfSDavid du Colombier betomp(p, m, b);
1307dd7cddfSDavid du Colombier free(p);
1317dd7cddfSDavid du Colombier return a;
1327dd7cddfSDavid du Colombier }
1337dd7cddfSDavid du Colombier
1347dd7cddfSDavid du Colombier static char*
from32(char * a,mpint * b)1357dd7cddfSDavid du Colombier from32(char *a, mpint *b)
1367dd7cddfSDavid du Colombier {
1377dd7cddfSDavid du Colombier char *buf = a;
1387dd7cddfSDavid du Colombier uchar *p;
1397dd7cddfSDavid du Colombier int n, m;
1407dd7cddfSDavid du Colombier
141dc5a79c1SDavid du Colombier for(; tab.t64[*(uchar*)a] != INVAL; a++)
1427dd7cddfSDavid du Colombier ;
1437dd7cddfSDavid du Colombier n = a-buf;
14480ee5cbfSDavid du Colombier mpbits(b, n*5);
1457dd7cddfSDavid du Colombier p = malloc(n);
1467dd7cddfSDavid du Colombier if(p == nil)
147*f7db6155SDavid du Colombier return buf;
1487dd7cddfSDavid du Colombier m = dec32(p, n, buf, n);
149*f7db6155SDavid du Colombier if(m == -1)
150*f7db6155SDavid du Colombier a = buf;
151*f7db6155SDavid du Colombier else
1527dd7cddfSDavid du Colombier betomp(p, m, b);
1537dd7cddfSDavid du Colombier free(p);
1547dd7cddfSDavid du Colombier return a;
1557dd7cddfSDavid du Colombier }
1567dd7cddfSDavid du Colombier
1577dd7cddfSDavid du Colombier mpint*
strtomp(char * a,char ** pp,int base,mpint * b)1587dd7cddfSDavid du Colombier strtomp(char *a, char **pp, int base, mpint *b)
1597dd7cddfSDavid du Colombier {
1607dd7cddfSDavid du Colombier int sign;
1617dd7cddfSDavid du Colombier char *e;
1627dd7cddfSDavid du Colombier
1637dd7cddfSDavid du Colombier if(b == nil)
1647dd7cddfSDavid du Colombier b = mpnew(0);
1657dd7cddfSDavid du Colombier
1667dd7cddfSDavid du Colombier if(tab.inited == 0)
1677dd7cddfSDavid du Colombier init();
1687dd7cddfSDavid du Colombier
16980ee5cbfSDavid du Colombier while(*a==' ' || *a=='\t')
17080ee5cbfSDavid du Colombier a++;
17180ee5cbfSDavid du Colombier
1727dd7cddfSDavid du Colombier sign = 1;
1737dd7cddfSDavid du Colombier for(;; a++){
1747dd7cddfSDavid du Colombier switch(*a){
1757dd7cddfSDavid du Colombier case '-':
1767dd7cddfSDavid du Colombier sign *= -1;
1777dd7cddfSDavid du Colombier continue;
1787dd7cddfSDavid du Colombier }
1797dd7cddfSDavid du Colombier break;
1807dd7cddfSDavid du Colombier }
1817dd7cddfSDavid du Colombier
1827dd7cddfSDavid du Colombier switch(base){
1837dd7cddfSDavid du Colombier case 10:
1847dd7cddfSDavid du Colombier e = from10(a, b);
1857dd7cddfSDavid du Colombier break;
1867dd7cddfSDavid du Colombier default:
1877dd7cddfSDavid du Colombier case 16:
1887dd7cddfSDavid du Colombier e = from16(a, b);
1897dd7cddfSDavid du Colombier break;
1907dd7cddfSDavid du Colombier case 32:
1917dd7cddfSDavid du Colombier e = from32(a, b);
1927dd7cddfSDavid du Colombier break;
1937dd7cddfSDavid du Colombier case 64:
1947dd7cddfSDavid du Colombier e = from64(a, b);
1957dd7cddfSDavid du Colombier break;
1967dd7cddfSDavid du Colombier }
19780ee5cbfSDavid du Colombier
19880ee5cbfSDavid du Colombier // if no characters parsed, there wasn't a number to convert
19980ee5cbfSDavid du Colombier if(e == a)
20080ee5cbfSDavid du Colombier return nil;
20180ee5cbfSDavid du Colombier
2027dd7cddfSDavid du Colombier mpnorm(b);
2037dd7cddfSDavid du Colombier b->sign = sign;
2047dd7cddfSDavid du Colombier if(pp != nil)
2057dd7cddfSDavid du Colombier *pp = e;
2067dd7cddfSDavid du Colombier
2077dd7cddfSDavid du Colombier return b;
2087dd7cddfSDavid du Colombier }
209