scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

commit 7460e0903f9899f56cfb3ca8a2ee0d9076fcefba
parent 34c5c3dab36218a94b20dc087fbcc1958ec4c719
Author: Roberto E. Vargas Caballero <roberto.vargas@midokura.com>
Date:   Tue, 16 Aug 2022 15:35:46 +0200

libc: Fix "printf" precision handling

The original fix to handle negative precision values was wrong,
using signed/unsigned conversions.

Instead, keep the original parsed value,
and only apply conversion-specific behavior before printing.

Diffstat:
Msrc/libc/stdio/vfprintf.c | 30+++++++++++++++---------------
1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/src/libc/stdio/vfprintf.c b/src/libc/stdio/vfprintf.c @@ -151,15 +151,16 @@ static size_t strout(char *s, size_t len, int width, int fill, FILE *restrict fp) { int left = 0, adjust, ch, prefix; - size_t cnt = 0; + size_t cnt; if (width < 0) { left = 1; width = -width; } - adjust = (len > 0 && len < width) ? width - len : 0; + adjust = len < width ? width - len : 0; cnt = adjust + len; + if (left) adjust = -adjust; @@ -179,13 +180,8 @@ strout(char *s, size_t len, int width, int fill, FILE *restrict fp) for ( ; adjust > 0; adjust--) putc(fill, fp); - if (len == -1) { - for (cnt = 0; ch = *s++; ++cnt) - putc(ch, fp); - } else { - while (len-- > 0 && (ch = *s++)) - putc(ch, fp); - } + for ( ; len-- > 0 && (ch = *s) != '\0'; ++s) + putc(ch, fp); for ( ; adjust < 0; adjust++) putc(' ', fp); @@ -240,11 +236,8 @@ flags: for (n = 0; isdigit(ch = *fmt); fmt++) n = n * 10 + ch - '0'; } - if (n < 0) - n = 0; - if (n > MAXPREC) - n = MAXPREC; - conv.prec = n; + if (n >= 0) + conv.prec = n; goto flags; case '*': width = va_arg(va2, int); @@ -323,8 +316,11 @@ flags: conv.base = 8; flags |= UNSIGNED; numeric: - if (conv.prec != -1) + if (conv.prec != -1) { + if (conv.prec > MAXPREC) + conv.prec = MAXPREC; fill = ' '; + } s = numtostr(getnum(&va2, flags, &conv.sign), flags, &conv, @@ -347,6 +343,10 @@ flags: /* len = wcsnlen(ws, conv.prec); */ goto wstrout; } else { + if (conv.prec != -1) + len = conv.prec; + else + len = SIZE_MAX; s = va_arg(va2, char *); if ((len = strlen(s)) > conv.prec) len = conv.prec;