mailing list of musl libc
 help / color / mirror / code / Atom feed
* [musl] [PATCH] vfprintf: support C2x %b and %B conversion specifiers
@ 2022-09-08 16:36 Gabriel Ravier
  2022-09-12 13:59 ` Rich Felker
  0 siblings, 1 reply; 17+ messages in thread
From: Gabriel Ravier @ 2022-09-08 16:36 UTC (permalink / raw)
  To: gravier, musl; +Cc: Gabriel Ravier

These specifiers allow for formatted input/output of binary integers,
and have been added to C2x with N2630. The uppercase B specifier is
not formally required by C2x, as only lowercase specifiers were
reserved by C, and thus an implementation could have been using
uppercase B for an extension of their own, but C2x still has a note
saying that it is recommended practice to implement it as the logical
counterpart to b.

I have tested this on:
- glibc's tests for %b and %B
- The libc testsuite I'm developing over at https://github.com/GabrielRavier/yalibct
- musl's libc-test
- musl's libc-testsuite

and observed no regressions.
---
 src/stdio/vfprintf.c | 21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c
index 9b961e7f..89426b72 100644
--- a/src/stdio/vfprintf.c
+++ b/src/stdio/vfprintf.c
@@ -49,7 +49,7 @@ enum {
 static const unsigned char states[]['z'-'A'+1] = {
 	{ /* 0: bare types */
 		S('d') = INT, S('i') = INT,
-		S('o') = UINT, S('u') = UINT, S('x') = UINT, S('X') = UINT,
+		S('o') = UINT, S('u') = UINT, S('x') = UINT, S('X') = UINT, S('b') = UINT, S('B') = UINT,
 		S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL,
 		S('E') = DBL, S('F') = DBL, S('G') = DBL, S('A') = DBL,
 		S('c') = CHAR, S('C') = INT,
@@ -59,7 +59,7 @@ static const unsigned char states[]['z'-'A'+1] = {
 		S('z') = ZTPRE, S('j') = JPRE, S('t') = ZTPRE,
 	}, { /* 1: l-prefixed */
 		S('d') = LONG, S('i') = LONG,
-		S('o') = ULONG, S('u') = ULONG, S('x') = ULONG, S('X') = ULONG,
+		S('o') = ULONG, S('u') = ULONG, S('x') = ULONG, S('X') = ULONG, S('b') = ULONG, S('B') = ULONG,
 		S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL,
 		S('E') = DBL, S('F') = DBL, S('G') = DBL, S('A') = DBL,
 		S('c') = INT, S('s') = PTR, S('n') = PTR,
@@ -68,17 +68,20 @@ static const unsigned char states[]['z'-'A'+1] = {
 		S('d') = LLONG, S('i') = LLONG,
 		S('o') = ULLONG, S('u') = ULLONG,
 		S('x') = ULLONG, S('X') = ULLONG,
+		S('b') = ULLONG, S('B') = ULLONG,
 		S('n') = PTR,
 	}, { /* 3: h-prefixed */
 		S('d') = SHORT, S('i') = SHORT,
 		S('o') = USHORT, S('u') = USHORT,
 		S('x') = USHORT, S('X') = USHORT,
+		S('b') = USHORT, S('B') = USHORT,
 		S('n') = PTR,
 		S('h') = HHPRE,
 	}, { /* 4: hh-prefixed */
 		S('d') = CHAR, S('i') = CHAR,
 		S('o') = UCHAR, S('u') = UCHAR,
 		S('x') = UCHAR, S('X') = UCHAR,
+		S('b') = UCHAR, S('B') = UCHAR,
 		S('n') = PTR,
 	}, { /* 5: L-prefixed */
 		S('e') = LDBL, S('f') = LDBL, S('g') = LDBL, S('a') = LDBL,
@@ -88,11 +91,13 @@ static const unsigned char states[]['z'-'A'+1] = {
 		S('d') = PDIFF, S('i') = PDIFF,
 		S('o') = SIZET, S('u') = SIZET,
 		S('x') = SIZET, S('X') = SIZET,
+		S('b') = SIZET, S('B') = SIZET,
 		S('n') = PTR,
 	}, { /* 7: j-prefixed */
 		S('d') = IMAX, S('i') = IMAX,
 		S('o') = UMAX, S('u') = UMAX,
 		S('x') = UMAX, S('X') = UMAX,
+		S('b') = UMAX, S('B') = UMAX,
 		S('n') = PTR,
 	}
 };
@@ -162,6 +167,12 @@ static char *fmt_o(uintmax_t x, char *s)
 	return s;
 }
 
+static char *fmt_b(uintmax_t x, char *s)
+{
+	for (; x; x>>=1) *--s = '0' + (x&1);
+	return s;
+}
+
 static char *fmt_u(uintmax_t x, char *s)
 {
 	unsigned long y;
@@ -529,7 +540,7 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
 		if (!f) continue;
 
 		z = buf + sizeof(buf);
-		prefix = "-+   0X0x";
+		prefix = "-+   0X0x0B0b";
 		pl = 0;
 		t = s[-1];
 
@@ -559,6 +570,10 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
 			a = fmt_x(arg.i, z, t&32);
 			if (arg.i && (fl & ALT_FORM)) prefix+=(t>>4), pl=2;
 			if (0) {
+		case 'b': case 'B':
+			a = fmt_b(arg.i, z);
+			if (arg.i && (fl & ALT_FORM)) prefix += 9 + ((t == 'b') << 1), pl=2;
+			} if (0) {
 		case 'o':
 			a = fmt_o(arg.i, z);
 			if ((fl&ALT_FORM) && p<z-a+1) p=z-a+1;
-- 
2.37.3


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [musl] [PATCH] vfprintf: support C2x %b and %B conversion specifiers
  2022-09-08 16:36 [musl] [PATCH] vfprintf: support C2x %b and %B conversion specifiers Gabriel Ravier
@ 2022-09-12 13:59 ` Rich Felker
  2022-09-12 14:42   ` Jₑₙₛ Gustedt
  0 siblings, 1 reply; 17+ messages in thread
From: Rich Felker @ 2022-09-12 13:59 UTC (permalink / raw)
  To: Gabriel Ravier; +Cc: gravier, musl

On Thu, Sep 08, 2022 at 06:36:49PM +0200, Gabriel Ravier wrote:
> These specifiers allow for formatted input/output of binary integers,
> and have been added to C2x with N2630. The uppercase B specifier is
> not formally required by C2x, as only lowercase specifiers were
> reserved by C, and thus an implementation could have been using
> uppercase B for an extension of their own, but C2x still has a note
> saying that it is recommended practice to implement it as the logical
> counterpart to b.
> 
> I have tested this on:
> - glibc's tests for %b and %B
> - The libc testsuite I'm developing over at https://github.com/GabrielRavier/yalibct
> - musl's libc-test
> - musl's libc-testsuite
> 
> and observed no regressions.
> ---
>  src/stdio/vfprintf.c | 21 ++++++++++++++++++---
>  1 file changed, 18 insertions(+), 3 deletions(-)
> 
> diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c
> index 9b961e7f..89426b72 100644
> --- a/src/stdio/vfprintf.c
> +++ b/src/stdio/vfprintf.c
> @@ -49,7 +49,7 @@ enum {
>  static const unsigned char states[]['z'-'A'+1] = {
>  	{ /* 0: bare types */
>  		S('d') = INT, S('i') = INT,
> -		S('o') = UINT, S('u') = UINT, S('x') = UINT, S('X') = UINT,
> +		S('o') = UINT, S('u') = UINT, S('x') = UINT, S('X') = UINT, S('b') = UINT, S('B') = UINT,
>  		S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL,
>  		S('E') = DBL, S('F') = DBL, S('G') = DBL, S('A') = DBL,
>  		S('c') = CHAR, S('C') = INT,
> @@ -59,7 +59,7 @@ static const unsigned char states[]['z'-'A'+1] = {
>  		S('z') = ZTPRE, S('j') = JPRE, S('t') = ZTPRE,
>  	}, { /* 1: l-prefixed */
>  		S('d') = LONG, S('i') = LONG,
> -		S('o') = ULONG, S('u') = ULONG, S('x') = ULONG, S('X') = ULONG,
> +		S('o') = ULONG, S('u') = ULONG, S('x') = ULONG, S('X') = ULONG, S('b') = ULONG, S('B') = ULONG,
>  		S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL,
>  		S('E') = DBL, S('F') = DBL, S('G') = DBL, S('A') = DBL,
>  		S('c') = INT, S('s') = PTR, S('n') = PTR,
> @@ -68,17 +68,20 @@ static const unsigned char states[]['z'-'A'+1] = {
>  		S('d') = LLONG, S('i') = LLONG,
>  		S('o') = ULLONG, S('u') = ULLONG,
>  		S('x') = ULLONG, S('X') = ULLONG,
> +		S('b') = ULLONG, S('B') = ULLONG,
>  		S('n') = PTR,
>  	}, { /* 3: h-prefixed */
>  		S('d') = SHORT, S('i') = SHORT,
>  		S('o') = USHORT, S('u') = USHORT,
>  		S('x') = USHORT, S('X') = USHORT,
> +		S('b') = USHORT, S('B') = USHORT,
>  		S('n') = PTR,
>  		S('h') = HHPRE,
>  	}, { /* 4: hh-prefixed */
>  		S('d') = CHAR, S('i') = CHAR,
>  		S('o') = UCHAR, S('u') = UCHAR,
>  		S('x') = UCHAR, S('X') = UCHAR,
> +		S('b') = UCHAR, S('B') = UCHAR,
>  		S('n') = PTR,
>  	}, { /* 5: L-prefixed */
>  		S('e') = LDBL, S('f') = LDBL, S('g') = LDBL, S('a') = LDBL,
> @@ -88,11 +91,13 @@ static const unsigned char states[]['z'-'A'+1] = {
>  		S('d') = PDIFF, S('i') = PDIFF,
>  		S('o') = SIZET, S('u') = SIZET,
>  		S('x') = SIZET, S('X') = SIZET,
> +		S('b') = SIZET, S('B') = SIZET,
>  		S('n') = PTR,
>  	}, { /* 7: j-prefixed */
>  		S('d') = IMAX, S('i') = IMAX,
>  		S('o') = UMAX, S('u') = UMAX,
>  		S('x') = UMAX, S('X') = UMAX,
> +		S('b') = UMAX, S('B') = UMAX,
>  		S('n') = PTR,
>  	}
>  };
> @@ -162,6 +167,12 @@ static char *fmt_o(uintmax_t x, char *s)
>  	return s;
>  }
>  
> +static char *fmt_b(uintmax_t x, char *s)
> +{
> +	for (; x; x>>=1) *--s = '0' + (x&1);
> +	return s;
> +}
> +
>  static char *fmt_u(uintmax_t x, char *s)
>  {
>  	unsigned long y;
> @@ -529,7 +540,7 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
>  		if (!f) continue;
>  
>  		z = buf + sizeof(buf);
> -		prefix = "-+   0X0x";
> +		prefix = "-+   0X0x0B0b";
>  		pl = 0;
>  		t = s[-1];
>  
> @@ -559,6 +570,10 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
>  			a = fmt_x(arg.i, z, t&32);
>  			if (arg.i && (fl & ALT_FORM)) prefix+=(t>>4), pl=2;
>  			if (0) {
> +		case 'b': case 'B':
> +			a = fmt_b(arg.i, z);
> +			if (arg.i && (fl & ALT_FORM)) prefix += 9 + ((t == 'b') << 1), pl=2;
> +			} if (0) {
>  		case 'o':
>  			a = fmt_o(arg.i, z);
>  			if ((fl&ALT_FORM) && p<z-a+1) p=z-a+1;
> -- 
> 2.37.3

I'm not sure what the schedule on taking this or other C2x changes
relative to the standard becoming official should be, so we should
probably discuss that at some point. The only real hard concern is
that we need to be careful not to take anything where the standard
mandated behavior might change before it's final.

For the above patch specifically:

1. There's a buffer overflow because you did not adjust the size
   formula for buf[]. Presently it's only 40-55 bytes (due to the
   inclusion of LDBL_MANT_DIG/4 in there, which is almost surely cruft
   predating the initial release) while a binary-form string requires
   at least 64 bytes.

2. Presumably the wide printf forms need to accept %b too. Does scanf
   need to accept them too? I think those would all be easy changes,
   since scanf already has the strto* core with arbitrary base
   available to it, and wide printf just calls back to the narrow one.

I don't see anything else immediately wrong. No rush to submit an
updated patch. Let's first figure out the timeline for C2x features,
and I'll try to figure out what's going on with the weird buf[] size
expression and clean it up separately so that your patch is just
adding the feature and not also fighting with historical cruft.

Rich

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [musl] [PATCH] vfprintf: support C2x %b and %B conversion specifiers
  2022-09-12 13:59 ` Rich Felker
@ 2022-09-12 14:42   ` Jₑₙₛ Gustedt
  2022-09-19 15:09     ` Rich Felker
  0 siblings, 1 reply; 17+ messages in thread
From: Jₑₙₛ Gustedt @ 2022-09-12 14:42 UTC (permalink / raw)
  To: musl

[-- Attachment #1: Type: text/plain, Size: 2201 bytes --]

Rich,

on Mon, 12 Sep 2022 09:59:04 -0400 you (Rich Felker <dalias@libc.org>)
wrote:

> I don't see anything else immediately wrong. No rush to submit an
> updated patch. Let's first figure out the timeline for C2x features,
> and I'll try to figure out what's going on with the weird buf[] size
> expression and clean it up separately so that your patch is just
> adding the feature and not also fighting with historical cruft.

The specification of C23 has been finished in July, what follows now
in WG14 is merely editorial on the standard text itself and should not
have much impact on how things should be implemented. The current
draft is here

      https://open-std.org/jtc1/sc22/wg14/www/docs/n3047.pdf

and any changes from there should not have impact on implementations,
unless a majority of the national bodies imposes withdrawal of
specific new features. The timeline is publication in end of 2023, so
this leaves basically one year to have things ready when the new
standard is published

Already for `printf` and friends there are several additions, not only
the `b` formats but, e.g, also formats for the fixed-width types and
for the new bit-precise types.

Otherwise, there are changes to the C library all over the place, but
in general these are small and should be doable with limited work
load, in particular for implementations that also implement
POSIX. Those headers that have changes also are now supposed to have a
feature macro that describes the version for which a header works,
such that support for C23 can be added stepwise to C library
implementations.

There is one big addition, though, for the decimal floating point
types, but support here is optional. I don't know if there is already
an open stand-alone implementation of that stuff, but I think that
that should be the goal, instead of repeating the effort for every C
library implementation that is out there.

Jₑₙₛ

-- 
:: INRIA Nancy Grand Est ::: Camus ::::::: ICube/ICPS :::
:: :::::::::::::::::::::: gsm France : +33 651400183   ::
:: ::::::::::::::: gsm international : +49 15737185122 ::
:: http://icube-icps.unistra.fr/index.php/Jens_Gustedt ::

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [musl] [PATCH] vfprintf: support C2x %b and %B conversion specifiers
  2022-09-12 14:42   ` Jₑₙₛ Gustedt
@ 2022-09-19 15:09     ` Rich Felker
  2022-09-19 17:59       ` Szabolcs Nagy
  0 siblings, 1 reply; 17+ messages in thread
From: Rich Felker @ 2022-09-19 15:09 UTC (permalink / raw)
  To: Jₑₙₛ Gustedt; +Cc: musl

On Mon, Sep 12, 2022 at 04:42:51PM +0200, Jₑₙₛ Gustedt wrote:
> Rich,
> 
> on Mon, 12 Sep 2022 09:59:04 -0400 you (Rich Felker <dalias@libc.org>)
> wrote:
> 
> > I don't see anything else immediately wrong. No rush to submit an
> > updated patch. Let's first figure out the timeline for C2x features,
> > and I'll try to figure out what's going on with the weird buf[] size
> > expression and clean it up separately so that your patch is just
> > adding the feature and not also fighting with historical cruft.
> 
> The specification of C23 has been finished in July, what follows now
> in WG14 is merely editorial on the standard text itself and should not
> have much impact on how things should be implemented. The current
> draft is here
> 
>       https://open-std.org/jtc1/sc22/wg14/www/docs/n3047.pdf
> 
> and any changes from there should not have impact on implementations,
> unless a majority of the national bodies imposes withdrawal of
> specific new features. The timeline is publication in end of 2023, so
> this leaves basically one year to have things ready when the new
> standard is published
> 
> Already for `printf` and friends there are several additions, not only
> the `b` formats but, e.g, also formats for the fixed-width types and
> for the new bit-precise types.
> 
> Otherwise, there are changes to the C library all over the place, but
> in general these are small and should be doable with limited work
> load, in particular for implementations that also implement
> POSIX. Those headers that have changes also are now supposed to have a
> feature macro that describes the version for which a header works,
> such that support for C23 can be added stepwise to C library
> implementations.
> 
> There is one big addition, though, for the decimal floating point
> types, but support here is optional. I don't know if there is already
> an open stand-alone implementation of that stuff, but I think that
> that should be the goal, instead of repeating the effort for every C
> library implementation that is out there.

What do these entail? It looks like there's a requirement for printf
to support them, so I don't see how you'd do that as a separate
library. It looks like __STDC_IEC_60559_DFP__ is optional though, so
maybe we could just decline to define it and leave the support
sporadic at the level the compiler supports, as an extension rather
than part of the standard-specified functionality?

Implementing any of this seems rather blocking since it depends on new
types at the compiler level for the compiler compiling libc. The only
way out from that is using asm thunks. For just the printf case, we
could do it with an arch-provided asm fragment that grabs the decimal
float from the va_list, which would be fairly low-cost to add/maintain
and allow the rest of the decimal float library code to be relegated
to a separate standalone library like you suggested. The only part of
printf that looks hard to implement for decimal floats is %a, and from
a quick glance it looks like the reverse direction in scanf/strto*
doesn't support hex for decimal floats?

Rich

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [musl] [PATCH] vfprintf: support C2x %b and %B conversion specifiers
  2022-09-19 15:09     ` Rich Felker
@ 2022-09-19 17:59       ` Szabolcs Nagy
  2022-09-19 18:10         ` Rich Felker
  0 siblings, 1 reply; 17+ messages in thread
From: Szabolcs Nagy @ 2022-09-19 17:59 UTC (permalink / raw)
  To: Rich Felker; +Cc: Jₑₙₛ Gustedt, musl

* Rich Felker <dalias@libc.org> [2022-09-19 11:09:17 -0400]:
> On Mon, Sep 12, 2022 at 04:42:51PM +0200, Jₑₙₛ Gustedt wrote:
> > There is one big addition, though, for the decimal floating point
> > types, but support here is optional. I don't know if there is already
> > an open stand-alone implementation of that stuff, but I think that
> > that should be the goal, instead of repeating the effort for every C
> > library implementation that is out there.
> 
> What do these entail? It looks like there's a requirement for printf
> to support them, so I don't see how you'd do that as a separate
> library. It looks like __STDC_IEC_60559_DFP__ is optional though, so
> maybe we could just decline to define it and leave the support
> sporadic at the level the compiler supports, as an extension rather
> than part of the standard-specified functionality?

it seems there is
https://github.com/libdfp/libdfp/tree/master/printf-hooks
using glibc specific apis (register_printf_specifier)

i'm not sure how musl can handle this internally since
we dont know in advance if the user links against libdfp.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [musl] [PATCH] vfprintf: support C2x %b and %B conversion specifiers
  2022-09-19 17:59       ` Szabolcs Nagy
@ 2022-09-19 18:10         ` Rich Felker
  2022-09-20  9:19           ` Jₑₙₛ Gustedt
  0 siblings, 1 reply; 17+ messages in thread
From: Rich Felker @ 2022-09-19 18:10 UTC (permalink / raw)
  To: Jₑₙₛ Gustedt, musl

On Mon, Sep 19, 2022 at 07:59:52PM +0200, Szabolcs Nagy wrote:
> * Rich Felker <dalias@libc.org> [2022-09-19 11:09:17 -0400]:
> > On Mon, Sep 12, 2022 at 04:42:51PM +0200, Jₑₙₛ Gustedt wrote:
> > > There is one big addition, though, for the decimal floating point
> > > types, but support here is optional. I don't know if there is already
> > > an open stand-alone implementation of that stuff, but I think that
> > > that should be the goal, instead of repeating the effort for every C
> > > library implementation that is out there.
> > 
> > What do these entail? It looks like there's a requirement for printf
> > to support them, so I don't see how you'd do that as a separate
> > library. It looks like __STDC_IEC_60559_DFP__ is optional though, so
> > maybe we could just decline to define it and leave the support
> > sporadic at the level the compiler supports, as an extension rather
> > than part of the standard-specified functionality?
> 
> it seems there is
> https://github.com/libdfp/libdfp/tree/master/printf-hooks
> using glibc specific apis (register_printf_specifier)
> 
> i'm not sure how musl can handle this internally since
> we dont know in advance if the user links against libdfp.

Yeah, I don't see that as being a usable approach. It's closely tied
to the glibc printf model that's not usable in bounded memory with
arbitrary width and precision, and not compatible with linking
semantics as you mention. The amount of code needed for decimal float
printing in decimal is miniscule anyway and something we can easily do
with no actual decimal floating point code. I thought the hard case
was hex, but looking at the spec again, %a doesn't actually do hex for
decimal floats, so it should be easy too.

Rich

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [musl] [PATCH] vfprintf: support C2x %b and %B conversion specifiers
  2022-09-19 18:10         ` Rich Felker
@ 2022-09-20  9:19           ` Jₑₙₛ Gustedt
  2022-09-20 12:28             ` Rich Felker
  0 siblings, 1 reply; 17+ messages in thread
From: Jₑₙₛ Gustedt @ 2022-09-20  9:19 UTC (permalink / raw)
  To: Rich Felker; +Cc: musl

[-- Attachment #1: Type: text/plain, Size: 4121 bytes --]

Rich,

on Mon, 19 Sep 2022 14:10:39 -0400 you (Rich Felker <dalias@libc.org>)
wrote:

> On Mon, Sep 19, 2022 at 07:59:52PM +0200, Szabolcs Nagy wrote:
> > * Rich Felker <dalias@libc.org> [2022-09-19 11:09:17 -0400]:  
> > > On Mon, Sep 12, 2022 at 04:42:51PM +0200, Jₑₙₛ Gustedt wrote:  
>  [...]  
> > > 
> > > What do these entail? It looks like there's a requirement for
> > > printf to support them, so I don't see how you'd do that as a
> > > separate library. It looks like __STDC_IEC_60559_DFP__ is
> > > optional though, so maybe we could just decline to define it and
> > > leave the support sporadic at the level the compiler supports, as
> > > an extension rather than part of the standard-specified
> > > functionality?  
> > 
> > it seems there is
> > https://github.com/libdfp/libdfp/tree/master/printf-hooks
> > using glibc specific apis (register_printf_specifier)
> > 
> > i'm not sure how musl can handle this internally since
> > we dont know in advance if the user links against libdfp.  
> 
> Yeah, I don't see that as being a usable approach. It's closely tied
> to the glibc printf model that's not usable in bounded memory with
> arbitrary width and precision, and not compatible with linking
> semantics as you mention. The amount of code needed for decimal float
> printing in decimal is miniscule anyway and something we can easily do
> with no actual decimal floating point code. I thought the hard case
> was hex, but looking at the spec again, %a doesn't actually do hex for
> decimal floats, so it should be easy too.

Yes exactly. There is nothing conceptually difficult here and nothing
that should not be in some form or another already in every C library.

So yes, sorry, for the separate library part I forgot formated IO and
string functions. But the huge amount of functions that are added for
these types are math functions (I guess something like 600 or so)
stepping on user's identifier space all over.

Unfortunately, again as for complex types, the standard doesn't
properly distinguish language support for the new optional types and
library support. I really would have preferred to have the whole thing
in a separate header, but my voice echoed in the void. There are the
`__STDC_VERSION_…_H__` macros now, so this gives at least some sort of
feature test.

But for implementing the parts that are outside of math, things should
indeed not be so difficult. gcc has support for the types since long,
I think, and should also provide predefined macros that could be used
to check for language support. Then, the types themselves have clear
definition and prescribed representation, the ABI is de-facto sorted
out, so there would be not much other implementation dependency to
worry about.

Other types that come with C23, and these are mandatory, are
bit-precise integers. There the support by compilers is probably not
yet completely established. I know of an integration into llvm, but I
am not sure about the state of affairs for gcc, nor if there is a
de-facto agreement on ABI issues. In any case, these types need
support in formatted IO, too.

Also, C23, provides the possibility for extended integer types that
are wider than `[u]intmax_t` under some conditions. This is intended
in particular to allow for implementations such as gcc on x86_64 to
interface the existing 128 bit integer types properly as
`[u]int128_t`. From a C library POV, these then also would need
integration into formatted IO, but here again support in the compiler
with usable feature test macros is there for ages and the ABI should
already be sorted out.

So in summary that means that there is some work to do to make
formatted IO of C libraries become compliant with C23. Let me know if
and where I could help to make that happen for musl.


Thanks
Jₑₙₛ

-- 
:: INRIA Nancy Grand Est ::: Camus ::::::: ICube/ICPS :::
:: :::::::::::::::::::::: gsm France : +33 651400183   ::
:: ::::::::::::::: gsm international : +49 15737185122 ::
:: http://icube-icps.unistra.fr/index.php/Jens_Gustedt ::

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [musl] [PATCH] vfprintf: support C2x %b and %B conversion specifiers
  2022-09-20  9:19           ` Jₑₙₛ Gustedt
@ 2022-09-20 12:28             ` Rich Felker
  2022-09-20 13:29               ` Jₑₙₛ Gustedt
  0 siblings, 1 reply; 17+ messages in thread
From: Rich Felker @ 2022-09-20 12:28 UTC (permalink / raw)
  To: Jₑₙₛ Gustedt; +Cc: musl

On Tue, Sep 20, 2022 at 11:19:34AM +0200, Jₑₙₛ Gustedt wrote:
> Rich,
> 
> on Mon, 19 Sep 2022 14:10:39 -0400 you (Rich Felker <dalias@libc.org>)
> wrote:
> 
> > On Mon, Sep 19, 2022 at 07:59:52PM +0200, Szabolcs Nagy wrote:
> > > * Rich Felker <dalias@libc.org> [2022-09-19 11:09:17 -0400]:  
> > > > On Mon, Sep 12, 2022 at 04:42:51PM +0200, Jₑₙₛ Gustedt wrote:  
> >  [...]  
> > > > 
> > > > What do these entail? It looks like there's a requirement for
> > > > printf to support them, so I don't see how you'd do that as a
> > > > separate library. It looks like __STDC_IEC_60559_DFP__ is
> > > > optional though, so maybe we could just decline to define it and
> > > > leave the support sporadic at the level the compiler supports, as
> > > > an extension rather than part of the standard-specified
> > > > functionality?  
> > > 
> > > it seems there is
> > > https://github.com/libdfp/libdfp/tree/master/printf-hooks
> > > using glibc specific apis (register_printf_specifier)
> > > 
> > > i'm not sure how musl can handle this internally since
> > > we dont know in advance if the user links against libdfp.  
> > 
> > Yeah, I don't see that as being a usable approach. It's closely tied
> > to the glibc printf model that's not usable in bounded memory with
> > arbitrary width and precision, and not compatible with linking
> > semantics as you mention. The amount of code needed for decimal float
> > printing in decimal is miniscule anyway and something we can easily do
> > with no actual decimal floating point code. I thought the hard case
> > was hex, but looking at the spec again, %a doesn't actually do hex for
> > decimal floats, so it should be easy too.
> 
> Yes exactly. There is nothing conceptually difficult here and nothing
> that should not be in some form or another already in every C library.
> 
> So yes, sorry, for the separate library part I forgot formated IO and
> string functions. But the huge amount of functions that are added for
> these types are math functions (I guess something like 600 or so)
> stepping on user's identifier space all over.

Yes, I think it's fine for now to have a separate math library for the
math functions. Otherwise the work of adding these interfaces becomes
rather prohibitive. I would assume they're all pure functions where
correct implementations are basically interchangable, so I don't see a
lot of value in insisting these "go with" libc.

> Unfortunately, again as for complex types, the standard doesn't
> properly distinguish language support for the new optional types and
> library support. I really would have preferred to have the whole thing
> in a separate header, but my voice echoed in the void. There are the
> `__STDC_VERSION_…_H__` macros now, so this gives at least some sort of
> feature test.

I can see both viewpoints as having good motivation, but yes it's
frustrating.

> But for implementing the parts that are outside of math, things should
> indeed not be so difficult. gcc has support for the types since long,
> I think, and should also provide predefined macros that could be used
> to check for language support. Then, the types themselves have clear
> definition and prescribed representation, the ABI is de-facto sorted
> out, so there would be not much other implementation dependency to
> worry about.

The thing is we don't have the option to "check for language support".
Doing that would mean you get a deficient musl build if your compiler
doesn't have the language features, so essentially we'd be requiring
bleeding-edge gcc or clang (dropping all other-compiler support at the
same time) to get a properly featured libc.so that's capable of
supporting arbitrary musl-linked binaries.

This is why we're going to need asm thunks for performing va_arg with
the new types and (programmatically generated, I assume) asm entry
thunks for accepting arguments to any non-variadic functions, which
can convert (ideally as a no-op) the decimal float type arguments to
integer-type or struct arguments the underlying implementation files
would then receive.

> Other types that come with C23, and these are mandatory, are
> bit-precise integers. There the support by compilers is probably not
> yet completely established. I know of an integration into llvm, but I
> am not sure about the state of affairs for gcc, nor if there is a
> de-facto agreement on ABI issues. In any case, these types need
> support in formatted IO, too.

As far as I can tell, the draft standard makes printf support for all
but the ones defined as [u]intNN_t a choice for the implementation, so
the obvious choice is not to support any additional ones.

> Also, C23, provides the possibility for extended integer types that
> are wider than `[u]intmax_t` under some conditions. This is intended
> in particular to allow for implementations such as gcc on x86_64 to
> interface the existing 128 bit integer types properly as
> `[u]int128_t`. From a C library POV, these then also would need
> integration into formatted IO, but here again support in the compiler
> with usable feature test macros is there for ages and the ABI should
> already be sorted out.

Yes. I haven't followed the latest on this but my leaning was to leave
them as "compiler extensions" that don't count as "extended integer
types". However presumably they could be handled the same way as
decimal floats if needed.

> So in summary that means that there is some work to do to make
> formatted IO of C libraries become compliant with C23. Let me know if
> and where I could help to make that happen for musl.

The big issue is probably collating the list of what's actually needed
to meet requirements, and what the ABIs for them are. If there's
cross-arch agreement on a general pattern ABIs follow for them, that
would be wonderful, and even if not entirely so, a general pattern
would advise how we structure the underlying functions (to make thunks
as minimal as possible on the largest number of archs).

Rich

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [musl] [PATCH] vfprintf: support C2x %b and %B conversion specifiers
  2022-09-20 12:28             ` Rich Felker
@ 2022-09-20 13:29               ` Jₑₙₛ Gustedt
  2022-09-20 13:55                 ` Rich Felker
  0 siblings, 1 reply; 17+ messages in thread
From: Jₑₙₛ Gustedt @ 2022-09-20 13:29 UTC (permalink / raw)
  To: Rich Felker; +Cc: musl

[-- Attachment #1: Type: text/plain, Size: 8030 bytes --]

Rich,

on Tue, 20 Sep 2022 08:28:29 -0400 you (Rich Felker <dalias@libc.org>)
wrote:

> On Tue, Sep 20, 2022 at 11:19:34AM +0200, Jₑₙₛ Gustedt wrote:
> > Rich,
> > 
> > on Mon, 19 Sep 2022 14:10:39 -0400 you (Rich Felker
> > <dalias@libc.org>) wrote:
> >   
> > > On Mon, Sep 19, 2022 at 07:59:52PM +0200, Szabolcs Nagy wrote:  
>  [...]  
>  [...]  
> > >  [...]    
>  [...]  
>  [...]  
> > > 
> > > Yeah, I don't see that as being a usable approach. It's closely
> > > tied to the glibc printf model that's not usable in bounded
> > > memory with arbitrary width and precision, and not compatible
> > > with linking semantics as you mention. The amount of code needed
> > > for decimal float printing in decimal is miniscule anyway and
> > > something we can easily do with no actual decimal floating point
> > > code. I thought the hard case was hex, but looking at the spec
> > > again, %a doesn't actually do hex for decimal floats, so it
> > > should be easy too.  
> > 
> > Yes exactly. There is nothing conceptually difficult here and
> > nothing that should not be in some form or another already in every
> > C library.
> > 
> > So yes, sorry, for the separate library part I forgot formated IO
> > and string functions. But the huge amount of functions that are
> > added for these types are math functions (I guess something like
> > 600 or so) stepping on user's identifier space all over.  
> 
> Yes, I think it's fine for now to have a separate math library for the
> math functions. Otherwise the work of adding these interfaces becomes
> rather prohibitive. I would assume they're all pure functions where
> correct implementations are basically interchangable, so I don't see a
> lot of value in insisting these "go with" libc.

Depends on your instantiation of "pure", but yes, these should be
mostly interchangeable. The only thing to worry here are that there
are two possible representations for these types, one where the
mantissa is basically represented as an integer, and the other where
decimal digits are packed into groups of bytes in a clever way.

> …

> > But for implementing the parts that are outside of math, things
> > should indeed not be so difficult. gcc has support for the types
> > since long, I think, and should also provide predefined macros that
> > could be used to check for language support. Then, the types
> > themselves have clear definition and prescribed representation, the
> > ABI is de-facto sorted out, so there would be not much other
> > implementation dependency to worry about.  
> 
> The thing is we don't have the option to "check for language support".
> Doing that would mean you get a deficient musl build if your compiler
> doesn't have the language features, so essentially we'd be requiring
> bleeding-edge gcc or clang (dropping all other-compiler support at the
> same time) to get a properly featured libc.so that's capable of
> supporting arbitrary musl-linked binaries.

I don't think that this needs to be. If you add e.g support for
decimal floating point to `printf`, the compiler support for that only
has to be there on the platform where you compile musl. If a user
platform that uses such a library does not support it, that part will
simply never be called because users can't defined variables of that
type. This increases the size of `printf` a bit, though, but my guess
is that this would be marginal compared to the size that `printf` has,
anyhow.

> This is why we're going to need asm thunks for performing va_arg with
> the new types and (programmatically generated, I assume) asm entry
> thunks for accepting arguments to any non-variadic functions, which
> can convert (ideally as a no-op) the decimal float type arguments to
> integer-type or struct arguments the underlying implementation files
> would then receive.

There are no C library functions other than in math.h, I think, that
accept decimal floating types as prototyped arguments. So if we don't
do math.h, only `printf` and similar remain with `va_arg` calling
conventions.

The only functions that have decimal floating return types are the
`strtodN` functions in 7.24.1.6, AFAICS.

So, yes, we'd have to extend `va_arg` with the necessary knowledge to
obtain a decimal floating point, but hopefully that is just the same
as obtaining access to other 32, 64 or 128 bit types.

> > Other types that come with C23, and these are mandatory, are
> > bit-precise integers. There the support by compilers is probably not
> > yet completely established. I know of an integration into llvm, but
> > I am not sure about the state of affairs for gcc, nor if there is a
> > de-facto agreement on ABI issues. In any case, these types need
> > support in formatted IO, too.  
> 
> As far as I can tell, the draft standard makes printf support for all
> but the ones defined as [u]intNN_t a choice for the implementation, so
> the obvious choice is not to support any additional ones.

(There are also the "fast" version that have a different format
specifier, but which hopefully are basically the same as for the exact
width.)

I think for QoI it would be really good to support the bit-precise
types. These are a quite good design that avoids a lot of the
complications of the classical integer types. In particular we will
see them pop up for bit-fields and stuff like that, where there have
clearer semantics than the traditional ones and extend the
possibilities beyond the width of `int` to at least 64 bit.

> > Also, C23, provides the possibility for extended integer types that
> > are wider than `[u]intmax_t` under some conditions. This is intended
> > in particular to allow for implementations such as gcc on x86_64 to
> > interface the existing 128 bit integer types properly as
> > `[u]int128_t`. From a C library POV, these then also would need
> > integration into formatted IO, but here again support in the
> > compiler with usable feature test macros is there for ages and the
> > ABI should already be sorted out.  
> 
> Yes. I haven't followed the latest on this but my leaning was to leave
> them as "compiler extensions" that don't count as "extended integer
> types". However presumably they could be handled the same way as
> decimal floats if needed.

For once this allows to define extended integer types in the sense of
the standard and to provide full support for them. But you are right
the approach could be the same as for decimal floating point: compile
them in if the compilation platform of the C library supports them.

> > So in summary that means that there is some work to do to make
> > formatted IO of C libraries become compliant with C23. Let me know
> > if and where I could help to make that happen for musl.  
> 
> The big issue is probably collating the list of what's actually needed
> to meet requirements,

that I could do

> and what the ABIs for them are.

that's were I am not an expert in :-((

> If there's cross-arch agreement on a general pattern ABIs follow for
> them, that would be wonderful, and even if not entirely so, a
> general pattern would advise how we structure the underlying
> functions (to make thunks as minimal as possible on the largest
> number of archs).

My guess for that is that the decimal floating point types are just
handled by their respective width, and that the bit-precise integer
types of width N will be rounded up to the next power of two M and use
representation and calling convention for `uintM_t`. But that would of
course have to be verified. I can ask Aaron (who wrote this stuff and
has provided the implementation in llvm) how that is actually done
there.

Jₑₙₛ

-- 
:: INRIA Nancy Grand Est ::: Camus ::::::: ICube/ICPS :::
:: :::::::::::::::::::::: gsm France : +33 651400183   ::
:: ::::::::::::::: gsm international : +49 15737185122 ::
:: http://icube-icps.unistra.fr/index.php/Jens_Gustedt ::

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [musl] [PATCH] vfprintf: support C2x %b and %B conversion specifiers
  2022-09-20 13:29               ` Jₑₙₛ Gustedt
@ 2022-09-20 13:55                 ` Rich Felker
  2022-09-20 14:08                   ` Jₑₙₛ Gustedt
  0 siblings, 1 reply; 17+ messages in thread
From: Rich Felker @ 2022-09-20 13:55 UTC (permalink / raw)
  To: Jₑₙₛ Gustedt; +Cc: musl

On Tue, Sep 20, 2022 at 03:29:29PM +0200, Jₑₙₛ Gustedt wrote:
> Rich,
> 
> on Tue, 20 Sep 2022 08:28:29 -0400 you (Rich Felker <dalias@libc.org>)
> wrote:
> 
> > On Tue, Sep 20, 2022 at 11:19:34AM +0200, Jₑₙₛ Gustedt wrote:
> > > Rich,
> > > 
> > > on Mon, 19 Sep 2022 14:10:39 -0400 you (Rich Felker
> > > <dalias@libc.org>) wrote:
> > >   
> > > > On Mon, Sep 19, 2022 at 07:59:52PM +0200, Szabolcs Nagy wrote:  
> > > So yes, sorry, for the separate library part I forgot formated IO
> > > and string functions. But the huge amount of functions that are
> > > added for these types are math functions (I guess something like
> > > 600 or so) stepping on user's identifier space all over.  
> > 
> > Yes, I think it's fine for now to have a separate math library for the
> > math functions. Otherwise the work of adding these interfaces becomes
> > rather prohibitive. I would assume they're all pure functions where
> > correct implementations are basically interchangable, so I don't see a
> > lot of value in insisting these "go with" libc.
> 
> Depends on your instantiation of "pure", but yes, these should be
> mostly interchangeable. The only thing to worry here are that there
> are two possible representations for these types, one where the
> mantissa is basically represented as an integer, and the other where
> decimal digits are packed into groups of bytes in a clever way.

Well the one in use is presumably defined by the psABI. Does it
actually vary by arch, or is there a common form that everyone
reasonable has agreed upon? Note that we're not considering the full
generality the C standard allows, just a single family of platforms.

> > > But for implementing the parts that are outside of math, things
> > > should indeed not be so difficult. gcc has support for the types
> > > since long, I think, and should also provide predefined macros that
> > > could be used to check for language support. Then, the types
> > > themselves have clear definition and prescribed representation, the
> > > ABI is de-facto sorted out, so there would be not much other
> > > implementation dependency to worry about.  
> > 
> > The thing is we don't have the option to "check for language support".
> > Doing that would mean you get a deficient musl build if your compiler
> > doesn't have the language features, so essentially we'd be requiring
> > bleeding-edge gcc or clang (dropping all other-compiler support at the
> > same time) to get a properly featured libc.so that's capable of
> > supporting arbitrary musl-linked binaries.
> 
> I don't think that this needs to be. If you add e.g support for
> decimal floating point to `printf`, the compiler support for that only
> has to be there on the platform where you compile musl. If a user
> platform that uses such a library does not support it, that part will
> simply never be called because users can't defined variables of that
> type. This increases the size of `printf` a bit, though, but my guess
> is that this would be marginal compared to the size that `printf` has,
> anyhow.

You're looking at it from a perspective of producing your own software
linked to musl. I'm looking at it from a perspective of building your
own build of musl to execute existing dynamic-linked binaries outside
your control. Users building musl need to be able to build a
feature-complete version regardless of their compiler. We don't have
different interface/feature profiles based on which compiler version
you built with or any build-time options, and not having that is very
intentional.

> > This is why we're going to need asm thunks for performing va_arg with
> > the new types and (programmatically generated, I assume) asm entry
> > thunks for accepting arguments to any non-variadic functions, which
> > can convert (ideally as a no-op) the decimal float type arguments to
> > integer-type or struct arguments the underlying implementation files
> > would then receive.
> 
> There are no C library functions other than in math.h, I think, that
> accept decimal floating types as prototyped arguments. So if we don't
> do math.h, only `printf` and similar remain with `va_arg` calling
> conventions.
> 
> The only functions that have decimal floating return types are the
> `strtodN` functions in 7.24.1.6, AFAICS.
> 
> So, yes, we'd have to extend `va_arg` with the necessary knowledge to
> obtain a decimal floating point, but hopefully that is just the same
> as obtaining access to other 32, 64 or 128 bit types.

Oh, nice -- I didn't realize they only appear as return values not
arguments. Unfortunately, return values are worse. In order to do the
thunk, you need to setup a call frame and possibly munge the return
value into the storage it belongs in to meet the ABI requirement. For
arguments, on the other hand, it's likely just a tail-call.

> > > Other types that come with C23, and these are mandatory, are
> > > bit-precise integers. There the support by compilers is probably not
> > > yet completely established. I know of an integration into llvm, but
> > > I am not sure about the state of affairs for gcc, nor if there is a
> > > de-facto agreement on ABI issues. In any case, these types need
> > > support in formatted IO, too.  
> > 
> > As far as I can tell, the draft standard makes printf support for all
> > but the ones defined as [u]intNN_t a choice for the implementation, so
> > the obvious choice is not to support any additional ones.
> 
> (There are also the "fast" version that have a different format
> specifier, but which hopefully are basically the same as for the exact
> width.)
> 
> I think for QoI it would be really good to support the bit-precise
> types. These are a quite good design that avoids a lot of the
> complications of the classical integer types. In particular we will
> see them pop up for bit-fields and stuff like that, where there have
> clearer semantics than the traditional ones and extend the
> possibilities beyond the width of `int` to at least 64 bit.

Surely there are going to be all sorts of ABI issues with passing them
as arguments. The right thing to do, as an application programmer
writing a portable program, is the same as when printing types without
a format specifier like time_t: just cast them up to a maximal-size
type that you know is supported and can represent the value. There is
no sense in optimizing the type you pass these things as when the
operation you're passing them for is as "big" as printf.

> > > Also, C23, provides the possibility for extended integer types that
> > > are wider than `[u]intmax_t` under some conditions. This is intended
> > > in particular to allow for implementations such as gcc on x86_64 to
> > > interface the existing 128 bit integer types properly as
> > > `[u]int128_t`. From a C library POV, these then also would need
> > > integration into formatted IO, but here again support in the
> > > compiler with usable feature test macros is there for ages and the
> > > ABI should already be sorted out.  
> > 
> > Yes. I haven't followed the latest on this but my leaning was to leave
> > them as "compiler extensions" that don't count as "extended integer
> > types". However presumably they could be handled the same way as
> > decimal floats if needed.
> 
> For once this allows to define extended integer types in the sense of
> the standard and to provide full support for them. But you are right
> the approach could be the same as for decimal floating point: compile
> them in if the compilation platform of the C library supports them.
> 
> > > So in summary that means that there is some work to do to make
> > > formatted IO of C libraries become compliant with C23. Let me know
> > > if and where I could help to make that happen for musl.  
> > 
> > The big issue is probably collating the list of what's actually needed
> > to meet requirements,
> 
> that I could do

Thanks!

> > and what the ABIs for them are.
> 
> that's were I am not an expert in :-((

OK, hopefully someone else is.

> > If there's cross-arch agreement on a general pattern ABIs follow for
> > them, that would be wonderful, and even if not entirely so, a
> > general pattern would advise how we structure the underlying
> > functions (to make thunks as minimal as possible on the largest
> > number of archs).
> 
> My guess for that is that the decimal floating point types are just
> handled by their respective width, and that the bit-precise integer

Unfortunately in most ABIs the convention for passing a type is not
just a function of its size. Floating point types are usually passed
in different registers, and aggregate types often have complex
conventions for whether they're passed in registers or on the stack
depending on their member types and sizes. So, for decimal float, it's
probably the same as *some* N-bit type, but which one? :)

> types of width N will be rounded up to the next power of two M and use
> representation and calling convention for `uintM_t`. But that would of
> course have to be verified. I can ask Aaron (who wrote this stuff and
> has provided the implementation in llvm) how that is actually done
> there.

If the width-N stuff is uniform like that, it might be possible to
support arbitrary in-range N, but again I'm skeptical of the value
especially when applications cannot portably use any Ns except the
ones with macros defined in stdint.h.

In general, offering non-portable functionality that applications
can't already generally expect to have on popular systems, with no way
to probe for availability, does not seem useful, and it's even less
useful when there's a trivial portable way to do the same thing.

Rich

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [musl] [PATCH] vfprintf: support C2x %b and %B conversion specifiers
  2022-09-20 13:55                 ` Rich Felker
@ 2022-09-20 14:08                   ` Jₑₙₛ Gustedt
  2022-09-20 14:15                     ` Rich Felker
  0 siblings, 1 reply; 17+ messages in thread
From: Jₑₙₛ Gustedt @ 2022-09-20 14:08 UTC (permalink / raw)
  To: Rich Felker; +Cc: musl

[-- Attachment #1: Type: text/plain, Size: 1023 bytes --]

Rich,

on Tue, 20 Sep 2022 09:55:54 -0400 you (Rich Felker <dalias@libc.org>)
wrote:

> In general, offering non-portable functionality that applications
> can't already generally expect to have on popular systems, with no way
> to probe for availability, does not seem useful, and it's even less
> useful when there's a trivial portable way to do the same thing.

Unfortunately, for the the bit-precise types there isn't. The
supported types may be wider than `long long` (128 and even 256 will
be common values that will probably widely supported) and then the
task of printing them gets as nasty as for today's `__int128`. My hope
was really to get all of these done for once, such that our users may
use their creativity to do more useful stuff.

Jₑₙₛ

-- 
:: INRIA Nancy Grand Est ::: Camus ::::::: ICube/ICPS :::
:: :::::::::::::::::::::: gsm France : +33 651400183   ::
:: ::::::::::::::: gsm international : +49 15737185122 ::
:: http://icube-icps.unistra.fr/index.php/Jens_Gustedt ::

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [musl] [PATCH] vfprintf: support C2x %b and %B conversion specifiers
  2022-09-20 14:08                   ` Jₑₙₛ Gustedt
@ 2022-09-20 14:15                     ` Rich Felker
  2022-09-20 14:22                       ` Jₑₙₛ Gustedt
  0 siblings, 1 reply; 17+ messages in thread
From: Rich Felker @ 2022-09-20 14:15 UTC (permalink / raw)
  To: Jₑₙₛ Gustedt; +Cc: musl

On Tue, Sep 20, 2022 at 04:08:03PM +0200, Jₑₙₛ Gustedt wrote:
> Rich,
> 
> on Tue, 20 Sep 2022 09:55:54 -0400 you (Rich Felker <dalias@libc.org>)
> wrote:
> 
> > In general, offering non-portable functionality that applications
> > can't already generally expect to have on popular systems, with no way
> > to probe for availability, does not seem useful, and it's even less
> > useful when there's a trivial portable way to do the same thing.
> 
> Unfortunately, for the the bit-precise types there isn't. The
> supported types may be wider than `long long` (128 and even 256 will
> be common values that will probably widely supported) and then the
> task of printing them gets as nasty as for today's `__int128`. My hope
> was really to get all of these done for once, such that our users may
> use their creativity to do more useful stuff.

Well how are programmers supposed to probe what's available, and what
are they supposed to do as fallback when support is not available? And
what is the upper limit? Without answering those questions I don't see
how this functionality can be made useful, because it's not even safe
to use (you get UB if you guess wrong). The proposal on libc-coord for
how to advertise feature availability (including at runtime via
sysconf keys) addresses this kind of problem in general with
extensions you can't just probe for with a configure-time link test,
and might be the answer here...

Rich

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [musl] [PATCH] vfprintf: support C2x %b and %B conversion specifiers
  2022-09-20 14:15                     ` Rich Felker
@ 2022-09-20 14:22                       ` Jₑₙₛ Gustedt
  2022-09-20 14:27                         ` Jₑₙₛ Gustedt
  0 siblings, 1 reply; 17+ messages in thread
From: Jₑₙₛ Gustedt @ 2022-09-20 14:22 UTC (permalink / raw)
  To: Rich Felker; +Cc: musl

[-- Attachment #1: Type: text/plain, Size: 1637 bytes --]

Rich,

on Tue, 20 Sep 2022 10:15:18 -0400 you (Rich Felker <dalias@libc.org>)
wrote:

> On Tue, Sep 20, 2022 at 04:08:03PM +0200, Jₑₙₛ Gustedt wrote:
> > Rich,
> > 
> > on Tue, 20 Sep 2022 09:55:54 -0400 you (Rich Felker
> > <dalias@libc.org>) wrote:
> >   
> > > In general, offering non-portable functionality that applications
> > > can't already generally expect to have on popular systems, with
> > > no way to probe for availability, does not seem useful, and it's
> > > even less useful when there's a trivial portable way to do the
> > > same thing.  
> > 
> > Unfortunately, for the the bit-precise types there isn't. The
> > supported types may be wider than `long long` (128 and even 256 will
> > be common values that will probably widely supported) and then the
> > task of printing them gets as nasty as for today's `__int128`. My
> > hope was really to get all of these done for once, such that our
> > users may use their creativity to do more useful stuff.  
> 
> Well how are programmers supposed to probe what's available, and what
> are they supposed to do as fallback when support is not available? And
> what is the upper limit?

There is a feature test macro for the maximum width of bit-precise
integers, `BITINT_MAXWIDTH`. It is guaranteed to be at least
`ULLONG_WIDTH` but can (and will) be larger on many platforms.

Jₑₙₛ

-- 
:: INRIA Nancy Grand Est ::: Camus ::::::: ICube/ICPS :::
:: :::::::::::::::::::::: gsm France : +33 651400183   ::
:: ::::::::::::::: gsm international : +49 15737185122 ::
:: http://icube-icps.unistra.fr/index.php/Jens_Gustedt ::

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [musl] [PATCH] vfprintf: support C2x %b and %B conversion specifiers
  2022-09-20 14:22                       ` Jₑₙₛ Gustedt
@ 2022-09-20 14:27                         ` Jₑₙₛ Gustedt
  2022-09-20 14:46                           ` Rich Felker
  0 siblings, 1 reply; 17+ messages in thread
From: Jₑₙₛ Gustedt @ 2022-09-20 14:27 UTC (permalink / raw)
  To: Rich Felker; +Cc: musl

[-- Attachment #1: Type: text/plain, Size: 682 bytes --]

on Tue, 20 Sep 2022 16:22:36 +0200 you (Jₑₙₛ Gustedt
<jens.gustedt@inria.fr>) wrote:

> There is a feature test macro for the maximum width of bit-precise
> integers, `BITINT_MAXWIDTH`. It is guaranteed to be at least
> `ULLONG_WIDTH` but can (and will) be larger on many platforms.

e.g on my ubuntu-nothing-fancy machine I get

 clang -E -dM -xc /dev/null | grep -i bitint
 #define __BITINT_MAXWIDTH__ 128

Jₑₙₛ

-- 
:: INRIA Nancy Grand Est ::: Camus ::::::: ICube/ICPS :::
:: :::::::::::::::::::::: gsm France : +33 651400183   ::
:: ::::::::::::::: gsm international : +49 15737185122 ::
:: http://icube-icps.unistra.fr/index.php/Jens_Gustedt ::

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [musl] [PATCH] vfprintf: support C2x %b and %B conversion specifiers
  2022-09-20 14:27                         ` Jₑₙₛ Gustedt
@ 2022-09-20 14:46                           ` Rich Felker
  2022-09-20 15:20                             ` Jₑₙₛ Gustedt
  0 siblings, 1 reply; 17+ messages in thread
From: Rich Felker @ 2022-09-20 14:46 UTC (permalink / raw)
  To: Jₑₙₛ Gustedt; +Cc: musl

On Tue, Sep 20, 2022 at 04:27:28PM +0200, Jₑₙₛ Gustedt wrote:
> on Tue, 20 Sep 2022 16:22:36 +0200 you (Jₑₙₛ Gustedt
> <jens.gustedt@inria.fr>) wrote:
> 
> > There is a feature test macro for the maximum width of bit-precise
> > integers, `BITINT_MAXWIDTH`. It is guaranteed to be at least
> > `ULLONG_WIDTH` but can (and will) be larger on many platforms.
> 
> e.g on my ubuntu-nothing-fancy machine I get
> 
>  clang -E -dM -xc /dev/null | grep -i bitint
>  #define __BITINT_MAXWIDTH__ 128

As I understand it, that gives the application knowledge of what
bit-precise types the compiler can provide to it, but doesn't do
anything to tell the application what wN modifiers printf can be
expected to support. If it were required to support wN for
N==BITINT_MAXWIDTH that would at least be something to go from, but I
see no such requirement and I'm not sure it's desirable (it means you
can't let the compiler offer larger BITINT_MAXWIDTH, but would have to
define it as what libc supports).

I think a separate macro indicating what printf supports is needed to
solve this problem well.

Rich

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [musl] [PATCH] vfprintf: support C2x %b and %B conversion specifiers
  2022-09-20 14:46                           ` Rich Felker
@ 2022-09-20 15:20                             ` Jₑₙₛ Gustedt
  0 siblings, 0 replies; 17+ messages in thread
From: Jₑₙₛ Gustedt @ 2022-09-20 15:20 UTC (permalink / raw)
  To: Rich Felker; +Cc: musl

[-- Attachment #1: Type: text/plain, Size: 1656 bytes --]

Rich,

on Tue, 20 Sep 2022 10:46:18 -0400 you (Rich Felker <dalias@libc.org>)
wrote:

> On Tue, Sep 20, 2022 at 04:27:28PM +0200, Jₑₙₛ Gustedt wrote:
> > on Tue, 20 Sep 2022 16:22:36 +0200 you (Jₑₙₛ Gustedt
> > <jens.gustedt@inria.fr>) wrote:
> >   
> > > There is a feature test macro for the maximum width of bit-precise
> > > integers, `BITINT_MAXWIDTH`. It is guaranteed to be at least
> > > `ULLONG_WIDTH` but can (and will) be larger on many platforms.  
> > 
> > e.g on my ubuntu-nothing-fancy machine I get
> > 
> >  clang -E -dM -xc /dev/null | grep -i bitint
> >  #define __BITINT_MAXWIDTH__ 128  
> 
> As I understand it, that gives the application knowledge of what
> bit-precise types the compiler can provide to it, but doesn't do
> anything to tell the application what wN modifiers printf can be
> expected to support. If it were required to support wN for
> N==BITINT_MAXWIDTH that would at least be something to go from, but I
> see no such requirement and I'm not sure it's desirable (it means you
> can't let the compiler offer larger BITINT_MAXWIDTH, but would have to
> define it as what libc supports).
> 
> I think a separate macro indicating what printf supports is needed to
> solve this problem well.

That's an excellent point. It would be good if we filed a national
body comment for the ballot period to get such a thing in.

Jₑₙₛ

-- 
:: INRIA Nancy Grand Est ::: Camus ::::::: ICube/ICPS :::
:: :::::::::::::::::::::: gsm France : +33 651400183   ::
:: ::::::::::::::: gsm international : +49 15737185122 ::
:: http://icube-icps.unistra.fr/index.php/Jens_Gustedt ::

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [musl] [PATCH] vfprintf: support C2x %b and %B conversion specifiers
@ 2022-09-08 16:38 Gabriel Ravier
  0 siblings, 0 replies; 17+ messages in thread
From: Gabriel Ravier @ 2022-09-08 16:38 UTC (permalink / raw)
  To: musl; +Cc: Gabriel Ravier

These specifiers allow for formatted input/output of binary integers,
and have been added to C2x with N2630. The uppercase B specifier is
not formally required by C2x, as only lowercase specifiers were
reserved by C, and thus an implementation could have been using
uppercase B for an extension of their own, but C2x still has a note
saying that it is recommended practice to implement it as the logical
counterpart to b.

I have tested this on:
- glibc's tests for %b and %B
- The libc testsuite I'm developing over at https://github.com/GabrielRavier/yalibct
- musl's libc-test
- musl's libc-testsuite

and observed no regressions.
---
 src/stdio/vfprintf.c | 21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c
index 9b961e7f..89426b72 100644
--- a/src/stdio/vfprintf.c
+++ b/src/stdio/vfprintf.c
@@ -49,7 +49,7 @@ enum {
 static const unsigned char states[]['z'-'A'+1] = {
 	{ /* 0: bare types */
 		S('d') = INT, S('i') = INT,
-		S('o') = UINT, S('u') = UINT, S('x') = UINT, S('X') = UINT,
+		S('o') = UINT, S('u') = UINT, S('x') = UINT, S('X') = UINT, S('b') = UINT, S('B') = UINT,
 		S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL,
 		S('E') = DBL, S('F') = DBL, S('G') = DBL, S('A') = DBL,
 		S('c') = CHAR, S('C') = INT,
@@ -59,7 +59,7 @@ static const unsigned char states[]['z'-'A'+1] = {
 		S('z') = ZTPRE, S('j') = JPRE, S('t') = ZTPRE,
 	}, { /* 1: l-prefixed */
 		S('d') = LONG, S('i') = LONG,
-		S('o') = ULONG, S('u') = ULONG, S('x') = ULONG, S('X') = ULONG,
+		S('o') = ULONG, S('u') = ULONG, S('x') = ULONG, S('X') = ULONG, S('b') = ULONG, S('B') = ULONG,
 		S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL,
 		S('E') = DBL, S('F') = DBL, S('G') = DBL, S('A') = DBL,
 		S('c') = INT, S('s') = PTR, S('n') = PTR,
@@ -68,17 +68,20 @@ static const unsigned char states[]['z'-'A'+1] = {
 		S('d') = LLONG, S('i') = LLONG,
 		S('o') = ULLONG, S('u') = ULLONG,
 		S('x') = ULLONG, S('X') = ULLONG,
+		S('b') = ULLONG, S('B') = ULLONG,
 		S('n') = PTR,
 	}, { /* 3: h-prefixed */
 		S('d') = SHORT, S('i') = SHORT,
 		S('o') = USHORT, S('u') = USHORT,
 		S('x') = USHORT, S('X') = USHORT,
+		S('b') = USHORT, S('B') = USHORT,
 		S('n') = PTR,
 		S('h') = HHPRE,
 	}, { /* 4: hh-prefixed */
 		S('d') = CHAR, S('i') = CHAR,
 		S('o') = UCHAR, S('u') = UCHAR,
 		S('x') = UCHAR, S('X') = UCHAR,
+		S('b') = UCHAR, S('B') = UCHAR,
 		S('n') = PTR,
 	}, { /* 5: L-prefixed */
 		S('e') = LDBL, S('f') = LDBL, S('g') = LDBL, S('a') = LDBL,
@@ -88,11 +91,13 @@ static const unsigned char states[]['z'-'A'+1] = {
 		S('d') = PDIFF, S('i') = PDIFF,
 		S('o') = SIZET, S('u') = SIZET,
 		S('x') = SIZET, S('X') = SIZET,
+		S('b') = SIZET, S('B') = SIZET,
 		S('n') = PTR,
 	}, { /* 7: j-prefixed */
 		S('d') = IMAX, S('i') = IMAX,
 		S('o') = UMAX, S('u') = UMAX,
 		S('x') = UMAX, S('X') = UMAX,
+		S('b') = UMAX, S('B') = UMAX,
 		S('n') = PTR,
 	}
 };
@@ -162,6 +167,12 @@ static char *fmt_o(uintmax_t x, char *s)
 	return s;
 }
 
+static char *fmt_b(uintmax_t x, char *s)
+{
+	for (; x; x>>=1) *--s = '0' + (x&1);
+	return s;
+}
+
 static char *fmt_u(uintmax_t x, char *s)
 {
 	unsigned long y;
@@ -529,7 +540,7 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
 		if (!f) continue;
 
 		z = buf + sizeof(buf);
-		prefix = "-+   0X0x";
+		prefix = "-+   0X0x0B0b";
 		pl = 0;
 		t = s[-1];
 
@@ -559,6 +570,10 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
 			a = fmt_x(arg.i, z, t&32);
 			if (arg.i && (fl & ALT_FORM)) prefix+=(t>>4), pl=2;
 			if (0) {
+		case 'b': case 'B':
+			a = fmt_b(arg.i, z);
+			if (arg.i && (fl & ALT_FORM)) prefix += 9 + ((t == 'b') << 1), pl=2;
+			} if (0) {
 		case 'o':
 			a = fmt_o(arg.i, z);
 			if ((fl&ALT_FORM) && p<z-a+1) p=z-a+1;
-- 
2.37.3


^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2022-09-20 15:20 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-08 16:36 [musl] [PATCH] vfprintf: support C2x %b and %B conversion specifiers Gabriel Ravier
2022-09-12 13:59 ` Rich Felker
2022-09-12 14:42   ` Jₑₙₛ Gustedt
2022-09-19 15:09     ` Rich Felker
2022-09-19 17:59       ` Szabolcs Nagy
2022-09-19 18:10         ` Rich Felker
2022-09-20  9:19           ` Jₑₙₛ Gustedt
2022-09-20 12:28             ` Rich Felker
2022-09-20 13:29               ` Jₑₙₛ Gustedt
2022-09-20 13:55                 ` Rich Felker
2022-09-20 14:08                   ` Jₑₙₛ Gustedt
2022-09-20 14:15                     ` Rich Felker
2022-09-20 14:22                       ` Jₑₙₛ Gustedt
2022-09-20 14:27                         ` Jₑₙₛ Gustedt
2022-09-20 14:46                           ` Rich Felker
2022-09-20 15:20                             ` Jₑₙₛ Gustedt
2022-09-08 16:38 Gabriel Ravier

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).