19a747e4fSDavid du Colombier #include <u.h>
29a747e4fSDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier #include "fmtdef.h"
49a747e4fSDavid du Colombier
59a747e4fSDavid du Colombier /* format the output into f->to and return the number of characters fmted */
69a747e4fSDavid du Colombier int
dofmt(Fmt * f,char * fmt)79a747e4fSDavid du Colombier dofmt(Fmt *f, char *fmt)
89a747e4fSDavid du Colombier {
99a747e4fSDavid du Colombier Rune rune, *rt, *rs;
109a747e4fSDavid du Colombier int r;
119a747e4fSDavid du Colombier char *t, *s;
129a747e4fSDavid du Colombier int n, nfmt;
139a747e4fSDavid du Colombier
149a747e4fSDavid du Colombier nfmt = f->nfmt;
159a747e4fSDavid du Colombier for(;;){
169a747e4fSDavid du Colombier if(f->runes){
179a747e4fSDavid du Colombier rt = f->to;
189a747e4fSDavid du Colombier rs = f->stop;
199a747e4fSDavid du Colombier while((r = *(uchar*)fmt) && r != '%'){
209a747e4fSDavid du Colombier if(r < Runeself)
219a747e4fSDavid du Colombier fmt++;
229a747e4fSDavid du Colombier else{
239a747e4fSDavid du Colombier fmt += chartorune(&rune, fmt);
249a747e4fSDavid du Colombier r = rune;
259a747e4fSDavid du Colombier }
269a747e4fSDavid du Colombier FMTRCHAR(f, rt, rs, r);
279a747e4fSDavid du Colombier }
289a747e4fSDavid du Colombier fmt++;
299a747e4fSDavid du Colombier f->nfmt += rt - (Rune *)f->to;
309a747e4fSDavid du Colombier f->to = rt;
319a747e4fSDavid du Colombier if(!r)
329a747e4fSDavid du Colombier return f->nfmt - nfmt;
339a747e4fSDavid du Colombier f->stop = rs;
349a747e4fSDavid du Colombier }else{
359a747e4fSDavid du Colombier t = f->to;
369a747e4fSDavid du Colombier s = f->stop;
379a747e4fSDavid du Colombier while((r = *(uchar*)fmt) && r != '%'){
389a747e4fSDavid du Colombier if(r < Runeself){
399a747e4fSDavid du Colombier FMTCHAR(f, t, s, r);
409a747e4fSDavid du Colombier fmt++;
419a747e4fSDavid du Colombier }else{
429a747e4fSDavid du Colombier n = chartorune(&rune, fmt);
439a747e4fSDavid du Colombier if(t + n > s){
449a747e4fSDavid du Colombier t = _fmtflush(f, t, n);
459a747e4fSDavid du Colombier if(t != nil)
469a747e4fSDavid du Colombier s = f->stop;
479a747e4fSDavid du Colombier else
489a747e4fSDavid du Colombier return -1;
499a747e4fSDavid du Colombier }
509a747e4fSDavid du Colombier while(n--)
519a747e4fSDavid du Colombier *t++ = *fmt++;
529a747e4fSDavid du Colombier }
539a747e4fSDavid du Colombier }
549a747e4fSDavid du Colombier fmt++;
559a747e4fSDavid du Colombier f->nfmt += t - (char *)f->to;
569a747e4fSDavid du Colombier f->to = t;
579a747e4fSDavid du Colombier if(!r)
589a747e4fSDavid du Colombier return f->nfmt - nfmt;
599a747e4fSDavid du Colombier f->stop = s;
609a747e4fSDavid du Colombier }
619a747e4fSDavid du Colombier
629a747e4fSDavid du Colombier fmt = _fmtdispatch(f, fmt, 0);
639a747e4fSDavid du Colombier if(fmt == nil)
649a747e4fSDavid du Colombier return -1;
659a747e4fSDavid du Colombier }
669a747e4fSDavid du Colombier }
679a747e4fSDavid du Colombier
689a747e4fSDavid du Colombier void *
_fmtflush(Fmt * f,void * t,int len)699a747e4fSDavid du Colombier _fmtflush(Fmt *f, void *t, int len)
709a747e4fSDavid du Colombier {
719a747e4fSDavid du Colombier if(f->runes)
729a747e4fSDavid du Colombier f->nfmt += (Rune*)t - (Rune*)f->to;
739a747e4fSDavid du Colombier else
749a747e4fSDavid du Colombier f->nfmt += (char*)t - (char *)f->to;
759a747e4fSDavid du Colombier f->to = t;
769a747e4fSDavid du Colombier if(f->flush == 0 || (*f->flush)(f) == 0 || (char*)f->to + len > (char*)f->stop){
779a747e4fSDavid du Colombier f->stop = f->to;
789a747e4fSDavid du Colombier return nil;
799a747e4fSDavid du Colombier }
809a747e4fSDavid du Colombier return f->to;
819a747e4fSDavid du Colombier }
829a747e4fSDavid du Colombier
839a747e4fSDavid du Colombier /*
849a747e4fSDavid du Colombier * put a formatted block of memory sz bytes long of n runes into the output buffer,
859a747e4fSDavid du Colombier * left/right justified in a field of at least f->width charactes
869a747e4fSDavid du Colombier */
879a747e4fSDavid du Colombier int
_fmtpad(Fmt * f,int n)889a747e4fSDavid du Colombier _fmtpad(Fmt *f, int n)
899a747e4fSDavid du Colombier {
909a747e4fSDavid du Colombier char *t, *s;
919a747e4fSDavid du Colombier int i;
929a747e4fSDavid du Colombier
939a747e4fSDavid du Colombier t = f->to;
949a747e4fSDavid du Colombier s = f->stop;
959a747e4fSDavid du Colombier for(i = 0; i < n; i++)
969a747e4fSDavid du Colombier FMTCHAR(f, t, s, ' ');
979a747e4fSDavid du Colombier f->nfmt += t - (char *)f->to;
989a747e4fSDavid du Colombier f->to = t;
999a747e4fSDavid du Colombier return 0;
1009a747e4fSDavid du Colombier }
1019a747e4fSDavid du Colombier
1029a747e4fSDavid du Colombier int
_rfmtpad(Fmt * f,int n)1039a747e4fSDavid du Colombier _rfmtpad(Fmt *f, int n)
1049a747e4fSDavid du Colombier {
1059a747e4fSDavid du Colombier Rune *t, *s;
1069a747e4fSDavid du Colombier int i;
1079a747e4fSDavid du Colombier
1089a747e4fSDavid du Colombier t = f->to;
1099a747e4fSDavid du Colombier s = f->stop;
1109a747e4fSDavid du Colombier for(i = 0; i < n; i++)
1119a747e4fSDavid du Colombier FMTRCHAR(f, t, s, ' ');
1129a747e4fSDavid du Colombier f->nfmt += t - (Rune *)f->to;
1139a747e4fSDavid du Colombier f->to = t;
1149a747e4fSDavid du Colombier return 0;
1159a747e4fSDavid du Colombier }
1169a747e4fSDavid du Colombier
1179a747e4fSDavid du Colombier int
_fmtcpy(Fmt * f,void * vm,int n,int sz)1189a747e4fSDavid du Colombier _fmtcpy(Fmt *f, void *vm, int n, int sz)
1199a747e4fSDavid du Colombier {
1209a747e4fSDavid du Colombier Rune *rt, *rs, r;
1219a747e4fSDavid du Colombier char *t, *s, *m, *me;
1229a747e4fSDavid du Colombier ulong fl;
1239a747e4fSDavid du Colombier int nc, w;
1249a747e4fSDavid du Colombier
1259a747e4fSDavid du Colombier m = vm;
1269a747e4fSDavid du Colombier me = m + sz;
1279a747e4fSDavid du Colombier w = f->width;
1289a747e4fSDavid du Colombier fl = f->flags;
1299a747e4fSDavid du Colombier if((fl & FmtPrec) && n > f->prec)
1309a747e4fSDavid du Colombier n = f->prec;
1319a747e4fSDavid du Colombier if(f->runes){
1329a747e4fSDavid du Colombier if(!(fl & FmtLeft) && _rfmtpad(f, w - n) < 0)
1339a747e4fSDavid du Colombier return -1;
1349a747e4fSDavid du Colombier rt = f->to;
1359a747e4fSDavid du Colombier rs = f->stop;
1369a747e4fSDavid du Colombier for(nc = n; nc > 0; nc--){
1379a747e4fSDavid du Colombier r = *(uchar*)m;
1389a747e4fSDavid du Colombier if(r < Runeself)
1399a747e4fSDavid du Colombier m++;
1409a747e4fSDavid du Colombier else if((me - m) >= UTFmax || fullrune(m, me-m))
1419a747e4fSDavid du Colombier m += chartorune(&r, m);
1429a747e4fSDavid du Colombier else
1439a747e4fSDavid du Colombier break;
1449a747e4fSDavid du Colombier FMTRCHAR(f, rt, rs, r);
1459a747e4fSDavid du Colombier }
1469a747e4fSDavid du Colombier f->nfmt += rt - (Rune *)f->to;
1479a747e4fSDavid du Colombier f->to = rt;
1489a747e4fSDavid du Colombier if(fl & FmtLeft && _rfmtpad(f, w - n) < 0)
1499a747e4fSDavid du Colombier return -1;
1509a747e4fSDavid du Colombier }else{
1519a747e4fSDavid du Colombier if(!(fl & FmtLeft) && _fmtpad(f, w - n) < 0)
1529a747e4fSDavid du Colombier return -1;
1539a747e4fSDavid du Colombier t = f->to;
1549a747e4fSDavid du Colombier s = f->stop;
1559a747e4fSDavid du Colombier for(nc = n; nc > 0; nc--){
1569a747e4fSDavid du Colombier r = *(uchar*)m;
1579a747e4fSDavid du Colombier if(r < Runeself)
1589a747e4fSDavid du Colombier m++;
1599a747e4fSDavid du Colombier else if((me - m) >= UTFmax || fullrune(m, me-m))
1609a747e4fSDavid du Colombier m += chartorune(&r, m);
1619a747e4fSDavid du Colombier else
1629a747e4fSDavid du Colombier break;
1639a747e4fSDavid du Colombier FMTRUNE(f, t, s, r);
1649a747e4fSDavid du Colombier }
1659a747e4fSDavid du Colombier f->nfmt += t - (char *)f->to;
1669a747e4fSDavid du Colombier f->to = t;
1679a747e4fSDavid du Colombier if(fl & FmtLeft && _fmtpad(f, w - n) < 0)
1689a747e4fSDavid du Colombier return -1;
1699a747e4fSDavid du Colombier }
1709a747e4fSDavid du Colombier return 0;
1719a747e4fSDavid du Colombier }
1729a747e4fSDavid du Colombier
1739a747e4fSDavid du Colombier int
_fmtrcpy(Fmt * f,void * vm,int n)1749a747e4fSDavid du Colombier _fmtrcpy(Fmt *f, void *vm, int n)
1759a747e4fSDavid du Colombier {
1769a747e4fSDavid du Colombier Rune r, *m, *me, *rt, *rs;
1779a747e4fSDavid du Colombier char *t, *s;
1789a747e4fSDavid du Colombier ulong fl;
1799a747e4fSDavid du Colombier int w;
1809a747e4fSDavid du Colombier
1819a747e4fSDavid du Colombier m = vm;
1829a747e4fSDavid du Colombier w = f->width;
1839a747e4fSDavid du Colombier fl = f->flags;
1849a747e4fSDavid du Colombier if((fl & FmtPrec) && n > f->prec)
1859a747e4fSDavid du Colombier n = f->prec;
1869a747e4fSDavid du Colombier if(f->runes){
1879a747e4fSDavid du Colombier if(!(fl & FmtLeft) && _rfmtpad(f, w - n) < 0)
1889a747e4fSDavid du Colombier return -1;
1899a747e4fSDavid du Colombier rt = f->to;
1909a747e4fSDavid du Colombier rs = f->stop;
1919a747e4fSDavid du Colombier for(me = m + n; m < me; m++)
1929a747e4fSDavid du Colombier FMTRCHAR(f, rt, rs, *m);
1939a747e4fSDavid du Colombier f->nfmt += rt - (Rune *)f->to;
1949a747e4fSDavid du Colombier f->to = rt;
1959a747e4fSDavid du Colombier if(fl & FmtLeft && _rfmtpad(f, w - n) < 0)
1969a747e4fSDavid du Colombier return -1;
1979a747e4fSDavid du Colombier }else{
1989a747e4fSDavid du Colombier if(!(fl & FmtLeft) && _fmtpad(f, w - n) < 0)
1999a747e4fSDavid du Colombier return -1;
2009a747e4fSDavid du Colombier t = f->to;
2019a747e4fSDavid du Colombier s = f->stop;
2029a747e4fSDavid du Colombier for(me = m + n; m < me; m++){
2039a747e4fSDavid du Colombier r = *m;
2049a747e4fSDavid du Colombier FMTRUNE(f, t, s, r);
2059a747e4fSDavid du Colombier }
2069a747e4fSDavid du Colombier f->nfmt += t - (char *)f->to;
2079a747e4fSDavid du Colombier f->to = t;
2089a747e4fSDavid du Colombier if(fl & FmtLeft && _fmtpad(f, w - n) < 0)
2099a747e4fSDavid du Colombier return -1;
2109a747e4fSDavid du Colombier }
2119a747e4fSDavid du Colombier return 0;
2129a747e4fSDavid du Colombier }
2139a747e4fSDavid du Colombier
2149a747e4fSDavid du Colombier /* fmt out one character */
2159a747e4fSDavid du Colombier int
_charfmt(Fmt * f)2169a747e4fSDavid du Colombier _charfmt(Fmt *f)
2179a747e4fSDavid du Colombier {
2189a747e4fSDavid du Colombier char x[1];
2199a747e4fSDavid du Colombier
2209a747e4fSDavid du Colombier x[0] = va_arg(f->args, int);
221d9306527SDavid du Colombier f->prec = 1;
2229a747e4fSDavid du Colombier return _fmtcpy(f, x, 1, 1);
2239a747e4fSDavid du Colombier }
2249a747e4fSDavid du Colombier
2259a747e4fSDavid du Colombier /* fmt out one rune */
2269a747e4fSDavid du Colombier int
_runefmt(Fmt * f)2279a747e4fSDavid du Colombier _runefmt(Fmt *f)
2289a747e4fSDavid du Colombier {
2299a747e4fSDavid du Colombier Rune x[1];
2309a747e4fSDavid du Colombier
2319a747e4fSDavid du Colombier x[0] = va_arg(f->args, int);
2329a747e4fSDavid du Colombier return _fmtrcpy(f, x, 1);
2339a747e4fSDavid du Colombier }
2349a747e4fSDavid du Colombier
2359a747e4fSDavid du Colombier /* public helper routine: fmt out a null terminated string already in hand */
2369a747e4fSDavid du Colombier int
fmtstrcpy(Fmt * f,char * s)2379a747e4fSDavid du Colombier fmtstrcpy(Fmt *f, char *s)
2389a747e4fSDavid du Colombier {
23967031067SDavid du Colombier int i, j;
24067031067SDavid du Colombier Rune r;
24167031067SDavid du Colombier
2429a747e4fSDavid du Colombier if(!s)
2439a747e4fSDavid du Colombier return _fmtcpy(f, "<nil>", 5, 5);
2446a9fc400SDavid du Colombier /* if precision is specified, make sure we don't wander off the end */
2456a9fc400SDavid du Colombier if(f->flags & FmtPrec){
24667031067SDavid du Colombier i = 0;
24767031067SDavid du Colombier for(j=0; j<f->prec && s[i]; j++)
24867031067SDavid du Colombier i += chartorune(&r, s+i);
24967031067SDavid du Colombier return _fmtcpy(f, s, j, i);
2506a9fc400SDavid du Colombier }
2519a747e4fSDavid du Colombier return _fmtcpy(f, s, utflen(s), strlen(s));
2529a747e4fSDavid du Colombier }
2539a747e4fSDavid du Colombier
2549a747e4fSDavid du Colombier /* fmt out a null terminated utf string */
2559a747e4fSDavid du Colombier int
_strfmt(Fmt * f)2569a747e4fSDavid du Colombier _strfmt(Fmt *f)
2579a747e4fSDavid du Colombier {
2589a747e4fSDavid du Colombier char *s;
2599a747e4fSDavid du Colombier
2609a747e4fSDavid du Colombier s = va_arg(f->args, char *);
2619a747e4fSDavid du Colombier return fmtstrcpy(f, s);
2629a747e4fSDavid du Colombier }
2639a747e4fSDavid du Colombier
2649a747e4fSDavid du Colombier /* public helper routine: fmt out a null terminated rune string already in hand */
2659a747e4fSDavid du Colombier int
fmtrunestrcpy(Fmt * f,Rune * s)2669a747e4fSDavid du Colombier fmtrunestrcpy(Fmt *f, Rune *s)
2679a747e4fSDavid du Colombier {
2689a747e4fSDavid du Colombier Rune *e;
2696a9fc400SDavid du Colombier int n, p;
2709a747e4fSDavid du Colombier
2719a747e4fSDavid du Colombier if(!s)
2729a747e4fSDavid du Colombier return _fmtcpy(f, "<nil>", 5, 5);
2736a9fc400SDavid du Colombier /* if precision is specified, make sure we don't wander off the end */
2746a9fc400SDavid du Colombier if(f->flags & FmtPrec){
2756a9fc400SDavid du Colombier p = f->prec;
2766a9fc400SDavid du Colombier for(n = 0; n < p; n++)
2776a9fc400SDavid du Colombier if(s[n] == 0)
2786a9fc400SDavid du Colombier break;
2796a9fc400SDavid du Colombier }else{
2809a747e4fSDavid du Colombier for(e = s; *e; e++)
2819a747e4fSDavid du Colombier ;
2829a747e4fSDavid du Colombier n = e - s;
2836a9fc400SDavid du Colombier }
2849a747e4fSDavid du Colombier return _fmtrcpy(f, s, n);
2859a747e4fSDavid du Colombier }
2869a747e4fSDavid du Colombier
2879a747e4fSDavid du Colombier /* fmt out a null terminated rune string */
2889a747e4fSDavid du Colombier int
_runesfmt(Fmt * f)2899a747e4fSDavid du Colombier _runesfmt(Fmt *f)
2909a747e4fSDavid du Colombier {
2919a747e4fSDavid du Colombier Rune *s;
2929a747e4fSDavid du Colombier
2939a747e4fSDavid du Colombier s = va_arg(f->args, Rune *);
2949a747e4fSDavid du Colombier return fmtrunestrcpy(f, s);
2959a747e4fSDavid du Colombier }
2969a747e4fSDavid du Colombier
2979a747e4fSDavid du Colombier /* fmt a % */
2989a747e4fSDavid du Colombier int
_percentfmt(Fmt * f)2999a747e4fSDavid du Colombier _percentfmt(Fmt *f)
3009a747e4fSDavid du Colombier {
3019a747e4fSDavid du Colombier Rune x[1];
3029a747e4fSDavid du Colombier
3039a747e4fSDavid du Colombier x[0] = f->r;
304d9306527SDavid du Colombier f->prec = 1;
3059a747e4fSDavid du Colombier return _fmtrcpy(f, x, 1);
3069a747e4fSDavid du Colombier }
3079a747e4fSDavid du Colombier
308*ad6ca847SDavid du Colombier enum {
309*ad6ca847SDavid du Colombier /* %,#llb could emit a sign, "0b" and 64 digits with 21 commas */
310*ad6ca847SDavid du Colombier Maxintwidth = 1 + 2 + 64 + 64/3,
311*ad6ca847SDavid du Colombier };
312*ad6ca847SDavid du Colombier
3139a747e4fSDavid du Colombier /* fmt an integer */
3149a747e4fSDavid du Colombier int
_ifmt(Fmt * f)3159a747e4fSDavid du Colombier _ifmt(Fmt *f)
3169a747e4fSDavid du Colombier {
317*ad6ca847SDavid du Colombier char buf[Maxintwidth + 1], *p, *conv;
3189a747e4fSDavid du Colombier uvlong vu;
3199a747e4fSDavid du Colombier ulong u;
3201517f4bcSDavid du Colombier uintptr pu;
3219a747e4fSDavid du Colombier int neg, base, i, n, fl, w, isv;
3229a747e4fSDavid du Colombier
3239a747e4fSDavid du Colombier neg = 0;
3249a747e4fSDavid du Colombier fl = f->flags;
3259a747e4fSDavid du Colombier isv = 0;
3269a747e4fSDavid du Colombier vu = 0;
3279a747e4fSDavid du Colombier u = 0;
3289a747e4fSDavid du Colombier if(f->r == 'p'){
3291517f4bcSDavid du Colombier pu = va_arg(f->args, uintptr);
3301517f4bcSDavid du Colombier if(sizeof(uintptr) == sizeof(uvlong)){
3311517f4bcSDavid du Colombier vu = pu;
3321517f4bcSDavid du Colombier isv = 1;
3331517f4bcSDavid du Colombier }else
3341517f4bcSDavid du Colombier u = pu;
3359a747e4fSDavid du Colombier f->r = 'x';
3369a747e4fSDavid du Colombier fl |= FmtUnsigned;
3379a747e4fSDavid du Colombier }else if(fl & FmtVLong){
3389a747e4fSDavid du Colombier isv = 1;
3399a747e4fSDavid du Colombier if(fl & FmtUnsigned)
3409a747e4fSDavid du Colombier vu = va_arg(f->args, uvlong);
3419a747e4fSDavid du Colombier else
3429a747e4fSDavid du Colombier vu = va_arg(f->args, vlong);
3439a747e4fSDavid du Colombier }else if(fl & FmtLong){
3449a747e4fSDavid du Colombier if(fl & FmtUnsigned)
3459a747e4fSDavid du Colombier u = va_arg(f->args, ulong);
3469a747e4fSDavid du Colombier else
3479a747e4fSDavid du Colombier u = va_arg(f->args, long);
348b7b24591SDavid du Colombier }else if(fl & FmtByte){
349b7b24591SDavid du Colombier if(fl & FmtUnsigned)
350b7b24591SDavid du Colombier u = (uchar)va_arg(f->args, int);
351b7b24591SDavid du Colombier else
352b7b24591SDavid du Colombier u = (char)va_arg(f->args, int);
3539a747e4fSDavid du Colombier }else if(fl & FmtShort){
3549a747e4fSDavid du Colombier if(fl & FmtUnsigned)
355b7b24591SDavid du Colombier u = (ushort)va_arg(f->args, int);
3569a747e4fSDavid du Colombier else
357b7b24591SDavid du Colombier u = (short)va_arg(f->args, int);
3589a747e4fSDavid du Colombier }else{
3599a747e4fSDavid du Colombier if(fl & FmtUnsigned)
3609a747e4fSDavid du Colombier u = va_arg(f->args, uint);
3619a747e4fSDavid du Colombier else
3629a747e4fSDavid du Colombier u = va_arg(f->args, int);
3639a747e4fSDavid du Colombier }
3649a747e4fSDavid du Colombier conv = "0123456789abcdef";
3659a747e4fSDavid du Colombier switch(f->r){
3669a747e4fSDavid du Colombier case 'd':
3679a747e4fSDavid du Colombier base = 10;
3689a747e4fSDavid du Colombier break;
3699a747e4fSDavid du Colombier case 'x':
3709a747e4fSDavid du Colombier base = 16;
3719a747e4fSDavid du Colombier break;
3729a747e4fSDavid du Colombier case 'X':
3739a747e4fSDavid du Colombier base = 16;
3749a747e4fSDavid du Colombier conv = "0123456789ABCDEF";
3759a747e4fSDavid du Colombier break;
3769a747e4fSDavid du Colombier case 'b':
3779a747e4fSDavid du Colombier base = 2;
3789a747e4fSDavid du Colombier break;
3799a747e4fSDavid du Colombier case 'o':
3809a747e4fSDavid du Colombier base = 8;
3819a747e4fSDavid du Colombier break;
3829a747e4fSDavid du Colombier default:
3839a747e4fSDavid du Colombier return -1;
3849a747e4fSDavid du Colombier }
3859a747e4fSDavid du Colombier if(!(fl & FmtUnsigned)){
3869a747e4fSDavid du Colombier if(isv && (vlong)vu < 0){
3879a747e4fSDavid du Colombier vu = -(vlong)vu;
3889a747e4fSDavid du Colombier neg = 1;
3899a747e4fSDavid du Colombier }else if(!isv && (long)u < 0){
3909a747e4fSDavid du Colombier u = -(long)u;
3919a747e4fSDavid du Colombier neg = 1;
3929a747e4fSDavid du Colombier }
3939a747e4fSDavid du Colombier }
3949a747e4fSDavid du Colombier p = buf + sizeof buf - 1;
3959a747e4fSDavid du Colombier n = 0;
3969a747e4fSDavid du Colombier if(isv){
3979a747e4fSDavid du Colombier while(vu){
3989a747e4fSDavid du Colombier i = vu % base;
3999a747e4fSDavid du Colombier vu /= base;
4009a747e4fSDavid du Colombier if((fl & FmtComma) && n % 4 == 3){
4019a747e4fSDavid du Colombier *p-- = ',';
4029a747e4fSDavid du Colombier n++;
4039a747e4fSDavid du Colombier }
4049a747e4fSDavid du Colombier *p-- = conv[i];
4059a747e4fSDavid du Colombier n++;
4069a747e4fSDavid du Colombier }
4079a747e4fSDavid du Colombier }else{
4089a747e4fSDavid du Colombier while(u){
4099a747e4fSDavid du Colombier i = u % base;
4109a747e4fSDavid du Colombier u /= base;
4119a747e4fSDavid du Colombier if((fl & FmtComma) && n % 4 == 3){
4129a747e4fSDavid du Colombier *p-- = ',';
4139a747e4fSDavid du Colombier n++;
4149a747e4fSDavid du Colombier }
4159a747e4fSDavid du Colombier *p-- = conv[i];
4169a747e4fSDavid du Colombier n++;
4179a747e4fSDavid du Colombier }
4189a747e4fSDavid du Colombier }
4199a747e4fSDavid du Colombier if(n == 0){
4209a747e4fSDavid du Colombier *p-- = '0';
4219a747e4fSDavid du Colombier n = 1;
4229a747e4fSDavid du Colombier }
4239a747e4fSDavid du Colombier for(w = f->prec; n < w && p > buf+3; n++)
4249a747e4fSDavid du Colombier *p-- = '0';
4259a747e4fSDavid du Colombier if(neg || (fl & (FmtSign|FmtSpace)))
4269a747e4fSDavid du Colombier n++;
4279a747e4fSDavid du Colombier if(fl & FmtSharp){
4289a747e4fSDavid du Colombier if(base == 16)
4299a747e4fSDavid du Colombier n += 2;
4309a747e4fSDavid du Colombier else if(base == 8){
4319a747e4fSDavid du Colombier if(p[1] == '0')
4329a747e4fSDavid du Colombier fl &= ~FmtSharp;
4339a747e4fSDavid du Colombier else
4349a747e4fSDavid du Colombier n++;
4359a747e4fSDavid du Colombier }
4369a747e4fSDavid du Colombier }
437a0ef1dc2SDavid du Colombier if((fl & FmtZero) && !(fl & (FmtLeft|FmtPrec))){
4389a747e4fSDavid du Colombier for(w = f->width; n < w && p > buf+3; n++)
4399a747e4fSDavid du Colombier *p-- = '0';
4409a747e4fSDavid du Colombier f->width = 0;
4419a747e4fSDavid du Colombier }
4429a747e4fSDavid du Colombier if(fl & FmtSharp){
4439a747e4fSDavid du Colombier if(base == 16)
4449a747e4fSDavid du Colombier *p-- = f->r;
4459a747e4fSDavid du Colombier if(base == 16 || base == 8)
4469a747e4fSDavid du Colombier *p-- = '0';
4479a747e4fSDavid du Colombier }
4489a747e4fSDavid du Colombier if(neg)
4499a747e4fSDavid du Colombier *p-- = '-';
4509a747e4fSDavid du Colombier else if(fl & FmtSign)
4519a747e4fSDavid du Colombier *p-- = '+';
4529a747e4fSDavid du Colombier else if(fl & FmtSpace)
4539a747e4fSDavid du Colombier *p-- = ' ';
4549a747e4fSDavid du Colombier f->flags &= ~FmtPrec;
4559a747e4fSDavid du Colombier return _fmtcpy(f, p + 1, n, n);
4569a747e4fSDavid du Colombier }
4579a747e4fSDavid du Colombier
4589a747e4fSDavid du Colombier int
_countfmt(Fmt * f)4599a747e4fSDavid du Colombier _countfmt(Fmt *f)
4609a747e4fSDavid du Colombier {
4619a747e4fSDavid du Colombier void *p;
4629a747e4fSDavid du Colombier ulong fl;
4639a747e4fSDavid du Colombier
4649a747e4fSDavid du Colombier fl = f->flags;
4659a747e4fSDavid du Colombier p = va_arg(f->args, void*);
4669a747e4fSDavid du Colombier if(fl & FmtVLong){
4679a747e4fSDavid du Colombier *(vlong*)p = f->nfmt;
4689a747e4fSDavid du Colombier }else if(fl & FmtLong){
4699a747e4fSDavid du Colombier *(long*)p = f->nfmt;
4709a747e4fSDavid du Colombier }else if(fl & FmtByte){
4719a747e4fSDavid du Colombier *(char*)p = f->nfmt;
4729a747e4fSDavid du Colombier }else if(fl & FmtShort){
4739a747e4fSDavid du Colombier *(short*)p = f->nfmt;
4749a747e4fSDavid du Colombier }else{
4759a747e4fSDavid du Colombier *(int*)p = f->nfmt;
4769a747e4fSDavid du Colombier }
4779a747e4fSDavid du Colombier return 0;
4789a747e4fSDavid du Colombier }
4799a747e4fSDavid du Colombier
4809a747e4fSDavid du Colombier int
_flagfmt(Fmt * f)4819a747e4fSDavid du Colombier _flagfmt(Fmt *f)
4829a747e4fSDavid du Colombier {
4839a747e4fSDavid du Colombier switch(f->r){
4849a747e4fSDavid du Colombier case ',':
4859a747e4fSDavid du Colombier f->flags |= FmtComma;
4869a747e4fSDavid du Colombier break;
4879a747e4fSDavid du Colombier case '-':
4889a747e4fSDavid du Colombier f->flags |= FmtLeft;
4899a747e4fSDavid du Colombier break;
4909a747e4fSDavid du Colombier case '+':
4919a747e4fSDavid du Colombier f->flags |= FmtSign;
4929a747e4fSDavid du Colombier break;
4939a747e4fSDavid du Colombier case '#':
4949a747e4fSDavid du Colombier f->flags |= FmtSharp;
4959a747e4fSDavid du Colombier break;
4969a747e4fSDavid du Colombier case ' ':
4979a747e4fSDavid du Colombier f->flags |= FmtSpace;
4989a747e4fSDavid du Colombier break;
4999a747e4fSDavid du Colombier case 'u':
5009a747e4fSDavid du Colombier f->flags |= FmtUnsigned;
5019a747e4fSDavid du Colombier break;
5029a747e4fSDavid du Colombier case 'h':
5039a747e4fSDavid du Colombier if(f->flags & FmtShort)
5049a747e4fSDavid du Colombier f->flags |= FmtByte;
5059a747e4fSDavid du Colombier f->flags |= FmtShort;
5069a747e4fSDavid du Colombier break;
5079a747e4fSDavid du Colombier case 'l':
5089a747e4fSDavid du Colombier if(f->flags & FmtLong)
5099a747e4fSDavid du Colombier f->flags |= FmtVLong;
5109a747e4fSDavid du Colombier f->flags |= FmtLong;
5119a747e4fSDavid du Colombier break;
5129a747e4fSDavid du Colombier }
5139a747e4fSDavid du Colombier return 1;
5149a747e4fSDavid du Colombier }
5159a747e4fSDavid du Colombier
5169a747e4fSDavid du Colombier /* default error format */
5179a747e4fSDavid du Colombier int
_badfmt(Fmt * f)5189a747e4fSDavid du Colombier _badfmt(Fmt *f)
5199a747e4fSDavid du Colombier {
520*ad6ca847SDavid du Colombier Rune x[3];
5219a747e4fSDavid du Colombier
5229a747e4fSDavid du Colombier x[0] = '%';
5239a747e4fSDavid du Colombier x[1] = f->r;
5249a747e4fSDavid du Colombier x[2] = '%';
525d9306527SDavid du Colombier f->prec = 3;
526*ad6ca847SDavid du Colombier _fmtrcpy(f, x, 3);
5279a747e4fSDavid du Colombier return 0;
5289a747e4fSDavid du Colombier }
529