xref: /plan9/sys/src/cmd/unix/drawterm/libmp/mpfmt.c (revision 8ccd4a6360d974db7bd7bbd4f37e7018419ea908)
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