1*8ccd4a63SDavid du Colombier #include "os.h"
2*8ccd4a63SDavid du Colombier #include <mp.h>
3*8ccd4a63SDavid du Colombier #include <libsec.h>
4*8ccd4a63SDavid du Colombier #include "dat.h"
5*8ccd4a63SDavid du Colombier
6*8ccd4a63SDavid du Colombier static int
to64(mpint * b,char * buf,int len)7*8ccd4a63SDavid du Colombier to64(mpint *b, char *buf, int len)
8*8ccd4a63SDavid du Colombier {
9*8ccd4a63SDavid du Colombier uchar *p;
10*8ccd4a63SDavid du Colombier int n, rv;
11*8ccd4a63SDavid du Colombier
12*8ccd4a63SDavid du Colombier p = nil;
13*8ccd4a63SDavid du Colombier n = mptobe(b, nil, 0, &p);
14*8ccd4a63SDavid du Colombier if(n < 0)
15*8ccd4a63SDavid du Colombier return -1;
16*8ccd4a63SDavid du Colombier rv = enc64(buf, len, p, n);
17*8ccd4a63SDavid du Colombier free(p);
18*8ccd4a63SDavid du Colombier return rv;
19*8ccd4a63SDavid du Colombier }
20*8ccd4a63SDavid du Colombier
21*8ccd4a63SDavid du Colombier static int
to32(mpint * b,char * buf,int len)22*8ccd4a63SDavid du Colombier to32(mpint *b, char *buf, int len)
23*8ccd4a63SDavid du Colombier {
24*8ccd4a63SDavid du Colombier uchar *p;
25*8ccd4a63SDavid du Colombier int n, rv;
26*8ccd4a63SDavid du Colombier
27*8ccd4a63SDavid du Colombier // leave room for a multiple of 5 buffer size
28*8ccd4a63SDavid du Colombier n = b->top*Dbytes + 5;
29*8ccd4a63SDavid du Colombier p = malloc(n);
30*8ccd4a63SDavid du Colombier if(p == nil)
31*8ccd4a63SDavid du Colombier return -1;
32*8ccd4a63SDavid du Colombier n = mptobe(b, p, n, nil);
33*8ccd4a63SDavid du Colombier if(n < 0)
34*8ccd4a63SDavid du Colombier return -1;
35*8ccd4a63SDavid du Colombier
36*8ccd4a63SDavid du Colombier // round up buffer size, enc32 only accepts a multiple of 5
37*8ccd4a63SDavid du Colombier if(n%5)
38*8ccd4a63SDavid du Colombier n += 5 - (n%5);
39*8ccd4a63SDavid du Colombier rv = enc32(buf, len, p, n);
40*8ccd4a63SDavid du Colombier free(p);
41*8ccd4a63SDavid du Colombier return rv;
42*8ccd4a63SDavid du Colombier }
43*8ccd4a63SDavid du Colombier
44*8ccd4a63SDavid du Colombier static char set16[] = "0123456789ABCDEF";
45*8ccd4a63SDavid du Colombier
46*8ccd4a63SDavid du Colombier static int
to16(mpint * b,char * buf,int len)47*8ccd4a63SDavid du Colombier to16(mpint *b, char *buf, int len)
48*8ccd4a63SDavid du Colombier {
49*8ccd4a63SDavid du Colombier mpdigit *p, x;
50*8ccd4a63SDavid du Colombier int i, j;
51*8ccd4a63SDavid du Colombier char *out, *eout;
52*8ccd4a63SDavid du Colombier
53*8ccd4a63SDavid du Colombier if(len < 1)
54*8ccd4a63SDavid du Colombier return -1;
55*8ccd4a63SDavid du Colombier
56*8ccd4a63SDavid du Colombier out = buf;
57*8ccd4a63SDavid du Colombier eout = buf+len;
58*8ccd4a63SDavid du Colombier for(p = &b->p[b->top-1]; p >= b->p; p--){
59*8ccd4a63SDavid du Colombier x = *p;
60*8ccd4a63SDavid du Colombier for(i = Dbits-4; i >= 0; i -= 4){
61*8ccd4a63SDavid du Colombier j = 0xf & (x>>i);
62*8ccd4a63SDavid du Colombier if(j != 0 || out != buf){
63*8ccd4a63SDavid du Colombier if(out >= eout)
64*8ccd4a63SDavid du Colombier return -1;
65*8ccd4a63SDavid du Colombier *out++ = set16[j];
66*8ccd4a63SDavid du Colombier }
67*8ccd4a63SDavid du Colombier }
68*8ccd4a63SDavid du Colombier }
69*8ccd4a63SDavid du Colombier if(out == buf)
70*8ccd4a63SDavid du Colombier *out++ = '0';
71*8ccd4a63SDavid du Colombier if(out >= eout)
72*8ccd4a63SDavid du Colombier return -1;
73*8ccd4a63SDavid du Colombier *out = 0;
74*8ccd4a63SDavid du Colombier return 0;
75*8ccd4a63SDavid du Colombier }
76*8ccd4a63SDavid du Colombier
77*8ccd4a63SDavid du Colombier static char*
modbillion(int rem,ulong r,char * out,char * buf)78*8ccd4a63SDavid du Colombier modbillion(int rem, ulong r, char *out, char *buf)
79*8ccd4a63SDavid du Colombier {
80*8ccd4a63SDavid du Colombier ulong rr;
81*8ccd4a63SDavid du Colombier int i;
82*8ccd4a63SDavid du Colombier
83*8ccd4a63SDavid du Colombier for(i = 0; i < 9; i++){
84*8ccd4a63SDavid du Colombier rr = r%10;
85*8ccd4a63SDavid du Colombier r /= 10;
86*8ccd4a63SDavid du Colombier if(out <= buf)
87*8ccd4a63SDavid du Colombier return nil;
88*8ccd4a63SDavid du Colombier *--out = '0' + rr;
89*8ccd4a63SDavid du Colombier if(rem == 0 && r == 0)
90*8ccd4a63SDavid du Colombier break;
91*8ccd4a63SDavid du Colombier }
92*8ccd4a63SDavid du Colombier return out;
93*8ccd4a63SDavid du Colombier }
94*8ccd4a63SDavid du Colombier
95*8ccd4a63SDavid du Colombier static int
to10(mpint * b,char * buf,int len)96*8ccd4a63SDavid du Colombier to10(mpint *b, char *buf, int len)
97*8ccd4a63SDavid du Colombier {
98*8ccd4a63SDavid du Colombier mpint *d, *r, *billion;
99*8ccd4a63SDavid du Colombier char *out;
100*8ccd4a63SDavid du Colombier
101*8ccd4a63SDavid du Colombier if(len < 1)
102*8ccd4a63SDavid du Colombier return -1;
103*8ccd4a63SDavid du Colombier
104*8ccd4a63SDavid du Colombier d = mpcopy(b);
105*8ccd4a63SDavid du Colombier r = mpnew(0);
106*8ccd4a63SDavid du Colombier billion = uitomp(1000000000, nil);
107*8ccd4a63SDavid du Colombier out = buf+len;
108*8ccd4a63SDavid du Colombier *--out = 0;
109*8ccd4a63SDavid du Colombier do {
110*8ccd4a63SDavid du Colombier mpdiv(d, billion, d, r);
111*8ccd4a63SDavid du Colombier out = modbillion(d->top, r->p[0], out, buf);
112*8ccd4a63SDavid du Colombier if(out == nil)
113*8ccd4a63SDavid du Colombier break;
114*8ccd4a63SDavid du Colombier } while(d->top != 0);
115*8ccd4a63SDavid du Colombier mpfree(d);
116*8ccd4a63SDavid du Colombier mpfree(r);
117*8ccd4a63SDavid du Colombier mpfree(billion);
118*8ccd4a63SDavid du Colombier
119*8ccd4a63SDavid du Colombier if(out == nil)
120*8ccd4a63SDavid du Colombier return -1;
121*8ccd4a63SDavid du Colombier len -= out-buf;
122*8ccd4a63SDavid du Colombier if(out != buf)
123*8ccd4a63SDavid du Colombier memmove(buf, out, len);
124*8ccd4a63SDavid du Colombier return 0;
125*8ccd4a63SDavid du Colombier }
126*8ccd4a63SDavid du Colombier
127*8ccd4a63SDavid du Colombier int
mpfmt(Fmt * fmt)128*8ccd4a63SDavid du Colombier mpfmt(Fmt *fmt)
129*8ccd4a63SDavid du Colombier {
130*8ccd4a63SDavid du Colombier mpint *b;
131*8ccd4a63SDavid du Colombier char *p;
132*8ccd4a63SDavid du Colombier
133*8ccd4a63SDavid du Colombier b = va_arg(fmt->args, mpint*);
134*8ccd4a63SDavid du Colombier if(b == nil)
135*8ccd4a63SDavid du Colombier return fmtstrcpy(fmt, "*");
136*8ccd4a63SDavid du Colombier
137*8ccd4a63SDavid du Colombier p = mptoa(b, fmt->prec, nil, 0);
138*8ccd4a63SDavid du Colombier fmt->flags &= ~FmtPrec;
139*8ccd4a63SDavid du Colombier
140*8ccd4a63SDavid du Colombier if(p == nil)
141*8ccd4a63SDavid du Colombier return fmtstrcpy(fmt, "*");
142*8ccd4a63SDavid du Colombier else{
143*8ccd4a63SDavid du Colombier fmtstrcpy(fmt, p);
144*8ccd4a63SDavid du Colombier free(p);
145*8ccd4a63SDavid du Colombier return 0;
146*8ccd4a63SDavid du Colombier }
147*8ccd4a63SDavid du Colombier }
148*8ccd4a63SDavid du Colombier
149*8ccd4a63SDavid du Colombier char*
mptoa(mpint * b,int base,char * buf,int len)150*8ccd4a63SDavid du Colombier mptoa(mpint *b, int base, char *buf, int len)
151*8ccd4a63SDavid du Colombier {
152*8ccd4a63SDavid du Colombier char *out;
153*8ccd4a63SDavid du Colombier int rv, alloced;
154*8ccd4a63SDavid du Colombier
155*8ccd4a63SDavid du Colombier alloced = 0;
156*8ccd4a63SDavid du Colombier if(buf == nil){
157*8ccd4a63SDavid du Colombier len = ((b->top+1)*Dbits+2)/3 + 1;
158*8ccd4a63SDavid du Colombier buf = malloc(len);
159*8ccd4a63SDavid du Colombier if(buf == nil)
160*8ccd4a63SDavid du Colombier return nil;
161*8ccd4a63SDavid du Colombier alloced = 1;
162*8ccd4a63SDavid du Colombier }
163*8ccd4a63SDavid du Colombier
164*8ccd4a63SDavid du Colombier if(len < 2)
165*8ccd4a63SDavid du Colombier return nil;
166*8ccd4a63SDavid du Colombier
167*8ccd4a63SDavid du Colombier out = buf;
168*8ccd4a63SDavid du Colombier if(b->sign < 0){
169*8ccd4a63SDavid du Colombier *out++ = '-';
170*8ccd4a63SDavid du Colombier len--;
171*8ccd4a63SDavid du Colombier }
172*8ccd4a63SDavid du Colombier switch(base){
173*8ccd4a63SDavid du Colombier case 64:
174*8ccd4a63SDavid du Colombier rv = to64(b, out, len);
175*8ccd4a63SDavid du Colombier break;
176*8ccd4a63SDavid du Colombier case 32:
177*8ccd4a63SDavid du Colombier rv = to32(b, out, len);
178*8ccd4a63SDavid du Colombier break;
179*8ccd4a63SDavid du Colombier default:
180*8ccd4a63SDavid du Colombier case 16:
181*8ccd4a63SDavid du Colombier rv = to16(b, out, len);
182*8ccd4a63SDavid du Colombier break;
183*8ccd4a63SDavid du Colombier case 10:
184*8ccd4a63SDavid du Colombier rv = to10(b, out, len);
185*8ccd4a63SDavid du Colombier break;
186*8ccd4a63SDavid du Colombier }
187*8ccd4a63SDavid du Colombier if(rv < 0){
188*8ccd4a63SDavid du Colombier if(alloced)
189*8ccd4a63SDavid du Colombier free(buf);
190*8ccd4a63SDavid du Colombier return nil;
191*8ccd4a63SDavid du Colombier }
192*8ccd4a63SDavid du Colombier return buf;
193*8ccd4a63SDavid du Colombier }
194