*printf-posix: ISO C 23: Add %b directive for binary output of integers

2023-03-17 Thread Bruno Haible
This set of patches adds support for the %b format string directive, required
by ISO C 23, to the *printf family of functions.

So far, only glibc implements it (since version 2.35). For portability to the
other platforms, use the *printf-posix modules.


2023-03-17  Bruno Haible  

*printf-posix: ISO C 23: Add %b directive for binary output of integers.
* lib/printf-parse.c (PRINTF_PARSE): Recognize the 'b' directive.
* lib/printf-parse.h: Update comment.
* lib/wprintf-parse.h: Likewise.
* lib/vasnprintf.c (MAX_ROOM_NEEDED, VASNPRINTF): Add support for the
'b' directive.
* m4/printf.m4 (gl_PRINTF_DIRECTIVE_B): New macro.
* m4/vasnprintf.m4 (gl_PREREQ_VASNPRINTF_DIRECTIVE_B): New macro.
(gl_PREREQ_VASNPRINTF_WITH_EXTRAS): Invoke it.
* m4/vasnwprintf-posix.m4 (gl_FUNC_VASNWPRINTF_POSIX): Invoke
gl_PREREQ_VASNPRINTF_DIRECTIVE_B.
* m4/dprintf-posix.m4 (gl_FUNC_DPRINTF_POSIX): Require
gl_PRINTF_DIRECTIVE_B and test its result. Invoke
gl_PREREQ_VASNPRINTF_DIRECTIVE_B.
* m4/fprintf-posix.m4 (gl_FUNC_FPRINTF_POSIX): Likewise.
* m4/obstack-printf-posix.m4 (gl_FUNC_OBSTACK_PRINTF_POSIX): Likewise.
* m4/snprintf-posix.m4 (gl_FUNC_SNPRINTF_POSIX): Likewise.
* m4/sprintf-posix.m4 (gl_FUNC_SPRINTF_POSIX): Likewise.
* m4/vasnprintf-posix.m4 (gl_FUNC_VASNPRINTF_POSIX): Likewise.
* m4/vasprintf-posix.m4 (gl_FUNC_VASPRINTF_POSIX): Likewise.
* m4/vdprintf-posix.m4 (gl_FUNC_VDPRINTF_POSIX): Likewise.
* m4/vfprintf-posix.m4 (gl_FUNC_VFPRINTF_POSIX): Likewise.
* m4/vsnprintf-posix.m4 (gl_FUNC_VSNPRINTF_POSIX): Likewise.
* m4/vsprintf-posix.m4 (gl_FUNC_VSPRINTF_POSIX): Likewise.
* tests/test-snprintf-posix.h (test_function): Add some tests of 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.
* doc/glibc-functions/asprintf.texi: Mention the 'b' directive.
* doc/glibc-functions/obstack_printf.texi: Likewise.
* doc/glibc-functions/obstack_vprintf.texi: Likewise.
* doc/glibc-functions/vasprintf.texi: Likewise.
* doc/posix-functions/dprintf.texi: Likewise.
* doc/posix-functions/fprintf.texi: Likewise.
* doc/posix-functions/fwprintf.texi: Likewise.
* doc/posix-functions/printf.texi: Likewise.
* doc/posix-functions/snprintf.texi: Likewise.
* doc/posix-functions/sprintf.texi: Likewise.
* doc/posix-functions/swprintf.texi: Likewise.
* doc/posix-functions/vdprintf.texi: Likewise.
* doc/posix-functions/vfprintf.texi: Likewise.
* doc/posix-functions/vfwprintf.texi: Likewise.
* doc/posix-functions/vprintf.texi: Likewise.
* doc/posix-functions/vsnprintf.texi: Likewise.
* doc/posix-functions/vsprintf.texi: Likewise.
* doc/posix-functions/vswprintf.texi: Likewise.
* doc/posix-functions/vwprintf.texi: Likewise.
* doc/posix-functions/wprintf.texi: Likewise.

2023-03-17  Bruno Haible  

vasnprintf, vasnwprintf: Simplify code.
* lib/vasnprintf.c (MAX_ROOM_NEEDED): Remove dead code: The directives
'o', 'x', 'X' always take an unsigned integer argument.

>From 21ed6e8365e371b9088df727d0449133df58e9bc Mon Sep 17 00:00:00 2001
From: Bruno Haible 
Date: Fri, 17 Mar 2023 22:33:24 +0100
Subject: [PATCH 1/2] vasnprintf, vasnwprintf: Simplify code.

* lib/vasnprintf.c (MAX_ROOM_NEEDED): Remove dead code: The directives
'o', 'x', 'X' always take an unsigned integer argument.
---
 ChangeLog|  6 ++
 lib/vasnprintf.c | 10 +-
 2 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 8318d7f6fc..62dd39e17f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2023-03-17  Bruno Haible  
+
+	vasnprintf, vasnwprintf: Simplify code.
+	* lib/vasnprintf.c (MAX_ROOM_NEEDED): Remove dead code: The directives
+	'o', 'x', 'X' always take an unsigned integer argument.
+
 2023-03-17  Bruno Haible  
 
 	vasnwprintf: Fix test failure on OpenBSD.
diff --git a/lib/vasnprintf.c b/lib/vasnprintf.c
index 74a6712926..a49eb1dcd7 100644
--- a/lib/vasnprintf.c
+++ b/lib/vasnprintf.c
@@ -1654,13 +1654,13 @@ MAX_ROOM_NEEDED (const arguments *ap, size_t arg_index, FCHAR_T conversion,
   break;
 
 case 'o':
-  if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
+  if (type == TYPE_ULONGLONGINT)
 tmp_length =
   (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
   * 0.34 /* binary -> octal */
  

Re: *printf-posix: ISO C 23: Add %b directive for binary output of integers

2023-03-18 Thread Pádraig Brady

On 17/03/2023 21:51, Bruno Haible wrote:

This set of patches adds support for the %b format string directive, required
by ISO C 23, to the *printf family of functions.

So far, only glibc implements it (since version 2.35). For portability to the
other platforms, use the *printf-posix modules.


For my reference mainly...

It's interesting that this conflicts with the POSIX specified %b directive
for the printf(1) utility.

cheers,
Pádraig




Re: *printf-posix: ISO C 23: Add %b directive for binary output of integers

2023-03-18 Thread Eric Blake
On Sat, Mar 18, 2023 at 11:50:47AM +, Pádraig Brady wrote:
> On 17/03/2023 21:51, Bruno Haible wrote:
> > This set of patches adds support for the %b format string directive, 
> > required
> > by ISO C 23, to the *printf family of functions.
> > 
> > So far, only glibc implements it (since version 2.35). For portability to 
> > the
> > other platforms, use the *printf-posix modules.
> 
> For my reference mainly...
> 
> It's interesting that this conflicts with the POSIX specified %b directive
> for the printf(1) utility.

Another consideration: C23 admits that %#B is not available for
portable use of outputting uppercase '0B...', you would have to
manually write 0B%b instead.  However, since glibc DOES support %B as
the uppercase counterpart to %b, should we add that in gnulib (but
this time under the auspices of *printf-gnu, rather than
*printf-posix)?

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




Re: *printf-posix: ISO C 23: Add %b directive for binary output of integers

2023-03-22 Thread Bruno Haible
Some details of the %b implementation that I added on 2023-03-17 were incorrect.
This patch fixes them, while adding new unit tests.


2023-03-22  Bruno Haible  

*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.

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)
@@ -,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++)
diff --git a/modules/vasnwprintf-posix-tests b/modules/vasnwprintf-posix-tests
index 667eb61103..6354e79f75 100644
--- a/modules/vasnwprintf-posix-tests
+++ b/modules/vasnwprintf-posix-tests
@@ -7,6 +7,7 @@ tests/minus-zero.h
 tests/infinity.h
 tests/nan.h
 tests/macros.h
+m4/musl.m4
 m4/locale-fr.m4
 m4/codeset.m4
 
@@ -21,6 +22,7 @@ wmemcpy
 
 configure.ac:
 AC_REQUIRE([gl_LONG_DOUBLE_VS_DOUBLE])
+gl_MUSL_LIBC
 gt_LOCALE_FR
 gt_LOCALE_FR_UTF8
 
diff --git a/tests/test-snprintf-posix.h b/tests/test-snprintf-posix.h
index 05c7be8059..a8993f947a 100644
--- a/tests/test-snprintf-posix.h
+++ b/tests/test-snprintf-posix.h
@@ -3091,6 +3091,190 @@ test_function (int (*my_snprintf) (char *, size_t, 
const char *, ...))
   }
 #endif
 
+  /* Test the support of the 'x' conversion specifier for hexadecimal output of
+ integers.  */
+
+  { /* Zero.  */
+int retval =
+  my_snprintf (result, sizeof (result), "%x %d", 0, 33, 44, 55);
+ASSERT (strcmp (result, "0 33") == 0);
+ASSERT (retval