scc

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

commit 070569b2fee195711c81d5013e12d637d5593772
parent edc51eccc352411550ae1b40e84eb6da8bf3ab3a
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Tue,  8 Nov 2022 18:59:25 +0100

libc/stdio: Fix and simplify precision in printf()

After the last changes precision in strings was not correctly
handled. Adding a new flag indicating when the precision
value was set simplified several of the cases. Also, the case
of a precision with value 0 is handled correctly.

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

diff --git a/src/libc/stdio/vfprintf.c b/src/libc/stdio/vfprintf.c @@ -77,9 +77,6 @@ numtostr(uintmax_t val, int flags, struct conv *conv, char *buf) int base = conv->base, prec = conv->prec; uintmax_t oval = val; - if (prec == SIZE_MAX) - prec = 1; - for (*buf = '\0'; val > 0; val /= base) *--buf = conv->digs[val % base]; @@ -203,7 +200,7 @@ strout(char *s, size_t len, int width, int fill, FILE *restrict fp) int vfprintf(FILE *restrict fp, const char *restrict fmt, va_list va) { - int ch, n, flags, width, left, fill; + int ch, n, flags, width, left, fill, prec; size_t inc, len, cnt = 0; char *s; wchar_t *ws; @@ -221,8 +218,8 @@ vfprintf(FILE *restrict fp, const char *restrict fmt, va_list va) } fill = ' '; - left = flags = width = 0; - conv.prec = SIZE_MAX; + prec = left = flags = width = 0; + conv.prec = 0; conv.base = 10; conv.sign = '\0'; conv.digs = "0123456789ABCDEFX"; @@ -247,8 +244,10 @@ flags: for (n = 0; isdigit(ch = *fmt); fmt++) n = n * 10 + ch - '0'; } - if (n >= 0) + if (n >= 0) { conv.prec = n; + prec = 1; + } goto flags; case '*': width = va_arg(va2, int); @@ -327,11 +326,8 @@ flags: conv.base = 8; flags |= UNSIGNED; numeric: - if (conv.prec != SIZE_MAX) { - if (conv.prec > MAXPREC) - conv.prec = MAXPREC; - fill = ' '; - } + if (conv.prec > MAXPREC) + conv.prec = MAXPREC; s = numtostr(getnum(&va2, flags, &conv.sign), flags, &conv, @@ -349,12 +345,17 @@ flags: /* TODO */ break; case 's': - len = conv.prec; if (flags & LONG) { ws = va_arg(va2, wchar_t *); + len = wcslen(ws); + if (prec && len > conv.prec) + len = conv.prec; goto wstrout; } else { s = va_arg(va2, char *); + len = strlen(s); + if (prec && len > conv.prec) + len = conv.prec; goto strout; } wstrout: