Change fmt to preserve width, flags, and precision, and change the logic of fmt[v]print appropriately. That __fmtdispatch discards the flags of the Fmt structure it receives, is broken behaviour. I see no present code in sources that relies on this behaviour, and I have been running my Plan 9 boxes with these changes for a while (having rebuilt the whole source tree and kernel). Moreover, the Go compilers [568]g rely on the preservation of flags. Reference: /n/sources/patch/applied/fmt-preserve Date: Tue Apr 24 23:02:34 CES 2012 Signed-off-by: akumar@mail.nanosouffle.net --- /sys/src/libc/fmt/fmt.c Tue Apr 24 22:19:21 2012 +++ /sys/src/libc/fmt/fmt.c Tue Apr 24 22:19:18 2012 @@ -124,7 +124,13 @@ _fmtdispatch(Fmt *f, void *fmt, int isrunes) { Rune rune, r; - int i, n; + int i, n, w, p; + ulong fl; + void *ret; + + w = f->width; + p = f->prec; + fl = f->flags; f->flags = 0; f->width = f->prec = 0; @@ -140,7 +146,8 @@ f->r = r; switch(r){ case '\0': - return nil; + ret = nil; + goto end; case '.': f->flags |= FmtWidth|FmtPrec; continue; @@ -194,9 +201,18 @@ goto numflag; } n = (*fmtfmt(r))(f); - if(n < 0) - return nil; - if(n == 0) - return fmt; + if(n < 0){ + ret = nil; + break; + } + if(n == 0){ + ret = fmt; + break; + } } +end: + f->width = w; + f->prec = p; + f->flags = fl; + return ret; } --- /sys/src/libc/fmt/fmtprint.c Tue Apr 24 22:19:25 2012 +++ /sys/src/libc/fmt/fmtprint.c Tue Apr 24 22:19:22 2012 @@ -5,8 +5,7 @@ /* * format a string into the output buffer - * designed for formats which themselves call fmt, - * but ignore any width flags + * designed for formats which themselves call fmt */ int fmtprint(Fmt *f, char *fmt, ...) @@ -14,19 +13,9 @@ va_list va; int n; - f->flags = 0; - f->width = 0; - f->prec = 0; - va = f->args; - va_start(f->args, fmt); - n = dofmt(f, fmt); - va_end(f->args); - f->flags = 0; - f->width = 0; - f->prec = 0; - f->args = va; - if(n >= 0) - return 0; + va_start(va, fmt); + n = fmtvprint(f, fmt, va); + va_end(va); return n; } --- /sys/src/libc/fmt/fmtvprint.c Tue Apr 24 22:19:29 2012 +++ /sys/src/libc/fmt/fmtvprint.c Tue Apr 24 22:19:26 2012 @@ -5,8 +5,7 @@ /* * format a string into the output buffer - * designed for formats which themselves call fmt, - * but ignore any width flags + * designed for formats which themselves call fmt */ int fmtvprint(Fmt *f, char *fmt, va_list args) @@ -14,15 +13,9 @@ va_list va; int n; - f->flags = 0; - f->width = 0; - f->prec = 0; va = f->args; f->args = args; n = dofmt(f, fmt); - f->flags = 0; - f->width = 0; - f->prec = 0; f->args = va; if(n >= 0) return 0; --- /sys/src/ape/lib/fmt/fmt.c Tue Apr 24 22:19:33 2012 +++ /sys/src/ape/lib/fmt/fmt.c Tue Apr 24 22:19:31 2012 @@ -143,7 +143,13 @@ __fmtdispatch(Fmt *f, void *fmt, int isrunes) { Rune rune, r; - int i, n; + int i, n, w, p; + ulong fl; + void *ret; + + w = f->width; + p = f->prec; + fl = f->flags; f->flags = 0; f->width = f->prec = 0; @@ -159,7 +165,8 @@ f->r = r; switch(r){ case '\0': - return nil; + ret = nil; + goto end; case '.': f->flags |= FmtWidth|FmtPrec; continue; @@ -213,9 +220,18 @@ goto numflag; } n = (*fmtfmt(r))(f); - if(n < 0) - return nil; - if(n == 0) - return fmt; + if(n < 0){ + ret = nil; + break; + } + if(n == 0){ + ret = fmt; + break; + } } +end: + f->width = w; + f->prec = p; + f->flags = fl; + return ret; } --- /sys/src/ape/lib/fmt/fmtprint.c Tue Apr 24 22:19:38 2012 +++ /sys/src/ape/lib/fmt/fmtprint.c Tue Apr 24 22:19:35 2012 @@ -20,8 +20,7 @@ /* * format a string into the output buffer - * designed for formats which themselves call fmt, - * but ignore any width flags + * designed for formats which themselves call fmt */ int fmtprint(Fmt *f, char *fmt, ...) @@ -29,19 +28,9 @@ va_list va; int n; - f->flags = 0; - f->width = 0; - f->prec = 0; - va = f->args; va_start(f->args, fmt); - n = dofmt(f, fmt); + n = fmtvprint(f, fmt, va); va_end(f->args); - f->flags = 0; - f->width = 0; - f->prec = 0; - f->args = va; - if(n >= 0) - return 0; return n; } --- /sys/src/ape/lib/fmt/fmtvprint.c Tue Apr 24 22:19:44 2012 +++ /sys/src/ape/lib/fmt/fmtvprint.c Tue Apr 24 22:19:41 2012 @@ -20,8 +20,7 @@ /* * format a string into the output buffer - * designed for formats which themselves call fmt, - * but ignore any width flags + * designed for formats which themselves call fmt */ int fmtvprint(Fmt *f, char *fmt, va_list args) @@ -29,15 +28,9 @@ va_list va; int n; - f->flags = 0; - f->width = 0; - f->prec = 0; va = f->args; f->args = args; n = dofmt(f, fmt); - f->flags = 0; - f->width = 0; - f->prec = 0; f->args = va; if(n >= 0) return 0; --- /sys/man/2/fmtinstall Tue Apr 24 22:19:48 2012 +++ /sys/man/2/fmtinstall Tue Apr 24 22:19:46 2012 @@ -266,7 +266,7 @@ .IR fmtvprint may be called to help prepare output in custom conversion routines. -However, these functions clear the width, precision, and flags. +These functions will preserve width, precision, and flags. Both functions return 0 for success and \-1 for failure. .PP The functions