xref: /plan9-contrib/sys/src/nboot/bitsy/donprint.c (revision 529c1f209803c78c4f2cda11b13818a57f01c872)
1*529c1f20SDavid du Colombier #include	"u.h"
2*529c1f20SDavid du Colombier #include	"lib.h"
3*529c1f20SDavid du Colombier 
4*529c1f20SDavid du Colombier #define	PTR	sizeof(char*)
5*529c1f20SDavid du Colombier #define	SHORT	sizeof(int)
6*529c1f20SDavid du Colombier #define	INT	sizeof(int)
7*529c1f20SDavid du Colombier #define	LONG	sizeof(long)
8*529c1f20SDavid du Colombier #define	IDIGIT	30
9*529c1f20SDavid du Colombier #define	MAXCON	30
10*529c1f20SDavid du Colombier 
11*529c1f20SDavid du Colombier #define	FLONG	(1<<0)
12*529c1f20SDavid du Colombier #define	FSHORT	(1<<1)
13*529c1f20SDavid du Colombier #define	FUNSIGN	(1<<2)
14*529c1f20SDavid du Colombier 
15*529c1f20SDavid du Colombier typedef struct Op	Op;
16*529c1f20SDavid du Colombier struct Op
17*529c1f20SDavid du Colombier {
18*529c1f20SDavid du Colombier 	char	*p;
19*529c1f20SDavid du Colombier 	char	*ep;
20*529c1f20SDavid du Colombier 	void	*argp;
21*529c1f20SDavid du Colombier 	int	f1;
22*529c1f20SDavid du Colombier 	int	f2;
23*529c1f20SDavid du Colombier 	int	f3;
24*529c1f20SDavid du Colombier };
25*529c1f20SDavid du Colombier 
26*529c1f20SDavid du Colombier static	int	noconv(Op*);
27*529c1f20SDavid du Colombier static	int	cconv(Op*);
28*529c1f20SDavid du Colombier static	int	dconv(Op*);
29*529c1f20SDavid du Colombier static	int	hconv(Op*);
30*529c1f20SDavid du Colombier static	int	lconv(Op*);
31*529c1f20SDavid du Colombier static	int	oconv(Op*);
32*529c1f20SDavid du Colombier static	int	sconv(Op*);
33*529c1f20SDavid du Colombier static	int	uconv(Op*);
34*529c1f20SDavid du Colombier static	int	xconv(Op*);
35*529c1f20SDavid du Colombier static	int	Xconv(Op*);
36*529c1f20SDavid du Colombier static	int	percent(Op*);
37*529c1f20SDavid du Colombier 
38*529c1f20SDavid du Colombier static
39*529c1f20SDavid du Colombier int	(*fmtconv[MAXCON])(Op*) =
40*529c1f20SDavid du Colombier {
41*529c1f20SDavid du Colombier 	noconv,
42*529c1f20SDavid du Colombier 	cconv, dconv, hconv, lconv,
43*529c1f20SDavid du Colombier 	oconv, sconv, uconv, xconv,
44*529c1f20SDavid du Colombier 	Xconv, percent,
45*529c1f20SDavid du Colombier };
46*529c1f20SDavid du Colombier static
47*529c1f20SDavid du Colombier char	fmtindex[128] =
48*529c1f20SDavid du Colombier {
49*529c1f20SDavid du Colombier 	['c'] 1,
50*529c1f20SDavid du Colombier 	['d'] 2,
51*529c1f20SDavid du Colombier 	['h'] 3,
52*529c1f20SDavid du Colombier 	['l'] 4,
53*529c1f20SDavid du Colombier 	['o'] 5,
54*529c1f20SDavid du Colombier 	['s'] 6,
55*529c1f20SDavid du Colombier 	['u'] 7,
56*529c1f20SDavid du Colombier 	['x'] 8,
57*529c1f20SDavid du Colombier 	['X'] 9,
58*529c1f20SDavid du Colombier 	['%'] 10,
59*529c1f20SDavid du Colombier };
60*529c1f20SDavid du Colombier 
61*529c1f20SDavid du Colombier static	int	convcount  = { 11 };
62*529c1f20SDavid du Colombier static	int	ucase;
63*529c1f20SDavid du Colombier 
64*529c1f20SDavid du Colombier static void
PUT(Op * o,int c)65*529c1f20SDavid du Colombier PUT(Op *o, int c)
66*529c1f20SDavid du Colombier {
67*529c1f20SDavid du Colombier 	static int pos;
68*529c1f20SDavid du Colombier 	int opos;
69*529c1f20SDavid du Colombier 
70*529c1f20SDavid du Colombier 	if(c == '\t'){
71*529c1f20SDavid du Colombier 		opos = pos;
72*529c1f20SDavid du Colombier 		pos = (opos+8) & ~7;
73*529c1f20SDavid du Colombier 		while(opos++ < pos && o->p < o->ep)
74*529c1f20SDavid du Colombier 			*o->p++ = ' ';
75*529c1f20SDavid du Colombier 		return;
76*529c1f20SDavid du Colombier 	}
77*529c1f20SDavid du Colombier 	if(o->p < o->ep){
78*529c1f20SDavid du Colombier 		*o->p++ = c;
79*529c1f20SDavid du Colombier 		pos++;
80*529c1f20SDavid du Colombier 	}
81*529c1f20SDavid du Colombier 	if(c == '\n')
82*529c1f20SDavid du Colombier 		pos = 0;
83*529c1f20SDavid du Colombier }
84*529c1f20SDavid du Colombier 
85*529c1f20SDavid du Colombier int
fmtinstall(char c,int (* f)(Op *))86*529c1f20SDavid du Colombier fmtinstall(char c, int (*f)(Op*))
87*529c1f20SDavid du Colombier {
88*529c1f20SDavid du Colombier 
89*529c1f20SDavid du Colombier 	c &= 0177;
90*529c1f20SDavid du Colombier 	if(fmtindex[c] == 0) {
91*529c1f20SDavid du Colombier 		if(convcount >= MAXCON)
92*529c1f20SDavid du Colombier 			return 1;
93*529c1f20SDavid du Colombier 		fmtindex[c] = convcount++;
94*529c1f20SDavid du Colombier 	}
95*529c1f20SDavid du Colombier 	fmtconv[fmtindex[c]] = f;
96*529c1f20SDavid du Colombier 	return 0;
97*529c1f20SDavid du Colombier }
98*529c1f20SDavid du Colombier 
99*529c1f20SDavid du Colombier char*
donprint(char * p,char * ep,char * fmt,void * argp)100*529c1f20SDavid du Colombier donprint(char *p, char *ep, char *fmt, void *argp)
101*529c1f20SDavid du Colombier {
102*529c1f20SDavid du Colombier 	int sf1, c;
103*529c1f20SDavid du Colombier 	Op o;
104*529c1f20SDavid du Colombier 
105*529c1f20SDavid du Colombier 	o.p = p;
106*529c1f20SDavid du Colombier 	o.ep = ep;
107*529c1f20SDavid du Colombier 	o.argp = argp;
108*529c1f20SDavid du Colombier 
109*529c1f20SDavid du Colombier loop:
110*529c1f20SDavid du Colombier 	c = *fmt++;
111*529c1f20SDavid du Colombier 	if(c != '%') {
112*529c1f20SDavid du Colombier 		if(c == 0) {
113*529c1f20SDavid du Colombier 			if(o.p < o.ep)
114*529c1f20SDavid du Colombier 				*o.p = 0;
115*529c1f20SDavid du Colombier 			return o.p;
116*529c1f20SDavid du Colombier 		}
117*529c1f20SDavid du Colombier 		PUT(&o, c);
118*529c1f20SDavid du Colombier 		goto loop;
119*529c1f20SDavid du Colombier 	}
120*529c1f20SDavid du Colombier 	o.f1 = 0;
121*529c1f20SDavid du Colombier 	o.f2 = -1;
122*529c1f20SDavid du Colombier 	o.f3 = 0;
123*529c1f20SDavid du Colombier 	c = *fmt++;
124*529c1f20SDavid du Colombier 	sf1 = 0;
125*529c1f20SDavid du Colombier 	if(c == '-') {
126*529c1f20SDavid du Colombier 		sf1 = 1;
127*529c1f20SDavid du Colombier 		c = *fmt++;
128*529c1f20SDavid du Colombier 	}
129*529c1f20SDavid du Colombier 	while(c >= '0' && c <= '9') {
130*529c1f20SDavid du Colombier 		o.f1 = o.f1*10 + c-'0';
131*529c1f20SDavid du Colombier 		c = *fmt++;
132*529c1f20SDavid du Colombier 	}
133*529c1f20SDavid du Colombier 	if(sf1)
134*529c1f20SDavid du Colombier 		o.f1 = -o.f1;
135*529c1f20SDavid du Colombier 	if(c != '.')
136*529c1f20SDavid du Colombier 		goto l1;
137*529c1f20SDavid du Colombier 	c = *fmt++;
138*529c1f20SDavid du Colombier 	while(c >= '0' && c <= '9') {
139*529c1f20SDavid du Colombier 		if(o.f2 < 0)
140*529c1f20SDavid du Colombier 			o.f2 = 0;
141*529c1f20SDavid du Colombier 		o.f2 = o.f2*10 + c-'0';
142*529c1f20SDavid du Colombier 		c = *fmt++;
143*529c1f20SDavid du Colombier 	}
144*529c1f20SDavid du Colombier l1:
145*529c1f20SDavid du Colombier 	if(c == 0)
146*529c1f20SDavid du Colombier 		fmt--;
147*529c1f20SDavid du Colombier 	c = (*fmtconv[fmtindex[c&0177]])(&o);
148*529c1f20SDavid du Colombier 	if(c < 0) {
149*529c1f20SDavid du Colombier 		o.f3 |= -c;
150*529c1f20SDavid du Colombier 		c = *fmt++;
151*529c1f20SDavid du Colombier 		goto l1;
152*529c1f20SDavid du Colombier 	}
153*529c1f20SDavid du Colombier 	o.argp = (char*)o.argp + c;
154*529c1f20SDavid du Colombier 	goto loop;
155*529c1f20SDavid du Colombier }
156*529c1f20SDavid du Colombier 
157*529c1f20SDavid du Colombier void
strconv(char * o,Op * op,int f1,int f2)158*529c1f20SDavid du Colombier strconv(char *o, Op *op, int f1, int f2)
159*529c1f20SDavid du Colombier {
160*529c1f20SDavid du Colombier 	int n, c;
161*529c1f20SDavid du Colombier 	char *p;
162*529c1f20SDavid du Colombier 
163*529c1f20SDavid du Colombier 	n = strlen(o);
164*529c1f20SDavid du Colombier 	if(f1 >= 0)
165*529c1f20SDavid du Colombier 		while(n < f1) {
166*529c1f20SDavid du Colombier 			PUT(op, ' ');
167*529c1f20SDavid du Colombier 			n++;
168*529c1f20SDavid du Colombier 		}
169*529c1f20SDavid du Colombier 	for(p=o; c = *p++;)
170*529c1f20SDavid du Colombier 		if(f2 != 0) {
171*529c1f20SDavid du Colombier 			PUT(op, c);
172*529c1f20SDavid du Colombier 			f2--;
173*529c1f20SDavid du Colombier 		}
174*529c1f20SDavid du Colombier 	if(f1 < 0) {
175*529c1f20SDavid du Colombier 		f1 = -f1;
176*529c1f20SDavid du Colombier 		while(n < f1) {
177*529c1f20SDavid du Colombier 			PUT(op, ' ');
178*529c1f20SDavid du Colombier 			n++;
179*529c1f20SDavid du Colombier 		}
180*529c1f20SDavid du Colombier 	}
181*529c1f20SDavid du Colombier }
182*529c1f20SDavid du Colombier 
183*529c1f20SDavid du Colombier int
numbconv(Op * op,int base)184*529c1f20SDavid du Colombier numbconv(Op *op, int base)
185*529c1f20SDavid du Colombier {
186*529c1f20SDavid du Colombier 	char b[IDIGIT];
187*529c1f20SDavid du Colombier 	int i, f, n, r;
188*529c1f20SDavid du Colombier 	long v;
189*529c1f20SDavid du Colombier 	short h;
190*529c1f20SDavid du Colombier 
191*529c1f20SDavid du Colombier 	f = 0;
192*529c1f20SDavid du Colombier 	switch(op->f3 & (FLONG|FSHORT|FUNSIGN)) {
193*529c1f20SDavid du Colombier 	case FLONG:
194*529c1f20SDavid du Colombier 		v = *(long*)op->argp;
195*529c1f20SDavid du Colombier 		r = LONG;
196*529c1f20SDavid du Colombier 		break;
197*529c1f20SDavid du Colombier 
198*529c1f20SDavid du Colombier 	case FUNSIGN|FLONG:
199*529c1f20SDavid du Colombier 		v = *(ulong*)op->argp;
200*529c1f20SDavid du Colombier 		r = LONG;
201*529c1f20SDavid du Colombier 		break;
202*529c1f20SDavid du Colombier 
203*529c1f20SDavid du Colombier 	case FSHORT:
204*529c1f20SDavid du Colombier 		h = *(int*)op->argp;
205*529c1f20SDavid du Colombier 		v = h;
206*529c1f20SDavid du Colombier 		r = SHORT;
207*529c1f20SDavid du Colombier 		break;
208*529c1f20SDavid du Colombier 
209*529c1f20SDavid du Colombier 	case FUNSIGN|FSHORT:
210*529c1f20SDavid du Colombier 		h = *(int*)op->argp;
211*529c1f20SDavid du Colombier 		v = (ushort)h;
212*529c1f20SDavid du Colombier 		r = SHORT;
213*529c1f20SDavid du Colombier 		break;
214*529c1f20SDavid du Colombier 
215*529c1f20SDavid du Colombier 	default:
216*529c1f20SDavid du Colombier 		v = *(int*)op->argp;
217*529c1f20SDavid du Colombier 		r = INT;
218*529c1f20SDavid du Colombier 		break;
219*529c1f20SDavid du Colombier 
220*529c1f20SDavid du Colombier 	case FUNSIGN:
221*529c1f20SDavid du Colombier 		v = *(unsigned*)op->argp;
222*529c1f20SDavid du Colombier 		r = INT;
223*529c1f20SDavid du Colombier 		break;
224*529c1f20SDavid du Colombier 	}
225*529c1f20SDavid du Colombier 	if(!(op->f3 & FUNSIGN) && v < 0) {
226*529c1f20SDavid du Colombier 		v = -v;
227*529c1f20SDavid du Colombier 		f = 1;
228*529c1f20SDavid du Colombier 	}
229*529c1f20SDavid du Colombier 	b[IDIGIT-1] = 0;
230*529c1f20SDavid du Colombier 	for(i = IDIGIT-2;; i--) {
231*529c1f20SDavid du Colombier 		n = (ulong)v % base;
232*529c1f20SDavid du Colombier 		n += '0';
233*529c1f20SDavid du Colombier 		if(n > '9'){
234*529c1f20SDavid du Colombier 			n += 'a' - ('9'+1);
235*529c1f20SDavid du Colombier 			if(ucase)
236*529c1f20SDavid du Colombier 				n += 'A'-'a';
237*529c1f20SDavid du Colombier 		}
238*529c1f20SDavid du Colombier 		b[i] = n;
239*529c1f20SDavid du Colombier 		if(i < 2)
240*529c1f20SDavid du Colombier 			break;
241*529c1f20SDavid du Colombier 		v = (ulong)v / base;
242*529c1f20SDavid du Colombier 		if(op->f2 >= 0 && i >= IDIGIT-op->f2)
243*529c1f20SDavid du Colombier 			continue;
244*529c1f20SDavid du Colombier 		if(v <= 0)
245*529c1f20SDavid du Colombier 			break;
246*529c1f20SDavid du Colombier 	}
247*529c1f20SDavid du Colombier 	if(f)
248*529c1f20SDavid du Colombier 		b[--i] = '-';
249*529c1f20SDavid du Colombier 	strconv(b+i, op, op->f1, -1);
250*529c1f20SDavid du Colombier 	return r;
251*529c1f20SDavid du Colombier }
252*529c1f20SDavid du Colombier 
253*529c1f20SDavid du Colombier static	int
noconv(Op * op)254*529c1f20SDavid du Colombier noconv(Op *op)
255*529c1f20SDavid du Colombier {
256*529c1f20SDavid du Colombier 
257*529c1f20SDavid du Colombier 	strconv("***", op, 0, -1);
258*529c1f20SDavid du Colombier 	return 0;
259*529c1f20SDavid du Colombier }
260*529c1f20SDavid du Colombier 
261*529c1f20SDavid du Colombier static	int
cconv(Op * op)262*529c1f20SDavid du Colombier cconv(Op *op)
263*529c1f20SDavid du Colombier {
264*529c1f20SDavid du Colombier 	char b[2];
265*529c1f20SDavid du Colombier 
266*529c1f20SDavid du Colombier 	b[0] = *(int*)op->argp;
267*529c1f20SDavid du Colombier 	b[1] = 0;
268*529c1f20SDavid du Colombier 	strconv(b, op, op->f1, -1);
269*529c1f20SDavid du Colombier 	return INT;
270*529c1f20SDavid du Colombier }
271*529c1f20SDavid du Colombier 
272*529c1f20SDavid du Colombier static	int
dconv(Op * op)273*529c1f20SDavid du Colombier dconv(Op *op)
274*529c1f20SDavid du Colombier {
275*529c1f20SDavid du Colombier 	return numbconv(op, 10);
276*529c1f20SDavid du Colombier }
277*529c1f20SDavid du Colombier 
278*529c1f20SDavid du Colombier static	int
hconv(Op *)279*529c1f20SDavid du Colombier hconv(Op*)
280*529c1f20SDavid du Colombier {
281*529c1f20SDavid du Colombier 	return -FSHORT;
282*529c1f20SDavid du Colombier }
283*529c1f20SDavid du Colombier 
284*529c1f20SDavid du Colombier static	int
lconv(Op *)285*529c1f20SDavid du Colombier lconv(Op*)
286*529c1f20SDavid du Colombier {
287*529c1f20SDavid du Colombier 	return -FLONG;
288*529c1f20SDavid du Colombier }
289*529c1f20SDavid du Colombier 
290*529c1f20SDavid du Colombier static	int
oconv(Op * op)291*529c1f20SDavid du Colombier oconv(Op *op)
292*529c1f20SDavid du Colombier {
293*529c1f20SDavid du Colombier 	return numbconv(op, 8);
294*529c1f20SDavid du Colombier }
295*529c1f20SDavid du Colombier 
296*529c1f20SDavid du Colombier static	int
sconv(Op * op)297*529c1f20SDavid du Colombier sconv(Op *op)
298*529c1f20SDavid du Colombier {
299*529c1f20SDavid du Colombier 	strconv(*(char**)op->argp, op, op->f1, op->f2);
300*529c1f20SDavid du Colombier 	return PTR;
301*529c1f20SDavid du Colombier }
302*529c1f20SDavid du Colombier 
303*529c1f20SDavid du Colombier static	int
uconv(Op *)304*529c1f20SDavid du Colombier uconv(Op*)
305*529c1f20SDavid du Colombier {
306*529c1f20SDavid du Colombier 	return -FUNSIGN;
307*529c1f20SDavid du Colombier }
308*529c1f20SDavid du Colombier 
309*529c1f20SDavid du Colombier static	int
xconv(Op * op)310*529c1f20SDavid du Colombier xconv(Op *op)
311*529c1f20SDavid du Colombier {
312*529c1f20SDavid du Colombier 	return numbconv(op, 16);
313*529c1f20SDavid du Colombier }
314*529c1f20SDavid du Colombier 
315*529c1f20SDavid du Colombier static	int
Xconv(Op * op)316*529c1f20SDavid du Colombier Xconv(Op *op)
317*529c1f20SDavid du Colombier {
318*529c1f20SDavid du Colombier 	int r;
319*529c1f20SDavid du Colombier 
320*529c1f20SDavid du Colombier 	ucase = 1;
321*529c1f20SDavid du Colombier 	r = numbconv(op, 16);
322*529c1f20SDavid du Colombier 	ucase = 0;
323*529c1f20SDavid du Colombier 	return r;
324*529c1f20SDavid du Colombier }
325*529c1f20SDavid du Colombier 
326*529c1f20SDavid du Colombier static	int
percent(Op * op)327*529c1f20SDavid du Colombier percent(Op *op)
328*529c1f20SDavid du Colombier {
329*529c1f20SDavid du Colombier 
330*529c1f20SDavid du Colombier 	PUT(op, '%');
331*529c1f20SDavid du Colombier 	return 0;
332*529c1f20SDavid du Colombier }
333