diff options
author | Bruno Haible <bruno@clisp.org> | 2023-03-22 21:43:23 +0100 |
---|---|---|
committer | Bruno Haible <bruno@clisp.org> | 2023-03-22 21:43:23 +0100 |
commit | f61570c0ef38744c93865172dcbac80e7d4e7b23 (patch) | |
tree | 969f281aa83d72113adc702bcba758e3f155a6c3 /lib/vasnprintf.c | |
parent | 806d6f857009f0920b74405004a8ea42b4adb23d (diff) | |
download | gnulib-f61570c0ef38744c93865172dcbac80e7d4e7b23.tar.gz |
*printf-posix: Fix implementation of %b directive.
* lib/vasnprintf.c (VASNPRINTF): In the %b directive implementation, fix
the precision handling, and ignore the '0' flag when a width and a
precision are both present.
* tests/test-snprintf-posix.h (test_function): Add test cases for the %x
directive and more test cases for the %b directive.
* tests/test-sprintf-posix.h (test_function): Likewise.
* tests/test-vasnprintf-posix.c (test_function): Likewise.
* tests/test-vasnwprintf-posix.c (test_function): Likewise.
* tests/test-vasprintf-posix.c (test_function): Likewise.
* modules/vasnwprintf-posix-tests (Files): Add m4/musl.m4.
(configure.ac): Invoke gl_MUSL_LIBC.
Diffstat (limited to 'lib/vasnprintf.c')
-rw-r--r-- | lib/vasnprintf.c | 32 |
1 files changed, 26 insertions, 6 deletions
diff --git a/lib/vasnprintf.c b/lib/vasnprintf.c index 5cd52b5b6e..248444ca23 100644 --- a/lib/vasnprintf.c +++ b/lib/vasnprintf.c @@ -3217,6 +3217,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, { arg_type type = a.arg[dp->arg_index].type; int flags = dp->flags; + int has_width; size_t width; int has_precision; size_t precision; @@ -3229,6 +3230,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, DCHAR_T *pad_ptr; DCHAR_T *p; + has_width = 0; width = 0; if (dp->width_start != dp->width_end) { @@ -3256,10 +3258,11 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, width = xsum (xtimes (width, 10), *digitp++ - '0'); while (digitp != dp->width_end); } + has_width = 1; } has_precision = 0; - precision = 0; + precision = 1; if (dp->precision_start != dp->precision_end) { if (dp->precision_arg_index != ARG_NONE) @@ -3333,12 +3336,24 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, int need_prefix = ((flags & FLAG_ALT) && arg != 0); p = tmp_end; - do + /* "The result of converting a zero value with a precision + of zero is no characters." */ + if (!(has_precision && precision == 0 && arg == 0)) + { + do + { + *--p = '0' + (arg & 1); + arg = arg >> 1; + } + while (arg != 0); + } + + if (has_precision) { - *--p = '0' + (arg & 1); - arg = arg >> 1; + DCHAR_T *digits_start = tmp_end - precision; + while (p > digits_start) + *--p = '0'; } - while (arg != 0); pad_ptr = p; @@ -3365,7 +3380,12 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, for (p = tmp_end - pad; p < tmp_end; p++) *p = ' '; } - else if (flags & FLAG_ZERO) + else if ((flags & FLAG_ZERO) + /* Neither ISO C nor POSIX specify that the '0' + flag is ignored when a width and a precision + are both present. But most implementations + do so. */ + && !(has_width && has_precision)) { /* Pad with zeroes. */ for (p = tmp_start; p < pad_ptr; p++) |