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