1*0d601874SDavid du Colombier /* 2*0d601874SDavid du Colombier * The authors of this software are Rob Pike and Ken Thompson. 3*0d601874SDavid du Colombier * Copyright (c) 2002 by Lucent Technologies. 4*0d601874SDavid du Colombier * Permission to use, copy, modify, and distribute this software for any 5*0d601874SDavid du Colombier * purpose without fee is hereby granted, provided that this entire notice 6*0d601874SDavid du Colombier * is included in all copies of any software which is or includes a copy 7*0d601874SDavid du Colombier * or modification of this software and in all copies of the supporting 8*0d601874SDavid du Colombier * documentation for such software. 9*0d601874SDavid du Colombier * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED 10*0d601874SDavid du Colombier * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE 11*0d601874SDavid du Colombier * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY 12*0d601874SDavid du Colombier * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. 13*0d601874SDavid du Colombier */ 148ccd4a63SDavid du Colombier #include <u.h> 158ccd4a63SDavid du Colombier #include <libc.h> 168ccd4a63SDavid du Colombier #include "fmtdef.h" 178ccd4a63SDavid du Colombier 188ccd4a63SDavid du Colombier /* format the output into f->to and return the number of characters fmted */ 198ccd4a63SDavid du Colombier int 208ccd4a63SDavid du Colombier dofmt(Fmt *f, char *fmt) 218ccd4a63SDavid du Colombier { 228ccd4a63SDavid du Colombier Rune rune, *rt, *rs; 238ccd4a63SDavid du Colombier int r; 248ccd4a63SDavid du Colombier char *t, *s; 258ccd4a63SDavid du Colombier int n, nfmt; 268ccd4a63SDavid du Colombier 278ccd4a63SDavid du Colombier nfmt = f->nfmt; 288ccd4a63SDavid du Colombier for(;;){ 298ccd4a63SDavid du Colombier if(f->runes){ 30*0d601874SDavid du Colombier rt = (Rune*)f->to; 31*0d601874SDavid du Colombier rs = (Rune*)f->stop; 328ccd4a63SDavid du Colombier while((r = *(uchar*)fmt) && r != '%'){ 338ccd4a63SDavid du Colombier if(r < Runeself) 348ccd4a63SDavid du Colombier fmt++; 358ccd4a63SDavid du Colombier else{ 368ccd4a63SDavid du Colombier fmt += chartorune(&rune, fmt); 378ccd4a63SDavid du Colombier r = rune; 388ccd4a63SDavid du Colombier } 398ccd4a63SDavid du Colombier FMTRCHAR(f, rt, rs, r); 408ccd4a63SDavid du Colombier } 418ccd4a63SDavid du Colombier fmt++; 428ccd4a63SDavid du Colombier f->nfmt += rt - (Rune *)f->to; 438ccd4a63SDavid du Colombier f->to = rt; 448ccd4a63SDavid du Colombier if(!r) 458ccd4a63SDavid du Colombier return f->nfmt - nfmt; 468ccd4a63SDavid du Colombier f->stop = rs; 478ccd4a63SDavid du Colombier }else{ 48*0d601874SDavid du Colombier t = (char*)f->to; 49*0d601874SDavid du Colombier s = (char*)f->stop; 508ccd4a63SDavid du Colombier while((r = *(uchar*)fmt) && r != '%'){ 518ccd4a63SDavid du Colombier if(r < Runeself){ 528ccd4a63SDavid du Colombier FMTCHAR(f, t, s, r); 538ccd4a63SDavid du Colombier fmt++; 548ccd4a63SDavid du Colombier }else{ 558ccd4a63SDavid du Colombier n = chartorune(&rune, fmt); 568ccd4a63SDavid du Colombier if(t + n > s){ 57*0d601874SDavid du Colombier t = (char*)__fmtflush(f, t, n); 588ccd4a63SDavid du Colombier if(t != nil) 59*0d601874SDavid du Colombier s = (char*)f->stop; 608ccd4a63SDavid du Colombier else 618ccd4a63SDavid du Colombier return -1; 628ccd4a63SDavid du Colombier } 638ccd4a63SDavid du Colombier while(n--) 648ccd4a63SDavid du Colombier *t++ = *fmt++; 658ccd4a63SDavid du Colombier } 668ccd4a63SDavid du Colombier } 678ccd4a63SDavid du Colombier fmt++; 688ccd4a63SDavid du Colombier f->nfmt += t - (char *)f->to; 698ccd4a63SDavid du Colombier f->to = t; 708ccd4a63SDavid du Colombier if(!r) 718ccd4a63SDavid du Colombier return f->nfmt - nfmt; 728ccd4a63SDavid du Colombier f->stop = s; 738ccd4a63SDavid du Colombier } 748ccd4a63SDavid du Colombier 75*0d601874SDavid du Colombier fmt = (char*)__fmtdispatch(f, fmt, 0); 768ccd4a63SDavid du Colombier if(fmt == nil) 778ccd4a63SDavid du Colombier return -1; 788ccd4a63SDavid du Colombier } 798ccd4a63SDavid du Colombier } 808ccd4a63SDavid du Colombier 818ccd4a63SDavid du Colombier void * 82*0d601874SDavid du Colombier __fmtflush(Fmt *f, void *t, int len) 838ccd4a63SDavid du Colombier { 848ccd4a63SDavid du Colombier if(f->runes) 858ccd4a63SDavid du Colombier f->nfmt += (Rune*)t - (Rune*)f->to; 868ccd4a63SDavid du Colombier else 878ccd4a63SDavid du Colombier f->nfmt += (char*)t - (char *)f->to; 888ccd4a63SDavid du Colombier f->to = t; 898ccd4a63SDavid du Colombier if(f->flush == 0 || (*f->flush)(f) == 0 || (char*)f->to + len > (char*)f->stop){ 908ccd4a63SDavid du Colombier f->stop = f->to; 918ccd4a63SDavid du Colombier return nil; 928ccd4a63SDavid du Colombier } 938ccd4a63SDavid du Colombier return f->to; 948ccd4a63SDavid du Colombier } 958ccd4a63SDavid du Colombier 968ccd4a63SDavid du Colombier /* 978ccd4a63SDavid du Colombier * put a formatted block of memory sz bytes long of n runes into the output buffer, 988ccd4a63SDavid du Colombier * left/right justified in a field of at least f->width charactes 998ccd4a63SDavid du Colombier */ 1008ccd4a63SDavid du Colombier int 101*0d601874SDavid du Colombier __fmtpad(Fmt *f, int n) 1028ccd4a63SDavid du Colombier { 1038ccd4a63SDavid du Colombier char *t, *s; 1048ccd4a63SDavid du Colombier int i; 1058ccd4a63SDavid du Colombier 106*0d601874SDavid du Colombier t = (char*)f->to; 107*0d601874SDavid du Colombier s = (char*)f->stop; 1088ccd4a63SDavid du Colombier for(i = 0; i < n; i++) 1098ccd4a63SDavid du Colombier FMTCHAR(f, t, s, ' '); 1108ccd4a63SDavid du Colombier f->nfmt += t - (char *)f->to; 1118ccd4a63SDavid du Colombier f->to = t; 1128ccd4a63SDavid du Colombier return 0; 1138ccd4a63SDavid du Colombier } 1148ccd4a63SDavid du Colombier 1158ccd4a63SDavid du Colombier int 116*0d601874SDavid du Colombier __rfmtpad(Fmt *f, int n) 1178ccd4a63SDavid du Colombier { 1188ccd4a63SDavid du Colombier Rune *t, *s; 1198ccd4a63SDavid du Colombier int i; 1208ccd4a63SDavid du Colombier 121*0d601874SDavid du Colombier t = (Rune*)f->to; 122*0d601874SDavid du Colombier s = (Rune*)f->stop; 1238ccd4a63SDavid du Colombier for(i = 0; i < n; i++) 1248ccd4a63SDavid du Colombier FMTRCHAR(f, t, s, ' '); 1258ccd4a63SDavid du Colombier f->nfmt += t - (Rune *)f->to; 1268ccd4a63SDavid du Colombier f->to = t; 1278ccd4a63SDavid du Colombier return 0; 1288ccd4a63SDavid du Colombier } 1298ccd4a63SDavid du Colombier 1308ccd4a63SDavid du Colombier int 131*0d601874SDavid du Colombier __fmtcpy(Fmt *f, const void *vm, int n, int sz) 1328ccd4a63SDavid du Colombier { 1338ccd4a63SDavid du Colombier Rune *rt, *rs, r; 1348ccd4a63SDavid du Colombier char *t, *s, *m, *me; 1358ccd4a63SDavid du Colombier ulong fl; 1368ccd4a63SDavid du Colombier int nc, w; 1378ccd4a63SDavid du Colombier 138*0d601874SDavid du Colombier m = (char*)vm; 1398ccd4a63SDavid du Colombier me = m + sz; 1408ccd4a63SDavid du Colombier w = f->width; 1418ccd4a63SDavid du Colombier fl = f->flags; 1428ccd4a63SDavid du Colombier if((fl & FmtPrec) && n > f->prec) 1438ccd4a63SDavid du Colombier n = f->prec; 1448ccd4a63SDavid du Colombier if(f->runes){ 145*0d601874SDavid du Colombier if(!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0) 1468ccd4a63SDavid du Colombier return -1; 147*0d601874SDavid du Colombier rt = (Rune*)f->to; 148*0d601874SDavid du Colombier rs = (Rune*)f->stop; 1498ccd4a63SDavid du Colombier for(nc = n; nc > 0; nc--){ 1508ccd4a63SDavid du Colombier r = *(uchar*)m; 1518ccd4a63SDavid du Colombier if(r < Runeself) 1528ccd4a63SDavid du Colombier m++; 1538ccd4a63SDavid du Colombier else if((me - m) >= UTFmax || fullrune(m, me-m)) 1548ccd4a63SDavid du Colombier m += chartorune(&r, m); 1558ccd4a63SDavid du Colombier else 1568ccd4a63SDavid du Colombier break; 1578ccd4a63SDavid du Colombier FMTRCHAR(f, rt, rs, r); 1588ccd4a63SDavid du Colombier } 1598ccd4a63SDavid du Colombier f->nfmt += rt - (Rune *)f->to; 1608ccd4a63SDavid du Colombier f->to = rt; 161*0d601874SDavid du Colombier if(fl & FmtLeft && __rfmtpad(f, w - n) < 0) 1628ccd4a63SDavid du Colombier return -1; 1638ccd4a63SDavid du Colombier }else{ 164*0d601874SDavid du Colombier if(!(fl & FmtLeft) && __fmtpad(f, w - n) < 0) 1658ccd4a63SDavid du Colombier return -1; 166*0d601874SDavid du Colombier t = (char*)f->to; 167*0d601874SDavid du Colombier s = (char*)f->stop; 1688ccd4a63SDavid du Colombier for(nc = n; nc > 0; nc--){ 1698ccd4a63SDavid du Colombier r = *(uchar*)m; 1708ccd4a63SDavid du Colombier if(r < Runeself) 1718ccd4a63SDavid du Colombier m++; 1728ccd4a63SDavid du Colombier else if((me - m) >= UTFmax || fullrune(m, me-m)) 1738ccd4a63SDavid du Colombier m += chartorune(&r, m); 1748ccd4a63SDavid du Colombier else 1758ccd4a63SDavid du Colombier break; 1768ccd4a63SDavid du Colombier FMTRUNE(f, t, s, r); 1778ccd4a63SDavid du Colombier } 1788ccd4a63SDavid du Colombier f->nfmt += t - (char *)f->to; 1798ccd4a63SDavid du Colombier f->to = t; 180*0d601874SDavid du Colombier if(fl & FmtLeft && __fmtpad(f, w - n) < 0) 1818ccd4a63SDavid du Colombier return -1; 1828ccd4a63SDavid du Colombier } 1838ccd4a63SDavid du Colombier return 0; 1848ccd4a63SDavid du Colombier } 1858ccd4a63SDavid du Colombier 1868ccd4a63SDavid du Colombier int 187*0d601874SDavid du Colombier __fmtrcpy(Fmt *f, const void *vm, int n) 1888ccd4a63SDavid du Colombier { 1898ccd4a63SDavid du Colombier Rune r, *m, *me, *rt, *rs; 1908ccd4a63SDavid du Colombier char *t, *s; 1918ccd4a63SDavid du Colombier ulong fl; 1928ccd4a63SDavid du Colombier int w; 1938ccd4a63SDavid du Colombier 194*0d601874SDavid du Colombier m = (Rune*)vm; 1958ccd4a63SDavid du Colombier w = f->width; 1968ccd4a63SDavid du Colombier fl = f->flags; 1978ccd4a63SDavid du Colombier if((fl & FmtPrec) && n > f->prec) 1988ccd4a63SDavid du Colombier n = f->prec; 1998ccd4a63SDavid du Colombier if(f->runes){ 200*0d601874SDavid du Colombier if(!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0) 2018ccd4a63SDavid du Colombier return -1; 202*0d601874SDavid du Colombier rt = (Rune*)f->to; 203*0d601874SDavid du Colombier rs = (Rune*)f->stop; 2048ccd4a63SDavid du Colombier for(me = m + n; m < me; m++) 2058ccd4a63SDavid du Colombier FMTRCHAR(f, rt, rs, *m); 2068ccd4a63SDavid du Colombier f->nfmt += rt - (Rune *)f->to; 2078ccd4a63SDavid du Colombier f->to = rt; 208*0d601874SDavid du Colombier if(fl & FmtLeft && __rfmtpad(f, w - n) < 0) 2098ccd4a63SDavid du Colombier return -1; 2108ccd4a63SDavid du Colombier }else{ 211*0d601874SDavid du Colombier if(!(fl & FmtLeft) && __fmtpad(f, w - n) < 0) 2128ccd4a63SDavid du Colombier return -1; 213*0d601874SDavid du Colombier t = (char*)f->to; 214*0d601874SDavid du Colombier s = (char*)f->stop; 2158ccd4a63SDavid du Colombier for(me = m + n; m < me; m++){ 2168ccd4a63SDavid du Colombier r = *m; 2178ccd4a63SDavid du Colombier FMTRUNE(f, t, s, r); 2188ccd4a63SDavid du Colombier } 2198ccd4a63SDavid du Colombier f->nfmt += t - (char *)f->to; 2208ccd4a63SDavid du Colombier f->to = t; 221*0d601874SDavid du Colombier if(fl & FmtLeft && __fmtpad(f, w - n) < 0) 2228ccd4a63SDavid du Colombier return -1; 2238ccd4a63SDavid du Colombier } 2248ccd4a63SDavid du Colombier return 0; 2258ccd4a63SDavid du Colombier } 2268ccd4a63SDavid du Colombier 2278ccd4a63SDavid du Colombier /* fmt out one character */ 2288ccd4a63SDavid du Colombier int 229*0d601874SDavid du Colombier __charfmt(Fmt *f) 2308ccd4a63SDavid du Colombier { 2318ccd4a63SDavid du Colombier char x[1]; 2328ccd4a63SDavid du Colombier 2338ccd4a63SDavid du Colombier x[0] = va_arg(f->args, int); 2348ccd4a63SDavid du Colombier f->prec = 1; 235*0d601874SDavid du Colombier return __fmtcpy(f, (const char*)x, 1, 1); 2368ccd4a63SDavid du Colombier } 2378ccd4a63SDavid du Colombier 2388ccd4a63SDavid du Colombier /* fmt out one rune */ 2398ccd4a63SDavid du Colombier int 240*0d601874SDavid du Colombier __runefmt(Fmt *f) 2418ccd4a63SDavid du Colombier { 2428ccd4a63SDavid du Colombier Rune x[1]; 2438ccd4a63SDavid du Colombier 2448ccd4a63SDavid du Colombier x[0] = va_arg(f->args, int); 245*0d601874SDavid du Colombier return __fmtrcpy(f, (const void*)x, 1); 2468ccd4a63SDavid du Colombier } 2478ccd4a63SDavid du Colombier 2488ccd4a63SDavid du Colombier /* public helper routine: fmt out a null terminated string already in hand */ 2498ccd4a63SDavid du Colombier int 2508ccd4a63SDavid du Colombier fmtstrcpy(Fmt *f, char *s) 2518ccd4a63SDavid du Colombier { 252*0d601874SDavid du Colombier int i, j; 253*0d601874SDavid du Colombier Rune r; 254*0d601874SDavid du Colombier 2558ccd4a63SDavid du Colombier if(!s) 256*0d601874SDavid du Colombier return __fmtcpy(f, "<nil>", 5, 5); 2578ccd4a63SDavid du Colombier /* if precision is specified, make sure we don't wander off the end */ 2588ccd4a63SDavid du Colombier if(f->flags & FmtPrec){ 259*0d601874SDavid du Colombier i = 0; 260*0d601874SDavid du Colombier for(j=0; j<f->prec && s[i]; j++) 261*0d601874SDavid du Colombier i += chartorune(&r, s+i); 262*0d601874SDavid du Colombier return __fmtcpy(f, s, j, i); 2638ccd4a63SDavid du Colombier } 264*0d601874SDavid du Colombier return __fmtcpy(f, s, utflen(s), strlen(s)); 2658ccd4a63SDavid du Colombier } 2668ccd4a63SDavid du Colombier 2678ccd4a63SDavid du Colombier /* fmt out a null terminated utf string */ 2688ccd4a63SDavid du Colombier int 269*0d601874SDavid du Colombier __strfmt(Fmt *f) 2708ccd4a63SDavid du Colombier { 2718ccd4a63SDavid du Colombier char *s; 2728ccd4a63SDavid du Colombier 2738ccd4a63SDavid du Colombier s = va_arg(f->args, char *); 2748ccd4a63SDavid du Colombier return fmtstrcpy(f, s); 2758ccd4a63SDavid du Colombier } 2768ccd4a63SDavid du Colombier 2778ccd4a63SDavid du Colombier /* public helper routine: fmt out a null terminated rune string already in hand */ 2788ccd4a63SDavid du Colombier int 2798ccd4a63SDavid du Colombier fmtrunestrcpy(Fmt *f, Rune *s) 2808ccd4a63SDavid du Colombier { 2818ccd4a63SDavid du Colombier Rune *e; 2828ccd4a63SDavid du Colombier int n, p; 2838ccd4a63SDavid du Colombier 2848ccd4a63SDavid du Colombier if(!s) 285*0d601874SDavid du Colombier return __fmtcpy(f, "<nil>", 5, 5); 2868ccd4a63SDavid du Colombier /* if precision is specified, make sure we don't wander off the end */ 2878ccd4a63SDavid du Colombier if(f->flags & FmtPrec){ 2888ccd4a63SDavid du Colombier p = f->prec; 2898ccd4a63SDavid du Colombier for(n = 0; n < p; n++) 2908ccd4a63SDavid du Colombier if(s[n] == 0) 2918ccd4a63SDavid du Colombier break; 2928ccd4a63SDavid du Colombier }else{ 2938ccd4a63SDavid du Colombier for(e = s; *e; e++) 2948ccd4a63SDavid du Colombier ; 2958ccd4a63SDavid du Colombier n = e - s; 2968ccd4a63SDavid du Colombier } 297*0d601874SDavid du Colombier return __fmtrcpy(f, s, n); 2988ccd4a63SDavid du Colombier } 2998ccd4a63SDavid du Colombier 3008ccd4a63SDavid du Colombier /* fmt out a null terminated rune string */ 3018ccd4a63SDavid du Colombier int 302*0d601874SDavid du Colombier __runesfmt(Fmt *f) 3038ccd4a63SDavid du Colombier { 3048ccd4a63SDavid du Colombier Rune *s; 3058ccd4a63SDavid du Colombier 3068ccd4a63SDavid du Colombier s = va_arg(f->args, Rune *); 3078ccd4a63SDavid du Colombier return fmtrunestrcpy(f, s); 3088ccd4a63SDavid du Colombier } 3098ccd4a63SDavid du Colombier 3108ccd4a63SDavid du Colombier /* fmt a % */ 3118ccd4a63SDavid du Colombier int 312*0d601874SDavid du Colombier __percentfmt(Fmt *f) 3138ccd4a63SDavid du Colombier { 3148ccd4a63SDavid du Colombier Rune x[1]; 3158ccd4a63SDavid du Colombier 3168ccd4a63SDavid du Colombier x[0] = f->r; 3178ccd4a63SDavid du Colombier f->prec = 1; 318*0d601874SDavid du Colombier return __fmtrcpy(f, (const void*)x, 1); 3198ccd4a63SDavid du Colombier } 3208ccd4a63SDavid du Colombier 3218ccd4a63SDavid du Colombier /* fmt an integer */ 3228ccd4a63SDavid du Colombier int 323*0d601874SDavid du Colombier __ifmt(Fmt *f) 3248ccd4a63SDavid du Colombier { 3258ccd4a63SDavid du Colombier char buf[70], *p, *conv; 3268ccd4a63SDavid du Colombier uvlong vu; 3278ccd4a63SDavid du Colombier ulong u; 3288ccd4a63SDavid du Colombier int neg, base, i, n, fl, w, isv; 3298ccd4a63SDavid du Colombier 3308ccd4a63SDavid du Colombier neg = 0; 3318ccd4a63SDavid du Colombier fl = f->flags; 3328ccd4a63SDavid du Colombier isv = 0; 3338ccd4a63SDavid du Colombier vu = 0; 3348ccd4a63SDavid du Colombier u = 0; 335*0d601874SDavid du Colombier /* 336*0d601874SDavid du Colombier * Unsigned verbs for ANSI C 337*0d601874SDavid du Colombier */ 338*0d601874SDavid du Colombier switch(f->r){ 339*0d601874SDavid du Colombier case 'x': 340*0d601874SDavid du Colombier case 'X': 341*0d601874SDavid du Colombier case 'o': 342*0d601874SDavid du Colombier case 'u': 343*0d601874SDavid du Colombier case 'p': 344*0d601874SDavid du Colombier fl |= FmtUnsigned; 345*0d601874SDavid du Colombier fl &= ~(FmtSign|FmtSpace); 346*0d601874SDavid du Colombier break; 347*0d601874SDavid du Colombier } 3488ccd4a63SDavid du Colombier if(f->r == 'p'){ 3498ccd4a63SDavid du Colombier u = (ulong)va_arg(f->args, void*); 3508ccd4a63SDavid du Colombier f->r = 'x'; 3518ccd4a63SDavid du Colombier fl |= FmtUnsigned; 3528ccd4a63SDavid du Colombier }else if(fl & FmtVLong){ 3538ccd4a63SDavid du Colombier isv = 1; 3548ccd4a63SDavid du Colombier if(fl & FmtUnsigned) 3558ccd4a63SDavid du Colombier vu = va_arg(f->args, uvlong); 3568ccd4a63SDavid du Colombier else 3578ccd4a63SDavid du Colombier vu = va_arg(f->args, vlong); 3588ccd4a63SDavid du Colombier }else if(fl & FmtLong){ 3598ccd4a63SDavid du Colombier if(fl & FmtUnsigned) 3608ccd4a63SDavid du Colombier u = va_arg(f->args, ulong); 3618ccd4a63SDavid du Colombier else 3628ccd4a63SDavid du Colombier u = va_arg(f->args, long); 3638ccd4a63SDavid du Colombier }else if(fl & FmtByte){ 3648ccd4a63SDavid du Colombier if(fl & FmtUnsigned) 3658ccd4a63SDavid du Colombier u = (uchar)va_arg(f->args, int); 3668ccd4a63SDavid du Colombier else 3678ccd4a63SDavid du Colombier u = (char)va_arg(f->args, int); 3688ccd4a63SDavid du Colombier }else if(fl & FmtShort){ 3698ccd4a63SDavid du Colombier if(fl & FmtUnsigned) 3708ccd4a63SDavid du Colombier u = (ushort)va_arg(f->args, int); 3718ccd4a63SDavid du Colombier else 3728ccd4a63SDavid du Colombier u = (short)va_arg(f->args, int); 3738ccd4a63SDavid du Colombier }else{ 3748ccd4a63SDavid du Colombier if(fl & FmtUnsigned) 3758ccd4a63SDavid du Colombier u = va_arg(f->args, uint); 3768ccd4a63SDavid du Colombier else 3778ccd4a63SDavid du Colombier u = va_arg(f->args, int); 3788ccd4a63SDavid du Colombier } 3798ccd4a63SDavid du Colombier conv = "0123456789abcdef"; 3808ccd4a63SDavid du Colombier switch(f->r){ 3818ccd4a63SDavid du Colombier case 'd': 382*0d601874SDavid du Colombier case 'i': 383*0d601874SDavid du Colombier case 'u': 3848ccd4a63SDavid du Colombier base = 10; 3858ccd4a63SDavid du Colombier break; 3868ccd4a63SDavid du Colombier case 'x': 3878ccd4a63SDavid du Colombier base = 16; 3888ccd4a63SDavid du Colombier break; 3898ccd4a63SDavid du Colombier case 'X': 3908ccd4a63SDavid du Colombier base = 16; 3918ccd4a63SDavid du Colombier conv = "0123456789ABCDEF"; 3928ccd4a63SDavid du Colombier break; 3938ccd4a63SDavid du Colombier case 'b': 3948ccd4a63SDavid du Colombier base = 2; 3958ccd4a63SDavid du Colombier break; 3968ccd4a63SDavid du Colombier case 'o': 3978ccd4a63SDavid du Colombier base = 8; 3988ccd4a63SDavid du Colombier break; 3998ccd4a63SDavid du Colombier default: 4008ccd4a63SDavid du Colombier return -1; 4018ccd4a63SDavid du Colombier } 4028ccd4a63SDavid du Colombier if(!(fl & FmtUnsigned)){ 4038ccd4a63SDavid du Colombier if(isv && (vlong)vu < 0){ 4048ccd4a63SDavid du Colombier vu = -(vlong)vu; 4058ccd4a63SDavid du Colombier neg = 1; 4068ccd4a63SDavid du Colombier }else if(!isv && (long)u < 0){ 4078ccd4a63SDavid du Colombier u = -(long)u; 4088ccd4a63SDavid du Colombier neg = 1; 4098ccd4a63SDavid du Colombier } 4108ccd4a63SDavid du Colombier } 4118ccd4a63SDavid du Colombier p = buf + sizeof buf - 1; 4128ccd4a63SDavid du Colombier n = 0; 4138ccd4a63SDavid du Colombier if(isv){ 4148ccd4a63SDavid du Colombier while(vu){ 4158ccd4a63SDavid du Colombier i = vu % base; 4168ccd4a63SDavid du Colombier vu /= base; 4178ccd4a63SDavid du Colombier if((fl & FmtComma) && n % 4 == 3){ 4188ccd4a63SDavid du Colombier *p-- = ','; 4198ccd4a63SDavid du Colombier n++; 4208ccd4a63SDavid du Colombier } 4218ccd4a63SDavid du Colombier *p-- = conv[i]; 4228ccd4a63SDavid du Colombier n++; 4238ccd4a63SDavid du Colombier } 4248ccd4a63SDavid du Colombier }else{ 4258ccd4a63SDavid du Colombier while(u){ 4268ccd4a63SDavid du Colombier i = u % base; 4278ccd4a63SDavid du Colombier u /= base; 4288ccd4a63SDavid du Colombier if((fl & FmtComma) && n % 4 == 3){ 4298ccd4a63SDavid du Colombier *p-- = ','; 4308ccd4a63SDavid du Colombier n++; 4318ccd4a63SDavid du Colombier } 4328ccd4a63SDavid du Colombier *p-- = conv[i]; 4338ccd4a63SDavid du Colombier n++; 4348ccd4a63SDavid du Colombier } 4358ccd4a63SDavid du Colombier } 4368ccd4a63SDavid du Colombier if(n == 0){ 4378ccd4a63SDavid du Colombier *p-- = '0'; 4388ccd4a63SDavid du Colombier n = 1; 4398ccd4a63SDavid du Colombier } 4408ccd4a63SDavid du Colombier for(w = f->prec; n < w && p > buf+3; n++) 4418ccd4a63SDavid du Colombier *p-- = '0'; 4428ccd4a63SDavid du Colombier if(neg || (fl & (FmtSign|FmtSpace))) 4438ccd4a63SDavid du Colombier n++; 4448ccd4a63SDavid du Colombier if(fl & FmtSharp){ 4458ccd4a63SDavid du Colombier if(base == 16) 4468ccd4a63SDavid du Colombier n += 2; 4478ccd4a63SDavid du Colombier else if(base == 8){ 4488ccd4a63SDavid du Colombier if(p[1] == '0') 4498ccd4a63SDavid du Colombier fl &= ~FmtSharp; 4508ccd4a63SDavid du Colombier else 4518ccd4a63SDavid du Colombier n++; 4528ccd4a63SDavid du Colombier } 4538ccd4a63SDavid du Colombier } 454*0d601874SDavid du Colombier if((fl & FmtZero) && !(fl & (FmtLeft|FmtPrec))){ 4558ccd4a63SDavid du Colombier for(w = f->width; n < w && p > buf+3; n++) 4568ccd4a63SDavid du Colombier *p-- = '0'; 4578ccd4a63SDavid du Colombier f->width = 0; 4588ccd4a63SDavid du Colombier } 4598ccd4a63SDavid du Colombier if(fl & FmtSharp){ 4608ccd4a63SDavid du Colombier if(base == 16) 4618ccd4a63SDavid du Colombier *p-- = f->r; 4628ccd4a63SDavid du Colombier if(base == 16 || base == 8) 4638ccd4a63SDavid du Colombier *p-- = '0'; 4648ccd4a63SDavid du Colombier } 4658ccd4a63SDavid du Colombier if(neg) 4668ccd4a63SDavid du Colombier *p-- = '-'; 4678ccd4a63SDavid du Colombier else if(fl & FmtSign) 4688ccd4a63SDavid du Colombier *p-- = '+'; 4698ccd4a63SDavid du Colombier else if(fl & FmtSpace) 4708ccd4a63SDavid du Colombier *p-- = ' '; 4718ccd4a63SDavid du Colombier f->flags &= ~FmtPrec; 472*0d601874SDavid du Colombier return __fmtcpy(f, p + 1, n, n); 4738ccd4a63SDavid du Colombier } 4748ccd4a63SDavid du Colombier 4758ccd4a63SDavid du Colombier int 476*0d601874SDavid du Colombier __countfmt(Fmt *f) 4778ccd4a63SDavid du Colombier { 4788ccd4a63SDavid du Colombier void *p; 4798ccd4a63SDavid du Colombier ulong fl; 4808ccd4a63SDavid du Colombier 4818ccd4a63SDavid du Colombier fl = f->flags; 4828ccd4a63SDavid du Colombier p = va_arg(f->args, void*); 4838ccd4a63SDavid du Colombier if(fl & FmtVLong){ 4848ccd4a63SDavid du Colombier *(vlong*)p = f->nfmt; 4858ccd4a63SDavid du Colombier }else if(fl & FmtLong){ 4868ccd4a63SDavid du Colombier *(long*)p = f->nfmt; 4878ccd4a63SDavid du Colombier }else if(fl & FmtByte){ 4888ccd4a63SDavid du Colombier *(char*)p = f->nfmt; 4898ccd4a63SDavid du Colombier }else if(fl & FmtShort){ 4908ccd4a63SDavid du Colombier *(short*)p = f->nfmt; 4918ccd4a63SDavid du Colombier }else{ 4928ccd4a63SDavid du Colombier *(int*)p = f->nfmt; 4938ccd4a63SDavid du Colombier } 4948ccd4a63SDavid du Colombier return 0; 4958ccd4a63SDavid du Colombier } 4968ccd4a63SDavid du Colombier 4978ccd4a63SDavid du Colombier int 498*0d601874SDavid du Colombier __flagfmt(Fmt *f) 4998ccd4a63SDavid du Colombier { 5008ccd4a63SDavid du Colombier switch(f->r){ 5018ccd4a63SDavid du Colombier case ',': 5028ccd4a63SDavid du Colombier f->flags |= FmtComma; 5038ccd4a63SDavid du Colombier break; 5048ccd4a63SDavid du Colombier case '-': 5058ccd4a63SDavid du Colombier f->flags |= FmtLeft; 5068ccd4a63SDavid du Colombier break; 5078ccd4a63SDavid du Colombier case '+': 5088ccd4a63SDavid du Colombier f->flags |= FmtSign; 5098ccd4a63SDavid du Colombier break; 5108ccd4a63SDavid du Colombier case '#': 5118ccd4a63SDavid du Colombier f->flags |= FmtSharp; 5128ccd4a63SDavid du Colombier break; 5138ccd4a63SDavid du Colombier case ' ': 5148ccd4a63SDavid du Colombier f->flags |= FmtSpace; 5158ccd4a63SDavid du Colombier break; 5168ccd4a63SDavid du Colombier case 'u': 5178ccd4a63SDavid du Colombier f->flags |= FmtUnsigned; 5188ccd4a63SDavid du Colombier break; 5198ccd4a63SDavid du Colombier case 'h': 5208ccd4a63SDavid du Colombier if(f->flags & FmtShort) 5218ccd4a63SDavid du Colombier f->flags |= FmtByte; 5228ccd4a63SDavid du Colombier f->flags |= FmtShort; 5238ccd4a63SDavid du Colombier break; 524*0d601874SDavid du Colombier case 'L': 525*0d601874SDavid du Colombier f->flags |= FmtLDouble; 526*0d601874SDavid du Colombier break; 5278ccd4a63SDavid du Colombier case 'l': 5288ccd4a63SDavid du Colombier if(f->flags & FmtLong) 5298ccd4a63SDavid du Colombier f->flags |= FmtVLong; 5308ccd4a63SDavid du Colombier f->flags |= FmtLong; 5318ccd4a63SDavid du Colombier break; 5328ccd4a63SDavid du Colombier } 5338ccd4a63SDavid du Colombier return 1; 5348ccd4a63SDavid du Colombier } 5358ccd4a63SDavid du Colombier 5368ccd4a63SDavid du Colombier /* default error format */ 5378ccd4a63SDavid du Colombier int 538*0d601874SDavid du Colombier __badfmt(Fmt *f) 5398ccd4a63SDavid du Colombier { 5408ccd4a63SDavid du Colombier char x[3]; 5418ccd4a63SDavid du Colombier 5428ccd4a63SDavid du Colombier x[0] = '%'; 5438ccd4a63SDavid du Colombier x[1] = f->r; 5448ccd4a63SDavid du Colombier x[2] = '%'; 5458ccd4a63SDavid du Colombier f->prec = 3; 546*0d601874SDavid du Colombier __fmtcpy(f, (const void*)x, 3, 3); 5478ccd4a63SDavid du Colombier return 0; 5488ccd4a63SDavid du Colombier } 549