xref: /plan9-contrib/sys/src/cmd/unix/drawterm/libc/dofmt.c (revision 8ccd4a6360d974db7bd7bbd4f37e7018419ea908)
1*8ccd4a63SDavid du Colombier #include <u.h>
2*8ccd4a63SDavid du Colombier #include <libc.h>
3*8ccd4a63SDavid du Colombier #include "fmtdef.h"
4*8ccd4a63SDavid du Colombier 
5*8ccd4a63SDavid du Colombier /* format the output into f->to and return the number of characters fmted  */
6*8ccd4a63SDavid du Colombier int
7*8ccd4a63SDavid du Colombier dofmt(Fmt *f, char *fmt)
8*8ccd4a63SDavid du Colombier {
9*8ccd4a63SDavid du Colombier 	Rune rune, *rt, *rs;
10*8ccd4a63SDavid du Colombier 	int r;
11*8ccd4a63SDavid du Colombier 	char *t, *s;
12*8ccd4a63SDavid du Colombier 	int n, nfmt;
13*8ccd4a63SDavid du Colombier 
14*8ccd4a63SDavid du Colombier 	nfmt = f->nfmt;
15*8ccd4a63SDavid du Colombier 	for(;;){
16*8ccd4a63SDavid du Colombier 		if(f->runes){
17*8ccd4a63SDavid du Colombier 			rt = f->to;
18*8ccd4a63SDavid du Colombier 			rs = f->stop;
19*8ccd4a63SDavid du Colombier 			while((r = *(uchar*)fmt) && r != '%'){
20*8ccd4a63SDavid du Colombier 				if(r < Runeself)
21*8ccd4a63SDavid du Colombier 					fmt++;
22*8ccd4a63SDavid du Colombier 				else{
23*8ccd4a63SDavid du Colombier 					fmt += chartorune(&rune, fmt);
24*8ccd4a63SDavid du Colombier 					r = rune;
25*8ccd4a63SDavid du Colombier 				}
26*8ccd4a63SDavid du Colombier 				FMTRCHAR(f, rt, rs, r);
27*8ccd4a63SDavid du Colombier 			}
28*8ccd4a63SDavid du Colombier 			fmt++;
29*8ccd4a63SDavid du Colombier 			f->nfmt += rt - (Rune *)f->to;
30*8ccd4a63SDavid du Colombier 			f->to = rt;
31*8ccd4a63SDavid du Colombier 			if(!r)
32*8ccd4a63SDavid du Colombier 				return f->nfmt - nfmt;
33*8ccd4a63SDavid du Colombier 			f->stop = rs;
34*8ccd4a63SDavid du Colombier 		}else{
35*8ccd4a63SDavid du Colombier 			t = f->to;
36*8ccd4a63SDavid du Colombier 			s = f->stop;
37*8ccd4a63SDavid du Colombier 			while((r = *(uchar*)fmt) && r != '%'){
38*8ccd4a63SDavid du Colombier 				if(r < Runeself){
39*8ccd4a63SDavid du Colombier 					FMTCHAR(f, t, s, r);
40*8ccd4a63SDavid du Colombier 					fmt++;
41*8ccd4a63SDavid du Colombier 				}else{
42*8ccd4a63SDavid du Colombier 					n = chartorune(&rune, fmt);
43*8ccd4a63SDavid du Colombier 					if(t + n > s){
44*8ccd4a63SDavid du Colombier 						t = _fmtflush(f, t, n);
45*8ccd4a63SDavid du Colombier 						if(t != nil)
46*8ccd4a63SDavid du Colombier 							s = f->stop;
47*8ccd4a63SDavid du Colombier 						else
48*8ccd4a63SDavid du Colombier 							return -1;
49*8ccd4a63SDavid du Colombier 					}
50*8ccd4a63SDavid du Colombier 					while(n--)
51*8ccd4a63SDavid du Colombier 						*t++ = *fmt++;
52*8ccd4a63SDavid du Colombier 				}
53*8ccd4a63SDavid du Colombier 			}
54*8ccd4a63SDavid du Colombier 			fmt++;
55*8ccd4a63SDavid du Colombier 			f->nfmt += t - (char *)f->to;
56*8ccd4a63SDavid du Colombier 			f->to = t;
57*8ccd4a63SDavid du Colombier 			if(!r)
58*8ccd4a63SDavid du Colombier 				return f->nfmt - nfmt;
59*8ccd4a63SDavid du Colombier 			f->stop = s;
60*8ccd4a63SDavid du Colombier 		}
61*8ccd4a63SDavid du Colombier 
62*8ccd4a63SDavid du Colombier 		fmt = _fmtdispatch(f, fmt, 0);
63*8ccd4a63SDavid du Colombier 		if(fmt == nil)
64*8ccd4a63SDavid du Colombier 			return -1;
65*8ccd4a63SDavid du Colombier 	}
66*8ccd4a63SDavid du Colombier 	return 0;	/* not reached */
67*8ccd4a63SDavid du Colombier }
68*8ccd4a63SDavid du Colombier 
69*8ccd4a63SDavid du Colombier void *
70*8ccd4a63SDavid du Colombier _fmtflush(Fmt *f, void *t, int len)
71*8ccd4a63SDavid du Colombier {
72*8ccd4a63SDavid du Colombier 	if(f->runes)
73*8ccd4a63SDavid du Colombier 		f->nfmt += (Rune*)t - (Rune*)f->to;
74*8ccd4a63SDavid du Colombier 	else
75*8ccd4a63SDavid du Colombier 		f->nfmt += (char*)t - (char *)f->to;
76*8ccd4a63SDavid du Colombier 	f->to = t;
77*8ccd4a63SDavid du Colombier 	if(f->flush == 0 || (*f->flush)(f) == 0 || (char*)f->to + len > (char*)f->stop){
78*8ccd4a63SDavid du Colombier 		f->stop = f->to;
79*8ccd4a63SDavid du Colombier 		return nil;
80*8ccd4a63SDavid du Colombier 	}
81*8ccd4a63SDavid du Colombier 	return f->to;
82*8ccd4a63SDavid du Colombier }
83*8ccd4a63SDavid du Colombier 
84*8ccd4a63SDavid du Colombier /*
85*8ccd4a63SDavid du Colombier  * put a formatted block of memory sz bytes long of n runes into the output buffer,
86*8ccd4a63SDavid du Colombier  * left/right justified in a field of at least f->width charactes
87*8ccd4a63SDavid du Colombier  */
88*8ccd4a63SDavid du Colombier int
89*8ccd4a63SDavid du Colombier _fmtpad(Fmt *f, int n)
90*8ccd4a63SDavid du Colombier {
91*8ccd4a63SDavid du Colombier 	char *t, *s;
92*8ccd4a63SDavid du Colombier 	int i;
93*8ccd4a63SDavid du Colombier 
94*8ccd4a63SDavid du Colombier 	t = f->to;
95*8ccd4a63SDavid du Colombier 	s = f->stop;
96*8ccd4a63SDavid du Colombier 	for(i = 0; i < n; i++)
97*8ccd4a63SDavid du Colombier 		FMTCHAR(f, t, s, ' ');
98*8ccd4a63SDavid du Colombier 	f->nfmt += t - (char *)f->to;
99*8ccd4a63SDavid du Colombier 	f->to = t;
100*8ccd4a63SDavid du Colombier 	return 0;
101*8ccd4a63SDavid du Colombier }
102*8ccd4a63SDavid du Colombier 
103*8ccd4a63SDavid du Colombier int
104*8ccd4a63SDavid du Colombier _rfmtpad(Fmt *f, int n)
105*8ccd4a63SDavid du Colombier {
106*8ccd4a63SDavid du Colombier 	Rune *t, *s;
107*8ccd4a63SDavid du Colombier 	int i;
108*8ccd4a63SDavid du Colombier 
109*8ccd4a63SDavid du Colombier 	t = f->to;
110*8ccd4a63SDavid du Colombier 	s = f->stop;
111*8ccd4a63SDavid du Colombier 	for(i = 0; i < n; i++)
112*8ccd4a63SDavid du Colombier 		FMTRCHAR(f, t, s, ' ');
113*8ccd4a63SDavid du Colombier 	f->nfmt += t - (Rune *)f->to;
114*8ccd4a63SDavid du Colombier 	f->to = t;
115*8ccd4a63SDavid du Colombier 	return 0;
116*8ccd4a63SDavid du Colombier }
117*8ccd4a63SDavid du Colombier 
118*8ccd4a63SDavid du Colombier int
119*8ccd4a63SDavid du Colombier _fmtcpy(Fmt *f, void *vm, int n, int sz)
120*8ccd4a63SDavid du Colombier {
121*8ccd4a63SDavid du Colombier 	Rune *rt, *rs, r;
122*8ccd4a63SDavid du Colombier 	char *t, *s, *m, *me;
123*8ccd4a63SDavid du Colombier 	ulong fl;
124*8ccd4a63SDavid du Colombier 	int nc, w;
125*8ccd4a63SDavid du Colombier 
126*8ccd4a63SDavid du Colombier 	m = vm;
127*8ccd4a63SDavid du Colombier 	me = m + sz;
128*8ccd4a63SDavid du Colombier 	w = f->width;
129*8ccd4a63SDavid du Colombier 	fl = f->flags;
130*8ccd4a63SDavid du Colombier 	if((fl & FmtPrec) && n > f->prec)
131*8ccd4a63SDavid du Colombier 		n = f->prec;
132*8ccd4a63SDavid du Colombier 	if(f->runes){
133*8ccd4a63SDavid du Colombier 		if(!(fl & FmtLeft) && _rfmtpad(f, w - n) < 0)
134*8ccd4a63SDavid du Colombier 			return -1;
135*8ccd4a63SDavid du Colombier 		rt = f->to;
136*8ccd4a63SDavid du Colombier 		rs = f->stop;
137*8ccd4a63SDavid du Colombier 		for(nc = n; nc > 0; nc--){
138*8ccd4a63SDavid du Colombier 			r = *(uchar*)m;
139*8ccd4a63SDavid du Colombier 			if(r < Runeself)
140*8ccd4a63SDavid du Colombier 				m++;
141*8ccd4a63SDavid du Colombier 			else if((me - m) >= UTFmax || fullrune(m, me-m))
142*8ccd4a63SDavid du Colombier 				m += chartorune(&r, m);
143*8ccd4a63SDavid du Colombier 			else
144*8ccd4a63SDavid du Colombier 				break;
145*8ccd4a63SDavid du Colombier 			FMTRCHAR(f, rt, rs, r);
146*8ccd4a63SDavid du Colombier 		}
147*8ccd4a63SDavid du Colombier 		f->nfmt += rt - (Rune *)f->to;
148*8ccd4a63SDavid du Colombier 		f->to = rt;
149*8ccd4a63SDavid du Colombier 		if(m < me)
150*8ccd4a63SDavid du Colombier 			return -1;
151*8ccd4a63SDavid du Colombier 		if(fl & FmtLeft && _rfmtpad(f, w - n) < 0)
152*8ccd4a63SDavid du Colombier 			return -1;
153*8ccd4a63SDavid du Colombier 	}else{
154*8ccd4a63SDavid du Colombier 		if(!(fl & FmtLeft) && _fmtpad(f, w - n) < 0)
155*8ccd4a63SDavid du Colombier 			return -1;
156*8ccd4a63SDavid du Colombier 		t = f->to;
157*8ccd4a63SDavid du Colombier 		s = f->stop;
158*8ccd4a63SDavid du Colombier 		for(nc = n; nc > 0; nc--){
159*8ccd4a63SDavid du Colombier 			r = *(uchar*)m;
160*8ccd4a63SDavid du Colombier 			if(r < Runeself)
161*8ccd4a63SDavid du Colombier 				m++;
162*8ccd4a63SDavid du Colombier 			else if((me - m) >= UTFmax || fullrune(m, me-m))
163*8ccd4a63SDavid du Colombier 				m += chartorune(&r, m);
164*8ccd4a63SDavid du Colombier 			else
165*8ccd4a63SDavid du Colombier 				break;
166*8ccd4a63SDavid du Colombier 			FMTRUNE(f, t, s, r);
167*8ccd4a63SDavid du Colombier 		}
168*8ccd4a63SDavid du Colombier 		f->nfmt += t - (char *)f->to;
169*8ccd4a63SDavid du Colombier 		f->to = t;
170*8ccd4a63SDavid du Colombier 		if(fl & FmtLeft && _fmtpad(f, w - n) < 0)
171*8ccd4a63SDavid du Colombier 			return -1;
172*8ccd4a63SDavid du Colombier 	}
173*8ccd4a63SDavid du Colombier 	return 0;
174*8ccd4a63SDavid du Colombier }
175*8ccd4a63SDavid du Colombier 
176*8ccd4a63SDavid du Colombier int
177*8ccd4a63SDavid du Colombier _fmtrcpy(Fmt *f, void *vm, int n)
178*8ccd4a63SDavid du Colombier {
179*8ccd4a63SDavid du Colombier 	Rune r, *m, *me, *rt, *rs;
180*8ccd4a63SDavid du Colombier 	char *t, *s;
181*8ccd4a63SDavid du Colombier 	ulong fl;
182*8ccd4a63SDavid du Colombier 	int w;
183*8ccd4a63SDavid du Colombier 
184*8ccd4a63SDavid du Colombier 	m = vm;
185*8ccd4a63SDavid du Colombier 	w = f->width;
186*8ccd4a63SDavid du Colombier 	fl = f->flags;
187*8ccd4a63SDavid du Colombier 	if((fl & FmtPrec) && n > f->prec)
188*8ccd4a63SDavid du Colombier 		n = f->prec;
189*8ccd4a63SDavid du Colombier 	if(f->runes){
190*8ccd4a63SDavid du Colombier 		if(!(fl & FmtLeft) && _rfmtpad(f, w - n) < 0)
191*8ccd4a63SDavid du Colombier 			return -1;
192*8ccd4a63SDavid du Colombier 		rt = f->to;
193*8ccd4a63SDavid du Colombier 		rs = f->stop;
194*8ccd4a63SDavid du Colombier 		for(me = m + n; m < me; m++)
195*8ccd4a63SDavid du Colombier 			FMTRCHAR(f, rt, rs, *m);
196*8ccd4a63SDavid du Colombier 		f->nfmt += rt - (Rune *)f->to;
197*8ccd4a63SDavid du Colombier 		f->to = rt;
198*8ccd4a63SDavid du Colombier 		if(fl & FmtLeft && _rfmtpad(f, w - n) < 0)
199*8ccd4a63SDavid du Colombier 			return -1;
200*8ccd4a63SDavid du Colombier 	}else{
201*8ccd4a63SDavid du Colombier 		if(!(fl & FmtLeft) && _fmtpad(f, w - n) < 0)
202*8ccd4a63SDavid du Colombier 			return -1;
203*8ccd4a63SDavid du Colombier 		t = f->to;
204*8ccd4a63SDavid du Colombier 		s = f->stop;
205*8ccd4a63SDavid du Colombier 		for(me = m + n; m < me; m++){
206*8ccd4a63SDavid du Colombier 			r = *m;
207*8ccd4a63SDavid du Colombier 			FMTRUNE(f, t, s, r);
208*8ccd4a63SDavid du Colombier 		}
209*8ccd4a63SDavid du Colombier 		f->nfmt += t - (char *)f->to;
210*8ccd4a63SDavid du Colombier 		f->to = t;
211*8ccd4a63SDavid du Colombier 		if(fl & FmtLeft && _fmtpad(f, w - n) < 0)
212*8ccd4a63SDavid du Colombier 			return -1;
213*8ccd4a63SDavid du Colombier 	}
214*8ccd4a63SDavid du Colombier 	return 0;
215*8ccd4a63SDavid du Colombier }
216*8ccd4a63SDavid du Colombier 
217*8ccd4a63SDavid du Colombier /* fmt out one character */
218*8ccd4a63SDavid du Colombier int
219*8ccd4a63SDavid du Colombier _charfmt(Fmt *f)
220*8ccd4a63SDavid du Colombier {
221*8ccd4a63SDavid du Colombier 	char x[1];
222*8ccd4a63SDavid du Colombier 
223*8ccd4a63SDavid du Colombier 	x[0] = va_arg(f->args, int);
224*8ccd4a63SDavid du Colombier 	f->prec = 1;
225*8ccd4a63SDavid du Colombier 	return _fmtcpy(f, x, 1, 1);
226*8ccd4a63SDavid du Colombier }
227*8ccd4a63SDavid du Colombier 
228*8ccd4a63SDavid du Colombier /* fmt out one rune */
229*8ccd4a63SDavid du Colombier int
230*8ccd4a63SDavid du Colombier _runefmt(Fmt *f)
231*8ccd4a63SDavid du Colombier {
232*8ccd4a63SDavid du Colombier 	Rune x[1];
233*8ccd4a63SDavid du Colombier 
234*8ccd4a63SDavid du Colombier 	x[0] = va_arg(f->args, int);
235*8ccd4a63SDavid du Colombier 	return _fmtrcpy(f, x, 1);
236*8ccd4a63SDavid du Colombier }
237*8ccd4a63SDavid du Colombier 
238*8ccd4a63SDavid du Colombier /* public helper routine: fmt out a null terminated string already in hand */
239*8ccd4a63SDavid du Colombier int
240*8ccd4a63SDavid du Colombier fmtstrcpy(Fmt *f, char *s)
241*8ccd4a63SDavid du Colombier {
242*8ccd4a63SDavid du Colombier 	int p, i;
243*8ccd4a63SDavid du Colombier 	if(!s)
244*8ccd4a63SDavid du Colombier 		return _fmtcpy(f, "<nil>", 5, 5);
245*8ccd4a63SDavid du Colombier 	/* if precision is specified, make sure we don't wander off the end */
246*8ccd4a63SDavid du Colombier 	if(f->flags & FmtPrec){
247*8ccd4a63SDavid du Colombier 		p = f->prec;
248*8ccd4a63SDavid du Colombier 		for(i = 0; i < p; i++)
249*8ccd4a63SDavid du Colombier 			if(s[i] == 0)
250*8ccd4a63SDavid du Colombier 				break;
251*8ccd4a63SDavid du Colombier 		return _fmtcpy(f, s, utfnlen(s, i), i);	/* BUG?: won't print a partial rune at end */
252*8ccd4a63SDavid du Colombier 	}
253*8ccd4a63SDavid du Colombier 
254*8ccd4a63SDavid du Colombier 	return _fmtcpy(f, s, utflen(s), strlen(s));
255*8ccd4a63SDavid du Colombier }
256*8ccd4a63SDavid du Colombier 
257*8ccd4a63SDavid du Colombier /* fmt out a null terminated utf string */
258*8ccd4a63SDavid du Colombier int
259*8ccd4a63SDavid du Colombier _strfmt(Fmt *f)
260*8ccd4a63SDavid du Colombier {
261*8ccd4a63SDavid du Colombier 	char *s;
262*8ccd4a63SDavid du Colombier 
263*8ccd4a63SDavid du Colombier 	s = va_arg(f->args, char *);
264*8ccd4a63SDavid du Colombier 	return fmtstrcpy(f, s);
265*8ccd4a63SDavid du Colombier }
266*8ccd4a63SDavid du Colombier 
267*8ccd4a63SDavid du Colombier /* public helper routine: fmt out a null terminated rune string already in hand */
268*8ccd4a63SDavid du Colombier int
269*8ccd4a63SDavid du Colombier fmtrunestrcpy(Fmt *f, Rune *s)
270*8ccd4a63SDavid du Colombier {
271*8ccd4a63SDavid du Colombier 	Rune *e;
272*8ccd4a63SDavid du Colombier 	int n, p;
273*8ccd4a63SDavid du Colombier 
274*8ccd4a63SDavid du Colombier 	if(!s)
275*8ccd4a63SDavid du Colombier 		return _fmtcpy(f, "<nil>", 5, 5);
276*8ccd4a63SDavid du Colombier 	/* if precision is specified, make sure we don't wander off the end */
277*8ccd4a63SDavid du Colombier 	if(f->flags & FmtPrec){
278*8ccd4a63SDavid du Colombier 		p = f->prec;
279*8ccd4a63SDavid du Colombier 		for(n = 0; n < p; n++)
280*8ccd4a63SDavid du Colombier 			if(s[n] == 0)
281*8ccd4a63SDavid du Colombier 				break;
282*8ccd4a63SDavid du Colombier 	}else{
283*8ccd4a63SDavid du Colombier 		for(e = s; *e; e++)
284*8ccd4a63SDavid du Colombier 			;
285*8ccd4a63SDavid du Colombier 		n = e - s;
286*8ccd4a63SDavid du Colombier 	}
287*8ccd4a63SDavid du Colombier 	return _fmtrcpy(f, s, n);
288*8ccd4a63SDavid du Colombier }
289*8ccd4a63SDavid du Colombier 
290*8ccd4a63SDavid du Colombier /* fmt out a null terminated rune string */
291*8ccd4a63SDavid du Colombier int
292*8ccd4a63SDavid du Colombier _runesfmt(Fmt *f)
293*8ccd4a63SDavid du Colombier {
294*8ccd4a63SDavid du Colombier 	Rune *s;
295*8ccd4a63SDavid du Colombier 
296*8ccd4a63SDavid du Colombier 	s = va_arg(f->args, Rune *);
297*8ccd4a63SDavid du Colombier 	return fmtrunestrcpy(f, s);
298*8ccd4a63SDavid du Colombier }
299*8ccd4a63SDavid du Colombier 
300*8ccd4a63SDavid du Colombier /* fmt a % */
301*8ccd4a63SDavid du Colombier int
302*8ccd4a63SDavid du Colombier _percentfmt(Fmt *f)
303*8ccd4a63SDavid du Colombier {
304*8ccd4a63SDavid du Colombier 	Rune x[1];
305*8ccd4a63SDavid du Colombier 
306*8ccd4a63SDavid du Colombier 	x[0] = f->r;
307*8ccd4a63SDavid du Colombier 	f->prec = 1;
308*8ccd4a63SDavid du Colombier 	return _fmtrcpy(f, x, 1);
309*8ccd4a63SDavid du Colombier }
310*8ccd4a63SDavid du Colombier 
311*8ccd4a63SDavid du Colombier /* fmt an integer */
312*8ccd4a63SDavid du Colombier int
313*8ccd4a63SDavid du Colombier _ifmt(Fmt *f)
314*8ccd4a63SDavid du Colombier {
315*8ccd4a63SDavid du Colombier 	char buf[70], *p, *conv;
316*8ccd4a63SDavid du Colombier 	uvlong vu;
317*8ccd4a63SDavid du Colombier 	ulong u;
318*8ccd4a63SDavid du Colombier 	int neg, base, i, n, fl, w, isv;
319*8ccd4a63SDavid du Colombier 
320*8ccd4a63SDavid du Colombier 	neg = 0;
321*8ccd4a63SDavid du Colombier 	fl = f->flags;
322*8ccd4a63SDavid du Colombier 	isv = 0;
323*8ccd4a63SDavid du Colombier 	vu = 0;
324*8ccd4a63SDavid du Colombier 	u = 0;
325*8ccd4a63SDavid du Colombier 	if(f->r == 'p'){
326*8ccd4a63SDavid du Colombier 		u = (ulong)va_arg(f->args, void*);
327*8ccd4a63SDavid du Colombier 		f->r = 'x';
328*8ccd4a63SDavid du Colombier 		fl |= FmtUnsigned;
329*8ccd4a63SDavid du Colombier 	}else if(fl & FmtVLong){
330*8ccd4a63SDavid du Colombier 		isv = 1;
331*8ccd4a63SDavid du Colombier 		if(fl & FmtUnsigned)
332*8ccd4a63SDavid du Colombier 			vu = va_arg(f->args, uvlong);
333*8ccd4a63SDavid du Colombier 		else
334*8ccd4a63SDavid du Colombier 			vu = va_arg(f->args, vlong);
335*8ccd4a63SDavid du Colombier 	}else if(fl & FmtLong){
336*8ccd4a63SDavid du Colombier 		if(fl & FmtUnsigned)
337*8ccd4a63SDavid du Colombier 			u = va_arg(f->args, ulong);
338*8ccd4a63SDavid du Colombier 		else
339*8ccd4a63SDavid du Colombier 			u = va_arg(f->args, long);
340*8ccd4a63SDavid du Colombier 	}else if(fl & FmtByte){
341*8ccd4a63SDavid du Colombier 		if(fl & FmtUnsigned)
342*8ccd4a63SDavid du Colombier 			u = (uchar)va_arg(f->args, int);
343*8ccd4a63SDavid du Colombier 		else
344*8ccd4a63SDavid du Colombier 			u = (char)va_arg(f->args, int);
345*8ccd4a63SDavid du Colombier 	}else if(fl & FmtShort){
346*8ccd4a63SDavid du Colombier 		if(fl & FmtUnsigned)
347*8ccd4a63SDavid du Colombier 			u = (ushort)va_arg(f->args, int);
348*8ccd4a63SDavid du Colombier 		else
349*8ccd4a63SDavid du Colombier 			u = (short)va_arg(f->args, int);
350*8ccd4a63SDavid du Colombier 	}else{
351*8ccd4a63SDavid du Colombier 		if(fl & FmtUnsigned)
352*8ccd4a63SDavid du Colombier 			u = va_arg(f->args, uint);
353*8ccd4a63SDavid du Colombier 		else
354*8ccd4a63SDavid du Colombier 			u = va_arg(f->args, int);
355*8ccd4a63SDavid du Colombier 	}
356*8ccd4a63SDavid du Colombier 	conv = "0123456789abcdef";
357*8ccd4a63SDavid du Colombier 	switch(f->r){
358*8ccd4a63SDavid du Colombier 	case 'd':
359*8ccd4a63SDavid du Colombier 		base = 10;
360*8ccd4a63SDavid du Colombier 		break;
361*8ccd4a63SDavid du Colombier 	case 'x':
362*8ccd4a63SDavid du Colombier 		base = 16;
363*8ccd4a63SDavid du Colombier 		break;
364*8ccd4a63SDavid du Colombier 	case 'X':
365*8ccd4a63SDavid du Colombier 		base = 16;
366*8ccd4a63SDavid du Colombier 		conv = "0123456789ABCDEF";
367*8ccd4a63SDavid du Colombier 		break;
368*8ccd4a63SDavid du Colombier 	case 'b':
369*8ccd4a63SDavid du Colombier 		base = 2;
370*8ccd4a63SDavid du Colombier 		break;
371*8ccd4a63SDavid du Colombier 	case 'o':
372*8ccd4a63SDavid du Colombier 		base = 8;
373*8ccd4a63SDavid du Colombier 		break;
374*8ccd4a63SDavid du Colombier 	default:
375*8ccd4a63SDavid du Colombier 		return -1;
376*8ccd4a63SDavid du Colombier 	}
377*8ccd4a63SDavid du Colombier 	if(!(fl & FmtUnsigned)){
378*8ccd4a63SDavid du Colombier 		if(isv && (vlong)vu < 0){
379*8ccd4a63SDavid du Colombier 			vu = -(vlong)vu;
380*8ccd4a63SDavid du Colombier 			neg = 1;
381*8ccd4a63SDavid du Colombier 		}else if(!isv && (long)u < 0){
382*8ccd4a63SDavid du Colombier 			u = -(long)u;
383*8ccd4a63SDavid du Colombier 			neg = 1;
384*8ccd4a63SDavid du Colombier 		}
385*8ccd4a63SDavid du Colombier 	}
386*8ccd4a63SDavid du Colombier 	p = buf + sizeof buf - 1;
387*8ccd4a63SDavid du Colombier 	n = 0;
388*8ccd4a63SDavid du Colombier 	if(isv){
389*8ccd4a63SDavid du Colombier 		while(vu){
390*8ccd4a63SDavid du Colombier 			i = vu % base;
391*8ccd4a63SDavid du Colombier 			vu /= base;
392*8ccd4a63SDavid du Colombier 			if((fl & FmtComma) && n % 4 == 3){
393*8ccd4a63SDavid du Colombier 				*p-- = ',';
394*8ccd4a63SDavid du Colombier 				n++;
395*8ccd4a63SDavid du Colombier 			}
396*8ccd4a63SDavid du Colombier 			*p-- = conv[i];
397*8ccd4a63SDavid du Colombier 			n++;
398*8ccd4a63SDavid du Colombier 		}
399*8ccd4a63SDavid du Colombier 	}else{
400*8ccd4a63SDavid du Colombier 		while(u){
401*8ccd4a63SDavid du Colombier 			i = u % base;
402*8ccd4a63SDavid du Colombier 			u /= base;
403*8ccd4a63SDavid du Colombier 			if((fl & FmtComma) && n % 4 == 3){
404*8ccd4a63SDavid du Colombier 				*p-- = ',';
405*8ccd4a63SDavid du Colombier 				n++;
406*8ccd4a63SDavid du Colombier 			}
407*8ccd4a63SDavid du Colombier 			*p-- = conv[i];
408*8ccd4a63SDavid du Colombier 			n++;
409*8ccd4a63SDavid du Colombier 		}
410*8ccd4a63SDavid du Colombier 	}
411*8ccd4a63SDavid du Colombier 	if(n == 0){
412*8ccd4a63SDavid du Colombier 		*p-- = '0';
413*8ccd4a63SDavid du Colombier 		n = 1;
414*8ccd4a63SDavid du Colombier 	}
415*8ccd4a63SDavid du Colombier 	for(w = f->prec; n < w && p > buf+3; n++)
416*8ccd4a63SDavid du Colombier 		*p-- = '0';
417*8ccd4a63SDavid du Colombier 	if(neg || (fl & (FmtSign|FmtSpace)))
418*8ccd4a63SDavid du Colombier 		n++;
419*8ccd4a63SDavid du Colombier 	if(fl & FmtSharp){
420*8ccd4a63SDavid du Colombier 		if(base == 16)
421*8ccd4a63SDavid du Colombier 			n += 2;
422*8ccd4a63SDavid du Colombier 		else if(base == 8){
423*8ccd4a63SDavid du Colombier 			if(p[1] == '0')
424*8ccd4a63SDavid du Colombier 				fl &= ~FmtSharp;
425*8ccd4a63SDavid du Colombier 			else
426*8ccd4a63SDavid du Colombier 				n++;
427*8ccd4a63SDavid du Colombier 		}
428*8ccd4a63SDavid du Colombier 	}
429*8ccd4a63SDavid du Colombier 	if((fl & FmtZero) && !(fl & FmtLeft)){
430*8ccd4a63SDavid du Colombier 		for(w = f->width; n < w && p > buf+3; n++)
431*8ccd4a63SDavid du Colombier 			*p-- = '0';
432*8ccd4a63SDavid du Colombier 		f->width = 0;
433*8ccd4a63SDavid du Colombier 	}
434*8ccd4a63SDavid du Colombier 	if(fl & FmtSharp){
435*8ccd4a63SDavid du Colombier 		if(base == 16)
436*8ccd4a63SDavid du Colombier 			*p-- = f->r;
437*8ccd4a63SDavid du Colombier 		if(base == 16 || base == 8)
438*8ccd4a63SDavid du Colombier 			*p-- = '0';
439*8ccd4a63SDavid du Colombier 	}
440*8ccd4a63SDavid du Colombier 	if(neg)
441*8ccd4a63SDavid du Colombier 		*p-- = '-';
442*8ccd4a63SDavid du Colombier 	else if(fl & FmtSign)
443*8ccd4a63SDavid du Colombier 		*p-- = '+';
444*8ccd4a63SDavid du Colombier 	else if(fl & FmtSpace)
445*8ccd4a63SDavid du Colombier 		*p-- = ' ';
446*8ccd4a63SDavid du Colombier 	f->flags &= ~FmtPrec;
447*8ccd4a63SDavid du Colombier 	return _fmtcpy(f, p + 1, n, n);
448*8ccd4a63SDavid du Colombier }
449*8ccd4a63SDavid du Colombier 
450*8ccd4a63SDavid du Colombier int
451*8ccd4a63SDavid du Colombier _countfmt(Fmt *f)
452*8ccd4a63SDavid du Colombier {
453*8ccd4a63SDavid du Colombier 	void *p;
454*8ccd4a63SDavid du Colombier 	ulong fl;
455*8ccd4a63SDavid du Colombier 
456*8ccd4a63SDavid du Colombier 	fl = f->flags;
457*8ccd4a63SDavid du Colombier 	p = va_arg(f->args, void*);
458*8ccd4a63SDavid du Colombier 	if(fl & FmtVLong){
459*8ccd4a63SDavid du Colombier 		*(vlong*)p = f->nfmt;
460*8ccd4a63SDavid du Colombier 	}else if(fl & FmtLong){
461*8ccd4a63SDavid du Colombier 		*(long*)p = f->nfmt;
462*8ccd4a63SDavid du Colombier 	}else if(fl & FmtByte){
463*8ccd4a63SDavid du Colombier 		*(char*)p = f->nfmt;
464*8ccd4a63SDavid du Colombier 	}else if(fl & FmtShort){
465*8ccd4a63SDavid du Colombier 		*(short*)p = f->nfmt;
466*8ccd4a63SDavid du Colombier 	}else{
467*8ccd4a63SDavid du Colombier 		*(int*)p = f->nfmt;
468*8ccd4a63SDavid du Colombier 	}
469*8ccd4a63SDavid du Colombier 	return 0;
470*8ccd4a63SDavid du Colombier }
471*8ccd4a63SDavid du Colombier 
472*8ccd4a63SDavid du Colombier int
473*8ccd4a63SDavid du Colombier _flagfmt(Fmt *f)
474*8ccd4a63SDavid du Colombier {
475*8ccd4a63SDavid du Colombier 	switch(f->r){
476*8ccd4a63SDavid du Colombier 	case ',':
477*8ccd4a63SDavid du Colombier 		f->flags |= FmtComma;
478*8ccd4a63SDavid du Colombier 		break;
479*8ccd4a63SDavid du Colombier 	case '-':
480*8ccd4a63SDavid du Colombier 		f->flags |= FmtLeft;
481*8ccd4a63SDavid du Colombier 		break;
482*8ccd4a63SDavid du Colombier 	case '+':
483*8ccd4a63SDavid du Colombier 		f->flags |= FmtSign;
484*8ccd4a63SDavid du Colombier 		break;
485*8ccd4a63SDavid du Colombier 	case '#':
486*8ccd4a63SDavid du Colombier 		f->flags |= FmtSharp;
487*8ccd4a63SDavid du Colombier 		break;
488*8ccd4a63SDavid du Colombier 	case ' ':
489*8ccd4a63SDavid du Colombier 		f->flags |= FmtSpace;
490*8ccd4a63SDavid du Colombier 		break;
491*8ccd4a63SDavid du Colombier 	case 'u':
492*8ccd4a63SDavid du Colombier 		f->flags |= FmtUnsigned;
493*8ccd4a63SDavid du Colombier 		break;
494*8ccd4a63SDavid du Colombier 	case 'h':
495*8ccd4a63SDavid du Colombier 		if(f->flags & FmtShort)
496*8ccd4a63SDavid du Colombier 			f->flags |= FmtByte;
497*8ccd4a63SDavid du Colombier 		f->flags |= FmtShort;
498*8ccd4a63SDavid du Colombier 		break;
499*8ccd4a63SDavid du Colombier 	case 'l':
500*8ccd4a63SDavid du Colombier 		if(f->flags & FmtLong)
501*8ccd4a63SDavid du Colombier 			f->flags |= FmtVLong;
502*8ccd4a63SDavid du Colombier 		f->flags |= FmtLong;
503*8ccd4a63SDavid du Colombier 		break;
504*8ccd4a63SDavid du Colombier 	}
505*8ccd4a63SDavid du Colombier 	return 1;
506*8ccd4a63SDavid du Colombier }
507*8ccd4a63SDavid du Colombier 
508*8ccd4a63SDavid du Colombier /* default error format */
509*8ccd4a63SDavid du Colombier int
510*8ccd4a63SDavid du Colombier _badfmt(Fmt *f)
511*8ccd4a63SDavid du Colombier {
512*8ccd4a63SDavid du Colombier 	char x[3];
513*8ccd4a63SDavid du Colombier 
514*8ccd4a63SDavid du Colombier 	x[0] = '%';
515*8ccd4a63SDavid du Colombier 	x[1] = f->r;
516*8ccd4a63SDavid du Colombier 	x[2] = '%';
517*8ccd4a63SDavid du Colombier 	f->prec = 3;
518*8ccd4a63SDavid du Colombier 	_fmtcpy(f, x, 3, 3);
519*8ccd4a63SDavid du Colombier 	return 0;
520*8ccd4a63SDavid du Colombier }
521