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