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