18ccd4a63SDavid du Colombier #include <u.h>
28ccd4a63SDavid du Colombier #include <libc.h>
38ccd4a63SDavid du Colombier #include "fmtdef.h"
48ccd4a63SDavid du Colombier
58ccd4a63SDavid du Colombier /* format the output into f->to and return the number of characters fmted */
68ccd4a63SDavid du Colombier int
dofmt(Fmt * f,char * fmt)78ccd4a63SDavid du Colombier dofmt(Fmt *f, char *fmt)
88ccd4a63SDavid du Colombier {
98ccd4a63SDavid du Colombier Rune rune, *rt, *rs;
108ccd4a63SDavid du Colombier int r;
118ccd4a63SDavid du Colombier char *t, *s;
128ccd4a63SDavid du Colombier int n, nfmt;
138ccd4a63SDavid du Colombier
148ccd4a63SDavid du Colombier nfmt = f->nfmt;
158ccd4a63SDavid du Colombier for(;;){
168ccd4a63SDavid du Colombier if(f->runes){
170d601874SDavid du Colombier rt = (Rune*)f->to;
180d601874SDavid du Colombier rs = (Rune*)f->stop;
198ccd4a63SDavid du Colombier while((r = *(uchar*)fmt) && r != '%'){
208ccd4a63SDavid du Colombier if(r < Runeself)
218ccd4a63SDavid du Colombier fmt++;
228ccd4a63SDavid du Colombier else{
238ccd4a63SDavid du Colombier fmt += chartorune(&rune, fmt);
248ccd4a63SDavid du Colombier r = rune;
258ccd4a63SDavid du Colombier }
268ccd4a63SDavid du Colombier FMTRCHAR(f, rt, rs, r);
278ccd4a63SDavid du Colombier }
288ccd4a63SDavid du Colombier fmt++;
298ccd4a63SDavid du Colombier f->nfmt += rt - (Rune *)f->to;
308ccd4a63SDavid du Colombier f->to = rt;
318ccd4a63SDavid du Colombier if(!r)
328ccd4a63SDavid du Colombier return f->nfmt - nfmt;
338ccd4a63SDavid du Colombier f->stop = rs;
348ccd4a63SDavid du Colombier }else{
350d601874SDavid du Colombier t = (char*)f->to;
360d601874SDavid du Colombier s = (char*)f->stop;
378ccd4a63SDavid du Colombier while((r = *(uchar*)fmt) && r != '%'){
388ccd4a63SDavid du Colombier if(r < Runeself){
398ccd4a63SDavid du Colombier FMTCHAR(f, t, s, r);
408ccd4a63SDavid du Colombier fmt++;
418ccd4a63SDavid du Colombier }else{
428ccd4a63SDavid du Colombier n = chartorune(&rune, fmt);
438ccd4a63SDavid du Colombier if(t + n > s){
440d601874SDavid du Colombier t = (char*)__fmtflush(f, t, n);
458ccd4a63SDavid du Colombier if(t != nil)
460d601874SDavid du Colombier s = (char*)f->stop;
478ccd4a63SDavid du Colombier else
488ccd4a63SDavid du Colombier return -1;
498ccd4a63SDavid du Colombier }
508ccd4a63SDavid du Colombier while(n--)
518ccd4a63SDavid du Colombier *t++ = *fmt++;
528ccd4a63SDavid du Colombier }
538ccd4a63SDavid du Colombier }
548ccd4a63SDavid du Colombier fmt++;
558ccd4a63SDavid du Colombier f->nfmt += t - (char *)f->to;
568ccd4a63SDavid du Colombier f->to = t;
578ccd4a63SDavid du Colombier if(!r)
588ccd4a63SDavid du Colombier return f->nfmt - nfmt;
598ccd4a63SDavid du Colombier f->stop = s;
608ccd4a63SDavid du Colombier }
618ccd4a63SDavid du Colombier
620d601874SDavid du Colombier fmt = (char*)__fmtdispatch(f, fmt, 0);
638ccd4a63SDavid du Colombier if(fmt == nil)
648ccd4a63SDavid du Colombier return -1;
658ccd4a63SDavid du Colombier }
668ccd4a63SDavid du Colombier }
678ccd4a63SDavid du Colombier
688ccd4a63SDavid du Colombier void *
__fmtflush(Fmt * f,void * t,int len)690d601874SDavid du Colombier __fmtflush(Fmt *f, void *t, int len)
708ccd4a63SDavid du Colombier {
718ccd4a63SDavid du Colombier if(f->runes)
728ccd4a63SDavid du Colombier f->nfmt += (Rune*)t - (Rune*)f->to;
738ccd4a63SDavid du Colombier else
748ccd4a63SDavid du Colombier f->nfmt += (char*)t - (char *)f->to;
758ccd4a63SDavid du Colombier f->to = t;
768ccd4a63SDavid du Colombier if(f->flush == 0 || (*f->flush)(f) == 0 || (char*)f->to + len > (char*)f->stop){
778ccd4a63SDavid du Colombier f->stop = f->to;
788ccd4a63SDavid du Colombier return nil;
798ccd4a63SDavid du Colombier }
808ccd4a63SDavid du Colombier return f->to;
818ccd4a63SDavid du Colombier }
828ccd4a63SDavid du Colombier
838ccd4a63SDavid du Colombier /*
848ccd4a63SDavid du Colombier * put a formatted block of memory sz bytes long of n runes into the output buffer,
858ccd4a63SDavid du Colombier * left/right justified in a field of at least f->width charactes
868ccd4a63SDavid du Colombier */
878ccd4a63SDavid du Colombier int
__fmtpad(Fmt * f,int n)880d601874SDavid du Colombier __fmtpad(Fmt *f, int n)
898ccd4a63SDavid du Colombier {
908ccd4a63SDavid du Colombier char *t, *s;
918ccd4a63SDavid du Colombier int i;
928ccd4a63SDavid du Colombier
930d601874SDavid du Colombier t = (char*)f->to;
940d601874SDavid du Colombier s = (char*)f->stop;
958ccd4a63SDavid du Colombier for(i = 0; i < n; i++)
968ccd4a63SDavid du Colombier FMTCHAR(f, t, s, ' ');
978ccd4a63SDavid du Colombier f->nfmt += t - (char *)f->to;
988ccd4a63SDavid du Colombier f->to = t;
998ccd4a63SDavid du Colombier return 0;
1008ccd4a63SDavid du Colombier }
1018ccd4a63SDavid du Colombier
1028ccd4a63SDavid du Colombier int
__rfmtpad(Fmt * f,int n)1030d601874SDavid du Colombier __rfmtpad(Fmt *f, int n)
1048ccd4a63SDavid du Colombier {
1058ccd4a63SDavid du Colombier Rune *t, *s;
1068ccd4a63SDavid du Colombier int i;
1078ccd4a63SDavid du Colombier
1080d601874SDavid du Colombier t = (Rune*)f->to;
1090d601874SDavid du Colombier s = (Rune*)f->stop;
1108ccd4a63SDavid du Colombier for(i = 0; i < n; i++)
1118ccd4a63SDavid du Colombier FMTRCHAR(f, t, s, ' ');
1128ccd4a63SDavid du Colombier f->nfmt += t - (Rune *)f->to;
1138ccd4a63SDavid du Colombier f->to = t;
1148ccd4a63SDavid du Colombier return 0;
1158ccd4a63SDavid du Colombier }
1168ccd4a63SDavid du Colombier
1178ccd4a63SDavid du Colombier int
__fmtcpy(Fmt * f,const void * vm,int n,int sz)1180d601874SDavid du Colombier __fmtcpy(Fmt *f, const void *vm, int n, int sz)
1198ccd4a63SDavid du Colombier {
1208ccd4a63SDavid du Colombier Rune *rt, *rs, r;
1218ccd4a63SDavid du Colombier char *t, *s, *m, *me;
1228ccd4a63SDavid du Colombier ulong fl;
1238ccd4a63SDavid du Colombier int nc, w;
1248ccd4a63SDavid du Colombier
1250d601874SDavid du Colombier m = (char*)vm;
1268ccd4a63SDavid du Colombier me = m + sz;
1278ccd4a63SDavid du Colombier w = f->width;
1288ccd4a63SDavid du Colombier fl = f->flags;
1298ccd4a63SDavid du Colombier if((fl & FmtPrec) && n > f->prec)
1308ccd4a63SDavid du Colombier n = f->prec;
1318ccd4a63SDavid du Colombier if(f->runes){
1320d601874SDavid du Colombier if(!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0)
1338ccd4a63SDavid du Colombier return -1;
1340d601874SDavid du Colombier rt = (Rune*)f->to;
1350d601874SDavid du Colombier rs = (Rune*)f->stop;
1368ccd4a63SDavid du Colombier for(nc = n; nc > 0; nc--){
1378ccd4a63SDavid du Colombier r = *(uchar*)m;
1388ccd4a63SDavid du Colombier if(r < Runeself)
1398ccd4a63SDavid du Colombier m++;
1408ccd4a63SDavid du Colombier else if((me - m) >= UTFmax || fullrune(m, me-m))
1418ccd4a63SDavid du Colombier m += chartorune(&r, m);
1428ccd4a63SDavid du Colombier else
1438ccd4a63SDavid du Colombier break;
1448ccd4a63SDavid du Colombier FMTRCHAR(f, rt, rs, r);
1458ccd4a63SDavid du Colombier }
1468ccd4a63SDavid du Colombier f->nfmt += rt - (Rune *)f->to;
1478ccd4a63SDavid du Colombier f->to = rt;
1480d601874SDavid du Colombier if(fl & FmtLeft && __rfmtpad(f, w - n) < 0)
1498ccd4a63SDavid du Colombier return -1;
1508ccd4a63SDavid du Colombier }else{
1510d601874SDavid du Colombier if(!(fl & FmtLeft) && __fmtpad(f, w - n) < 0)
1528ccd4a63SDavid du Colombier return -1;
1530d601874SDavid du Colombier t = (char*)f->to;
1540d601874SDavid du Colombier s = (char*)f->stop;
1558ccd4a63SDavid du Colombier for(nc = n; nc > 0; nc--){
1568ccd4a63SDavid du Colombier r = *(uchar*)m;
1578ccd4a63SDavid du Colombier if(r < Runeself)
1588ccd4a63SDavid du Colombier m++;
1598ccd4a63SDavid du Colombier else if((me - m) >= UTFmax || fullrune(m, me-m))
1608ccd4a63SDavid du Colombier m += chartorune(&r, m);
1618ccd4a63SDavid du Colombier else
1628ccd4a63SDavid du Colombier break;
1638ccd4a63SDavid du Colombier FMTRUNE(f, t, s, r);
1648ccd4a63SDavid du Colombier }
1658ccd4a63SDavid du Colombier f->nfmt += t - (char *)f->to;
1668ccd4a63SDavid du Colombier f->to = t;
1670d601874SDavid du Colombier if(fl & FmtLeft && __fmtpad(f, w - n) < 0)
1688ccd4a63SDavid du Colombier return -1;
1698ccd4a63SDavid du Colombier }
1708ccd4a63SDavid du Colombier return 0;
1718ccd4a63SDavid du Colombier }
1728ccd4a63SDavid du Colombier
1738ccd4a63SDavid du Colombier int
__fmtrcpy(Fmt * f,const void * vm,int n)1740d601874SDavid du Colombier __fmtrcpy(Fmt *f, const void *vm, int n)
1758ccd4a63SDavid du Colombier {
1768ccd4a63SDavid du Colombier Rune r, *m, *me, *rt, *rs;
1778ccd4a63SDavid du Colombier char *t, *s;
1788ccd4a63SDavid du Colombier ulong fl;
1798ccd4a63SDavid du Colombier int w;
1808ccd4a63SDavid du Colombier
1810d601874SDavid du Colombier m = (Rune*)vm;
1828ccd4a63SDavid du Colombier w = f->width;
1838ccd4a63SDavid du Colombier fl = f->flags;
1848ccd4a63SDavid du Colombier if((fl & FmtPrec) && n > f->prec)
1858ccd4a63SDavid du Colombier n = f->prec;
1868ccd4a63SDavid du Colombier if(f->runes){
1870d601874SDavid du Colombier if(!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0)
1888ccd4a63SDavid du Colombier return -1;
1890d601874SDavid du Colombier rt = (Rune*)f->to;
1900d601874SDavid du Colombier rs = (Rune*)f->stop;
1918ccd4a63SDavid du Colombier for(me = m + n; m < me; m++)
1928ccd4a63SDavid du Colombier FMTRCHAR(f, rt, rs, *m);
1938ccd4a63SDavid du Colombier f->nfmt += rt - (Rune *)f->to;
1948ccd4a63SDavid du Colombier f->to = rt;
1950d601874SDavid du Colombier if(fl & FmtLeft && __rfmtpad(f, w - n) < 0)
1968ccd4a63SDavid du Colombier return -1;
1978ccd4a63SDavid du Colombier }else{
1980d601874SDavid du Colombier if(!(fl & FmtLeft) && __fmtpad(f, w - n) < 0)
1998ccd4a63SDavid du Colombier return -1;
2000d601874SDavid du Colombier t = (char*)f->to;
2010d601874SDavid du Colombier s = (char*)f->stop;
2028ccd4a63SDavid du Colombier for(me = m + n; m < me; m++){
2038ccd4a63SDavid du Colombier r = *m;
2048ccd4a63SDavid du Colombier FMTRUNE(f, t, s, r);
2058ccd4a63SDavid du Colombier }
2068ccd4a63SDavid du Colombier f->nfmt += t - (char *)f->to;
2078ccd4a63SDavid du Colombier f->to = t;
2080d601874SDavid du Colombier if(fl & FmtLeft && __fmtpad(f, w - n) < 0)
2098ccd4a63SDavid du Colombier return -1;
2108ccd4a63SDavid du Colombier }
2118ccd4a63SDavid du Colombier return 0;
2128ccd4a63SDavid du Colombier }
2138ccd4a63SDavid du Colombier
2148ccd4a63SDavid du Colombier /* fmt out one character */
2158ccd4a63SDavid du Colombier int
__charfmt(Fmt * f)2160d601874SDavid du Colombier __charfmt(Fmt *f)
2178ccd4a63SDavid du Colombier {
2188ccd4a63SDavid du Colombier char x[1];
2198ccd4a63SDavid du Colombier
2208ccd4a63SDavid du Colombier x[0] = va_arg(f->args, int);
2218ccd4a63SDavid du Colombier f->prec = 1;
2220d601874SDavid du Colombier return __fmtcpy(f, (const char*)x, 1, 1);
2238ccd4a63SDavid du Colombier }
2248ccd4a63SDavid du Colombier
2258ccd4a63SDavid du Colombier /* fmt out one rune */
2268ccd4a63SDavid du Colombier int
__runefmt(Fmt * f)2270d601874SDavid du Colombier __runefmt(Fmt *f)
2288ccd4a63SDavid du Colombier {
2298ccd4a63SDavid du Colombier Rune x[1];
2308ccd4a63SDavid du Colombier
2318ccd4a63SDavid du Colombier x[0] = va_arg(f->args, int);
2320d601874SDavid du Colombier return __fmtrcpy(f, (const void*)x, 1);
2338ccd4a63SDavid du Colombier }
2348ccd4a63SDavid du Colombier
2358ccd4a63SDavid du Colombier /* public helper routine: fmt out a null terminated string already in hand */
2368ccd4a63SDavid du Colombier int
fmtstrcpy(Fmt * f,char * s)2378ccd4a63SDavid du Colombier fmtstrcpy(Fmt *f, char *s)
2388ccd4a63SDavid du Colombier {
2390d601874SDavid du Colombier int i, j;
2400d601874SDavid du Colombier Rune r;
2410d601874SDavid du Colombier
2428ccd4a63SDavid du Colombier if(!s)
2430d601874SDavid du Colombier return __fmtcpy(f, "<nil>", 5, 5);
2448ccd4a63SDavid du Colombier /* if precision is specified, make sure we don't wander off the end */
2458ccd4a63SDavid du Colombier if(f->flags & FmtPrec){
2460d601874SDavid du Colombier i = 0;
2470d601874SDavid du Colombier for(j=0; j<f->prec && s[i]; j++)
2480d601874SDavid du Colombier i += chartorune(&r, s+i);
2490d601874SDavid du Colombier return __fmtcpy(f, s, j, i);
2508ccd4a63SDavid du Colombier }
2510d601874SDavid du Colombier return __fmtcpy(f, s, utflen(s), strlen(s));
2528ccd4a63SDavid du Colombier }
2538ccd4a63SDavid du Colombier
2548ccd4a63SDavid du Colombier /* fmt out a null terminated utf string */
2558ccd4a63SDavid du Colombier int
__strfmt(Fmt * f)2560d601874SDavid du Colombier __strfmt(Fmt *f)
2578ccd4a63SDavid du Colombier {
2588ccd4a63SDavid du Colombier char *s;
2598ccd4a63SDavid du Colombier
2608ccd4a63SDavid du Colombier s = va_arg(f->args, char *);
2618ccd4a63SDavid du Colombier return fmtstrcpy(f, s);
2628ccd4a63SDavid du Colombier }
2638ccd4a63SDavid du Colombier
2648ccd4a63SDavid du Colombier /* public helper routine: fmt out a null terminated rune string already in hand */
2658ccd4a63SDavid du Colombier int
fmtrunestrcpy(Fmt * f,Rune * s)2668ccd4a63SDavid du Colombier fmtrunestrcpy(Fmt *f, Rune *s)
2678ccd4a63SDavid du Colombier {
2688ccd4a63SDavid du Colombier Rune *e;
2698ccd4a63SDavid du Colombier int n, p;
2708ccd4a63SDavid du Colombier
2718ccd4a63SDavid du Colombier if(!s)
2720d601874SDavid du Colombier return __fmtcpy(f, "<nil>", 5, 5);
2738ccd4a63SDavid du Colombier /* if precision is specified, make sure we don't wander off the end */
2748ccd4a63SDavid du Colombier if(f->flags & FmtPrec){
2758ccd4a63SDavid du Colombier p = f->prec;
2768ccd4a63SDavid du Colombier for(n = 0; n < p; n++)
2778ccd4a63SDavid du Colombier if(s[n] == 0)
2788ccd4a63SDavid du Colombier break;
2798ccd4a63SDavid du Colombier }else{
2808ccd4a63SDavid du Colombier for(e = s; *e; e++)
2818ccd4a63SDavid du Colombier ;
2828ccd4a63SDavid du Colombier n = e - s;
2838ccd4a63SDavid du Colombier }
2840d601874SDavid du Colombier return __fmtrcpy(f, s, n);
2858ccd4a63SDavid du Colombier }
2868ccd4a63SDavid du Colombier
2878ccd4a63SDavid du Colombier /* fmt out a null terminated rune string */
2888ccd4a63SDavid du Colombier int
__runesfmt(Fmt * f)2890d601874SDavid du Colombier __runesfmt(Fmt *f)
2908ccd4a63SDavid du Colombier {
2918ccd4a63SDavid du Colombier Rune *s;
2928ccd4a63SDavid du Colombier
2938ccd4a63SDavid du Colombier s = va_arg(f->args, Rune *);
2948ccd4a63SDavid du Colombier return fmtrunestrcpy(f, s);
2958ccd4a63SDavid du Colombier }
2968ccd4a63SDavid du Colombier
2978ccd4a63SDavid du Colombier /* fmt a % */
2988ccd4a63SDavid du Colombier int
__percentfmt(Fmt * f)2990d601874SDavid du Colombier __percentfmt(Fmt *f)
3008ccd4a63SDavid du Colombier {
3018ccd4a63SDavid du Colombier Rune x[1];
3028ccd4a63SDavid du Colombier
3038ccd4a63SDavid du Colombier x[0] = f->r;
3048ccd4a63SDavid du Colombier f->prec = 1;
3050d601874SDavid du Colombier return __fmtrcpy(f, (const void*)x, 1);
3068ccd4a63SDavid du Colombier }
3078ccd4a63SDavid du Colombier
3088ccd4a63SDavid du Colombier /* fmt an integer */
3098ccd4a63SDavid du Colombier int
__ifmt(Fmt * f)3100d601874SDavid du Colombier __ifmt(Fmt *f)
3118ccd4a63SDavid du Colombier {
3128ccd4a63SDavid du Colombier char buf[70], *p, *conv;
3138ccd4a63SDavid du Colombier uvlong vu;
3148ccd4a63SDavid du Colombier ulong u;
3158ccd4a63SDavid du Colombier int neg, base, i, n, fl, w, isv;
3168ccd4a63SDavid du Colombier
3178ccd4a63SDavid du Colombier neg = 0;
3188ccd4a63SDavid du Colombier fl = f->flags;
3198ccd4a63SDavid du Colombier isv = 0;
3208ccd4a63SDavid du Colombier vu = 0;
3218ccd4a63SDavid du Colombier u = 0;
3220d601874SDavid du Colombier /*
3230d601874SDavid du Colombier * Unsigned verbs for ANSI C
3240d601874SDavid du Colombier */
3250d601874SDavid du Colombier switch(f->r){
3260d601874SDavid du Colombier case 'x':
3270d601874SDavid du Colombier case 'X':
3280d601874SDavid du Colombier case 'o':
3290d601874SDavid du Colombier case 'u':
3300d601874SDavid du Colombier case 'p':
3310d601874SDavid du Colombier fl |= FmtUnsigned;
3320d601874SDavid du Colombier fl &= ~(FmtSign|FmtSpace);
3330d601874SDavid du Colombier break;
3340d601874SDavid du Colombier }
3358ccd4a63SDavid du Colombier if(f->r == 'p'){
336*ec59a3ddSDavid du Colombier if(sizeof(void*) == sizeof(uvlong)){
337*ec59a3ddSDavid du Colombier isv = 1;
338*ec59a3ddSDavid du Colombier vu = (uvlong)va_arg(f->args, uvlong);
339*ec59a3ddSDavid du Colombier }else
340*ec59a3ddSDavid du Colombier u = (ulong)va_arg(f->args, ulong);
3418ccd4a63SDavid du Colombier f->r = 'x';
3428ccd4a63SDavid du Colombier fl |= FmtUnsigned;
3438ccd4a63SDavid du Colombier }else if(fl & FmtVLong){
3448ccd4a63SDavid du Colombier isv = 1;
3458ccd4a63SDavid du Colombier if(fl & FmtUnsigned)
3468ccd4a63SDavid du Colombier vu = va_arg(f->args, uvlong);
3478ccd4a63SDavid du Colombier else
3488ccd4a63SDavid du Colombier vu = va_arg(f->args, vlong);
3498ccd4a63SDavid du Colombier }else if(fl & FmtLong){
3508ccd4a63SDavid du Colombier if(fl & FmtUnsigned)
3518ccd4a63SDavid du Colombier u = va_arg(f->args, ulong);
3528ccd4a63SDavid du Colombier else
3538ccd4a63SDavid du Colombier u = va_arg(f->args, long);
3548ccd4a63SDavid du Colombier }else if(fl & FmtByte){
3558ccd4a63SDavid du Colombier if(fl & FmtUnsigned)
3568ccd4a63SDavid du Colombier u = (uchar)va_arg(f->args, int);
3578ccd4a63SDavid du Colombier else
3588ccd4a63SDavid du Colombier u = (char)va_arg(f->args, int);
3598ccd4a63SDavid du Colombier }else if(fl & FmtShort){
3608ccd4a63SDavid du Colombier if(fl & FmtUnsigned)
3618ccd4a63SDavid du Colombier u = (ushort)va_arg(f->args, int);
3628ccd4a63SDavid du Colombier else
3638ccd4a63SDavid du Colombier u = (short)va_arg(f->args, int);
3648ccd4a63SDavid du Colombier }else{
3658ccd4a63SDavid du Colombier if(fl & FmtUnsigned)
3668ccd4a63SDavid du Colombier u = va_arg(f->args, uint);
3678ccd4a63SDavid du Colombier else
3688ccd4a63SDavid du Colombier u = va_arg(f->args, int);
3698ccd4a63SDavid du Colombier }
3708ccd4a63SDavid du Colombier conv = "0123456789abcdef";
3718ccd4a63SDavid du Colombier switch(f->r){
3728ccd4a63SDavid du Colombier case 'd':
3730d601874SDavid du Colombier case 'i':
3740d601874SDavid du Colombier case 'u':
3758ccd4a63SDavid du Colombier base = 10;
3768ccd4a63SDavid du Colombier break;
3778ccd4a63SDavid du Colombier case 'x':
3788ccd4a63SDavid du Colombier base = 16;
3798ccd4a63SDavid du Colombier break;
3808ccd4a63SDavid du Colombier case 'X':
3818ccd4a63SDavid du Colombier base = 16;
3828ccd4a63SDavid du Colombier conv = "0123456789ABCDEF";
3838ccd4a63SDavid du Colombier break;
3848ccd4a63SDavid du Colombier case 'b':
3858ccd4a63SDavid du Colombier base = 2;
3868ccd4a63SDavid du Colombier break;
3878ccd4a63SDavid du Colombier case 'o':
3888ccd4a63SDavid du Colombier base = 8;
3898ccd4a63SDavid du Colombier break;
3908ccd4a63SDavid du Colombier default:
3918ccd4a63SDavid du Colombier return -1;
3928ccd4a63SDavid du Colombier }
3938ccd4a63SDavid du Colombier if(!(fl & FmtUnsigned)){
3948ccd4a63SDavid du Colombier if(isv && (vlong)vu < 0){
3958ccd4a63SDavid du Colombier vu = -(vlong)vu;
3968ccd4a63SDavid du Colombier neg = 1;
3978ccd4a63SDavid du Colombier }else if(!isv && (long)u < 0){
3988ccd4a63SDavid du Colombier u = -(long)u;
3998ccd4a63SDavid du Colombier neg = 1;
4008ccd4a63SDavid du Colombier }
4018ccd4a63SDavid du Colombier }
4028ccd4a63SDavid du Colombier p = buf + sizeof buf - 1;
4038ccd4a63SDavid du Colombier n = 0;
4048ccd4a63SDavid du Colombier if(isv){
4058ccd4a63SDavid du Colombier while(vu){
4068ccd4a63SDavid du Colombier i = vu % base;
4078ccd4a63SDavid du Colombier vu /= base;
4088ccd4a63SDavid du Colombier if((fl & FmtComma) && n % 4 == 3){
4098ccd4a63SDavid du Colombier *p-- = ',';
4108ccd4a63SDavid du Colombier n++;
4118ccd4a63SDavid du Colombier }
4128ccd4a63SDavid du Colombier *p-- = conv[i];
4138ccd4a63SDavid du Colombier n++;
4148ccd4a63SDavid du Colombier }
4158ccd4a63SDavid du Colombier }else{
4168ccd4a63SDavid du Colombier while(u){
4178ccd4a63SDavid du Colombier i = u % base;
4188ccd4a63SDavid du Colombier u /= base;
4198ccd4a63SDavid du Colombier if((fl & FmtComma) && n % 4 == 3){
4208ccd4a63SDavid du Colombier *p-- = ',';
4218ccd4a63SDavid du Colombier n++;
4228ccd4a63SDavid du Colombier }
4238ccd4a63SDavid du Colombier *p-- = conv[i];
4248ccd4a63SDavid du Colombier n++;
4258ccd4a63SDavid du Colombier }
4268ccd4a63SDavid du Colombier }
4278ccd4a63SDavid du Colombier if(n == 0){
4288ccd4a63SDavid du Colombier *p-- = '0';
4298ccd4a63SDavid du Colombier n = 1;
4308ccd4a63SDavid du Colombier }
4318ccd4a63SDavid du Colombier for(w = f->prec; n < w && p > buf+3; n++)
4328ccd4a63SDavid du Colombier *p-- = '0';
4338ccd4a63SDavid du Colombier if(neg || (fl & (FmtSign|FmtSpace)))
4348ccd4a63SDavid du Colombier n++;
4358ccd4a63SDavid du Colombier if(fl & FmtSharp){
4368ccd4a63SDavid du Colombier if(base == 16)
4378ccd4a63SDavid du Colombier n += 2;
4388ccd4a63SDavid du Colombier else if(base == 8){
4398ccd4a63SDavid du Colombier if(p[1] == '0')
4408ccd4a63SDavid du Colombier fl &= ~FmtSharp;
4418ccd4a63SDavid du Colombier else
4428ccd4a63SDavid du Colombier n++;
4438ccd4a63SDavid du Colombier }
4448ccd4a63SDavid du Colombier }
4450d601874SDavid du Colombier if((fl & FmtZero) && !(fl & (FmtLeft|FmtPrec))){
4468ccd4a63SDavid du Colombier for(w = f->width; n < w && p > buf+3; n++)
4478ccd4a63SDavid du Colombier *p-- = '0';
4488ccd4a63SDavid du Colombier f->width = 0;
4498ccd4a63SDavid du Colombier }
4508ccd4a63SDavid du Colombier if(fl & FmtSharp){
4518ccd4a63SDavid du Colombier if(base == 16)
4528ccd4a63SDavid du Colombier *p-- = f->r;
4538ccd4a63SDavid du Colombier if(base == 16 || base == 8)
4548ccd4a63SDavid du Colombier *p-- = '0';
4558ccd4a63SDavid du Colombier }
4568ccd4a63SDavid du Colombier if(neg)
4578ccd4a63SDavid du Colombier *p-- = '-';
4588ccd4a63SDavid du Colombier else if(fl & FmtSign)
4598ccd4a63SDavid du Colombier *p-- = '+';
4608ccd4a63SDavid du Colombier else if(fl & FmtSpace)
4618ccd4a63SDavid du Colombier *p-- = ' ';
4628ccd4a63SDavid du Colombier f->flags &= ~FmtPrec;
4630d601874SDavid du Colombier return __fmtcpy(f, p + 1, n, n);
4648ccd4a63SDavid du Colombier }
4658ccd4a63SDavid du Colombier
4668ccd4a63SDavid du Colombier int
__countfmt(Fmt * f)4670d601874SDavid du Colombier __countfmt(Fmt *f)
4688ccd4a63SDavid du Colombier {
4698ccd4a63SDavid du Colombier void *p;
4708ccd4a63SDavid du Colombier ulong fl;
4718ccd4a63SDavid du Colombier
4728ccd4a63SDavid du Colombier fl = f->flags;
4738ccd4a63SDavid du Colombier p = va_arg(f->args, void*);
4748ccd4a63SDavid du Colombier if(fl & FmtVLong){
4758ccd4a63SDavid du Colombier *(vlong*)p = f->nfmt;
4768ccd4a63SDavid du Colombier }else if(fl & FmtLong){
4778ccd4a63SDavid du Colombier *(long*)p = f->nfmt;
4788ccd4a63SDavid du Colombier }else if(fl & FmtByte){
4798ccd4a63SDavid du Colombier *(char*)p = f->nfmt;
4808ccd4a63SDavid du Colombier }else if(fl & FmtShort){
4818ccd4a63SDavid du Colombier *(short*)p = f->nfmt;
4828ccd4a63SDavid du Colombier }else{
4838ccd4a63SDavid du Colombier *(int*)p = f->nfmt;
4848ccd4a63SDavid du Colombier }
4858ccd4a63SDavid du Colombier return 0;
4868ccd4a63SDavid du Colombier }
4878ccd4a63SDavid du Colombier
4888ccd4a63SDavid du Colombier int
__flagfmt(Fmt * f)4890d601874SDavid du Colombier __flagfmt(Fmt *f)
4908ccd4a63SDavid du Colombier {
4918ccd4a63SDavid du Colombier switch(f->r){
4928ccd4a63SDavid du Colombier case ',':
4938ccd4a63SDavid du Colombier f->flags |= FmtComma;
4948ccd4a63SDavid du Colombier break;
4958ccd4a63SDavid du Colombier case '-':
4968ccd4a63SDavid du Colombier f->flags |= FmtLeft;
4978ccd4a63SDavid du Colombier break;
4988ccd4a63SDavid du Colombier case '+':
4998ccd4a63SDavid du Colombier f->flags |= FmtSign;
5008ccd4a63SDavid du Colombier break;
5018ccd4a63SDavid du Colombier case '#':
5028ccd4a63SDavid du Colombier f->flags |= FmtSharp;
5038ccd4a63SDavid du Colombier break;
5048ccd4a63SDavid du Colombier case ' ':
5058ccd4a63SDavid du Colombier f->flags |= FmtSpace;
5068ccd4a63SDavid du Colombier break;
5078ccd4a63SDavid du Colombier case 'u':
5088ccd4a63SDavid du Colombier f->flags |= FmtUnsigned;
5098ccd4a63SDavid du Colombier break;
5108ccd4a63SDavid du Colombier case 'h':
5118ccd4a63SDavid du Colombier if(f->flags & FmtShort)
5128ccd4a63SDavid du Colombier f->flags |= FmtByte;
5138ccd4a63SDavid du Colombier f->flags |= FmtShort;
5148ccd4a63SDavid du Colombier break;
5150d601874SDavid du Colombier case 'L':
5160d601874SDavid du Colombier f->flags |= FmtLDouble;
5170d601874SDavid du Colombier break;
5188ccd4a63SDavid du Colombier case 'l':
5198ccd4a63SDavid du Colombier if(f->flags & FmtLong)
5208ccd4a63SDavid du Colombier f->flags |= FmtVLong;
5218ccd4a63SDavid du Colombier f->flags |= FmtLong;
5228ccd4a63SDavid du Colombier break;
5238ccd4a63SDavid du Colombier }
5248ccd4a63SDavid du Colombier return 1;
5258ccd4a63SDavid du Colombier }
5268ccd4a63SDavid du Colombier
5278ccd4a63SDavid du Colombier /* default error format */
5288ccd4a63SDavid du Colombier int
__badfmt(Fmt * f)5290d601874SDavid du Colombier __badfmt(Fmt *f)
5308ccd4a63SDavid du Colombier {
5318ccd4a63SDavid du Colombier char x[3];
5328ccd4a63SDavid du Colombier
5338ccd4a63SDavid du Colombier x[0] = '%';
5348ccd4a63SDavid du Colombier x[1] = f->r;
5358ccd4a63SDavid du Colombier x[2] = '%';
5368ccd4a63SDavid du Colombier f->prec = 3;
5370d601874SDavid du Colombier __fmtcpy(f, (const void*)x, 3, 3);
5388ccd4a63SDavid du Colombier return 0;
5398ccd4a63SDavid du Colombier }
540