summaryrefslogtreecommitdiff
path: root/lib/vasnprintf.c
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2023-03-22 21:43:23 +0100
committerBruno Haible <bruno@clisp.org>2023-03-22 21:43:23 +0100
commitf61570c0ef38744c93865172dcbac80e7d4e7b23 (patch)
tree969f281aa83d72113adc702bcba758e3f155a6c3 /lib/vasnprintf.c
parent806d6f857009f0920b74405004a8ea42b4adb23d (diff)
downloadgnulib-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.c32
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++)