* [musl] [PATCH] vfprintf: support C2x %b and %B conversion specifiers @ 2022-09-08 16:36 Gabriel Ravier 2022-09-12 13:59 ` Rich Felker ` (2 more replies) 0 siblings, 3 replies; 26+ 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] 26+ 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 2023-04-15 12:28 ` [musl] [PATCH v2 0/1] " Gabriel Ravier 2024-08-27 23:12 ` [musl] [PATCH v3 0/1] vfprintf: support C23 b and B " Gabriel Ravier 2 siblings, 1 reply; 26+ 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] 26+ 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; 26+ 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] 26+ 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; 26+ 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] 26+ 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; 26+ 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] 26+ 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; 26+ 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] 26+ 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; 26+ 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] 26+ 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; 26+ 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] 26+ 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; 26+ 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] 26+ 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; 26+ 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] 26+ 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; 26+ 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] 26+ 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; 26+ 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] 26+ 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; 26+ 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] 26+ 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; 26+ 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] 26+ 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; 26+ 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] 26+ 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; 26+ 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] 26+ messages in thread
* [musl] [PATCH v2 0/1] 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 @ 2023-04-15 12:28 ` Gabriel Ravier 2023-04-15 12:28 ` [musl] [PATCH v2 1/1] " Gabriel Ravier 2024-08-27 23:12 ` [musl] [PATCH v3 0/1] vfprintf: support C23 b and B " Gabriel Ravier 2 siblings, 1 reply; 26+ messages in thread From: Gabriel Ravier @ 2023-04-15 12:28 UTC (permalink / raw) To: musl; +Cc: Gabriel Ravier This updated version of the patch fixes the buffer overflow pointed out by Rich, and rebases it upon latest musl (the old version of the patch fails to apply on more recent versions). Gabriel Ravier (1): vfprintf: support C2x %b and %B conversion specifiers src/stdio/vfprintf.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) -- 2.39.2 ^ permalink raw reply [flat|nested] 26+ messages in thread
* [musl] [PATCH v2 1/1] vfprintf: support C2x %b and %B conversion specifiers 2023-04-15 12:28 ` [musl] [PATCH v2 0/1] " Gabriel Ravier @ 2023-04-15 12:28 ` Gabriel Ravier 2023-04-15 12:52 ` Jₑₙₛ Gustedt 2023-04-16 6:51 ` Jₑₙₛ Gustedt 0 siblings, 2 replies; 26+ messages in thread From: Gabriel Ravier @ 2023-04-15 12:28 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. --- src/stdio/vfprintf.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c index a712d80f..3d7e0aeb 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; @@ -437,7 +448,12 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg, unsigned st, ps; int cnt=0, l=0; size_t i; - char buf[sizeof(uintmax_t)*3+3+LDBL_MANT_DIG/4]; + /* This buffer is used for integer conversions. As such, it needs + * to be able to contain the full representation of a number in base 2, + * 8, 10 or 16, with base 2 having the largest possible requirement of + * as many characters as the amount of bits in the largest possible + * integer type */ + char buf[sizeof(uintmax_t)*CHAR_BIT]; const char *prefix; int t, pl; wchar_t wc[2], *ws; @@ -534,7 +550,7 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg, if (ferror(f)) return -1; z = buf + sizeof(buf); - prefix = "-+ 0X0x"; + prefix = "-+ 0X0x0B0b"; pl = 0; t = s[-1]; @@ -564,6 +580,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.39.2 ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [musl] [PATCH v2 1/1] vfprintf: support C2x %b and %B conversion specifiers 2023-04-15 12:28 ` [musl] [PATCH v2 1/1] " Gabriel Ravier @ 2023-04-15 12:52 ` Jₑₙₛ Gustedt 2023-04-15 13:15 ` Gabriel Ravier 2023-04-16 6:51 ` Jₑₙₛ Gustedt 1 sibling, 1 reply; 26+ messages in thread From: Jₑₙₛ Gustedt @ 2023-04-15 12:52 UTC (permalink / raw) To: Gabriel Ravier; +Cc: musl [-- Attachment #1: Type: text/plain, Size: 1354 bytes --] Hi, I was just working on these things, too. So great, one thing less on my list. Patch looks fine, but for the parts with the prefix, which I find suspicious, anyhow, too much black magic for me. What is still missing then, is to add PRIxYYY macros. With the latest draft https://open-std.org/JTC1/SC22/WG14/www/docs/n3096.pdf these become mandatory feature tests for this feature. I already have a patch for that. I also have already patches for - the wN and wfN length modifiers - an extension towards `[u]int128_t` - adding the `*_WIDTH` macros And I will soon be starting on the similar features for `scanf` and friends. There is one problem zone for that, namely that `0b` prefixes are not only extensions but change semantics of existing executables that would be linked against different versions of the C library. My plan is to make the distinction deep down in `__intscan` and have that internal function in two versions `__intscan_c17` and `__intscan_c23`, say. Thanks Jₑₙₛ -- :: ICube :::::::::::::::::::::::::::::: deputy director :: :: Université de Strasbourg :::::::::::::::::::::: ICPS :: :: INRIA Nancy Grand Est :::::::::::::::::::::::: Camus :: :: :::::::::::::::::::::::::::::::::::: ☎ +33 368854536 :: :: https://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] 26+ messages in thread
* Re: [musl] [PATCH v2 1/1] vfprintf: support C2x %b and %B conversion specifiers 2023-04-15 12:52 ` Jₑₙₛ Gustedt @ 2023-04-15 13:15 ` Gabriel Ravier 2023-04-15 14:15 ` Jₑₙₛ Gustedt 0 siblings, 1 reply; 26+ messages in thread From: Gabriel Ravier @ 2023-04-15 13:15 UTC (permalink / raw) To: Jₑₙₛ Gustedt; +Cc: musl On 4/15/23 14:52, Jₑₙₛ Gustedt wrote: > Hi, > I was just working on these things, too. So great, one thing less on > my list. > > Patch looks fine, but for the parts with the prefix, which I find > suspicious, anyhow, too much black magic for me. The parts with the prefix could instead be implemented as something like `"0B0b"+((t=='b')<<1)` (or something even cleaner, though it'd be a bit more verbose too) but I figured it was better to keep the same code style as for the hexadecimal conversion for now - changes to make it be less like black magic seem more like code style cleanup that probably aren't appropriate to put in the same patch (I suppose it also shaves off a single byte to do it the way its done right now, since a separate string would require an extra null terminator, and I highly doubt most compilers right now are able to figure out it's unneeded - to avoid taking an extra byte of space would require making a special array just for `0B0b` that specifically has a size of 4). > > What is still missing then, is to add PRIxYYY macros. With the latest > draft > > https://open-std.org/JTC1/SC22/WG14/www/docs/n3096.pdf > > these become mandatory feature tests for this feature. I already have > a patch for that. Nice to have a patch for that too, thanks. I wasn't planning on adding them myself, mostly because I don't really have any tests for them (as opposed to the b/B conversion specifiers which I have plenty of tests for) and don't plan on adding any anytime soon. > > I also have already patches for > > - the wN and wfN length modifiers > > - an extension towards `[u]int128_t` > > - adding the `*_WIDTH` macros > > And I will soon be starting on the similar features for `scanf` and > friends. There is one problem zone for that, namely that `0b` prefixes > are not only extensions but change semantics of existing executables > that would be linked against different versions of the C library. > > My plan is to make the distinction deep down in `__intscan` and have > that internal function in two versions `__intscan_c17` and > `__intscan_c23`, say. Doesn't the same apply to strto{,u}l{,l} given the behavior change is caused by the corresponding change in those functions ? > > Thanks > Jₑₙₛ > ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [musl] [PATCH v2 1/1] vfprintf: support C2x %b and %B conversion specifiers 2023-04-15 13:15 ` Gabriel Ravier @ 2023-04-15 14:15 ` Jₑₙₛ Gustedt 0 siblings, 0 replies; 26+ messages in thread From: Jₑₙₛ Gustedt @ 2023-04-15 14:15 UTC (permalink / raw) To: Gabriel Ravier; +Cc: musl [-- Attachment #1: Type: text/plain, Size: 2105 bytes --] Gabriel, on Sat, 15 Apr 2023 15:15:48 +0200 you (Gabriel Ravier <gabravier@gmail.com>) wrote: > > What is still missing then, is to add PRIxYYY macros. With the > > latest draft > > > > https://open-std.org/JTC1/SC22/WG14/www/docs/n3096.pdf > > > > these become mandatory feature tests for this feature. I already > > have a patch for that. > Nice to have a patch for that too, thanks. I wasn't planning on > adding them myself, mostly because I don't really have any tests for > them (as opposed to the b/B conversion specifiers which I have plenty > of tests for) and don't plan on adding any anytime soon. As said they are now mandatory, because the `B` also changes state from just "recommended" to "recommended optional". The git message could also reflect that. What I noticed after sending my mail, you are also missing to do the same for vfwprintf which unfortunately doubles the logic, here. A refactoring for these two functions could probably gain some kilo or so. > > And I will soon be starting on the similar features for `scanf` and > > friends. There is one problem zone for that, namely that `0b` > > prefixes are not only extensions but change semantics of existing > > executables that would be linked against different versions of the > > C library. > > > > My plan is to make the distinction deep down in `__intscan` and have > > that internal function in two versions `__intscan_c17` and > > `__intscan_c23`, say. > Doesn't the same apply to strto{,u}l{,l} given the behavior change is > caused by the corresponding change in those functions ? Yes. I have a very generous notion of "friend" ;-) They all use that same function __intscan underneath, so this factors out cleanly, it seems. Thanks Jₑₙₛ -- :: ICube :::::::::::::::::::::::::::::: deputy director :: :: Université de Strasbourg :::::::::::::::::::::: ICPS :: :: INRIA Nancy Grand Est :::::::::::::::::::::::: Camus :: :: :::::::::::::::::::::::::::::::::::: ☎ +33 368854536 :: :: https://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] 26+ messages in thread
* Re: [musl] [PATCH v2 1/1] vfprintf: support C2x %b and %B conversion specifiers 2023-04-15 12:28 ` [musl] [PATCH v2 1/1] " Gabriel Ravier 2023-04-15 12:52 ` Jₑₙₛ Gustedt @ 2023-04-16 6:51 ` Jₑₙₛ Gustedt 2023-04-16 13:20 ` Gabriel Ravier 1 sibling, 1 reply; 26+ messages in thread From: Jₑₙₛ Gustedt @ 2023-04-16 6:51 UTC (permalink / raw) To: Gabriel Ravier; +Cc: musl [-- Attachment #1: Type: text/plain, Size: 935 bytes --] Gabriel, it also seems to me that ... on Sat, 15 Apr 2023 14:28:28 +0200 you (Gabriel Ravier <gabravier@gmail.com>) wrote: > + /* This buffer is used for integer conversions. As such, it needs > + * to be able to contain the full representation of a number in base 2, > + * 8, 10 or 16, with base 2 having the largest possible requirement of > + * as many characters as the amount of bits in the largest > possible > + * integer type */ > + char buf[sizeof(uintmax_t)*CHAR_BIT]; ... here a `+3` seems to be in order to take care of the `0[bx]` prefix and a terminating null byte. Thanks Jₑₙₛ -- :: ICube :::::::::::::::::::::::::::::: deputy director :: :: Université de Strasbourg :::::::::::::::::::::: ICPS :: :: INRIA Nancy Grand Est :::::::::::::::::::::::: Camus :: :: :::::::::::::::::::::::::::::::::::: ☎ +33 368854536 :: :: https://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] 26+ messages in thread
* Re: [musl] [PATCH v2 1/1] vfprintf: support C2x %b and %B conversion specifiers 2023-04-16 6:51 ` Jₑₙₛ Gustedt @ 2023-04-16 13:20 ` Gabriel Ravier 2023-04-16 14:39 ` Rich Felker 0 siblings, 1 reply; 26+ messages in thread From: Gabriel Ravier @ 2023-04-16 13:20 UTC (permalink / raw) To: Jₑₙₛ Gustedt; +Cc: musl On 4/16/23 08:51, Jₑₙₛ Gustedt wrote: > Gabriel, > it also seems to me that ... > > on Sat, 15 Apr 2023 14:28:28 +0200 you (Gabriel Ravier > <gabravier@gmail.com>) wrote: > >> + /* This buffer is used for integer conversions. As such, it needs >> + * to be able to contain the full representation of a number in base 2, >> + * 8, 10 or 16, with base 2 having the largest possible requirement of >> + * as many characters as the amount of bits in the largest >> possible >> + * integer type */ >> + char buf[sizeof(uintmax_t)*CHAR_BIT]; > ... here a `+3` seems to be in order to take care of the `0[bx]` > prefix and a terminating null byte. This buffer is only used specifically for storing converted digits, and is never used to store the alternative form, and never contains a null terminator either as the code knows the used length and never passes the buffer to a function that doesn't do so, so from what I can see these objections are wrong (in fact it wouldn't make much sense to store the prefix in that buffer given that the code also has to handle the possibility of extremely large 0-padding that goes between the prefix and the converted digits). Though perhaps the comment could be improved, I suppose it could be confusing... > > Thanks > Jₑₙₛ > ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [musl] [PATCH v2 1/1] vfprintf: support C2x %b and %B conversion specifiers 2023-04-16 13:20 ` Gabriel Ravier @ 2023-04-16 14:39 ` Rich Felker 0 siblings, 0 replies; 26+ messages in thread From: Rich Felker @ 2023-04-16 14:39 UTC (permalink / raw) To: Gabriel Ravier; +Cc: Jₑₙₛ Gustedt, musl On Sun, Apr 16, 2023 at 03:20:59PM +0200, Gabriel Ravier wrote: > On 4/16/23 08:51, Jₑₙₛ Gustedt wrote: > >Gabriel, > >it also seems to me that ... > > > >on Sat, 15 Apr 2023 14:28:28 +0200 you (Gabriel Ravier > ><gabravier@gmail.com>) wrote: > > > >>+ /* This buffer is used for integer conversions. As such, it needs > >>+ * to be able to contain the full representation of a number in base 2, > >>+ * 8, 10 or 16, with base 2 having the largest possible requirement of > >>+ * as many characters as the amount of bits in the largest > >>possible > >>+ * integer type */ > >>+ char buf[sizeof(uintmax_t)*CHAR_BIT]; > >... here a `+3` seems to be in order to take care of the `0[bx]` > >prefix and a terminating null byte. > > This buffer is only used specifically for storing converted digits, > and is never used to store the alternative form, and never contains > a null terminator either as the code knows the used length and never > passes the buffer to a function that doesn't do so, so from what I > can see these objections are wrong (in fact it wouldn't make much > sense to store the prefix in that buffer given that the code also > has to handle the possibility of extremely large 0-padding that goes > between the prefix and the converted digits). > > Though perhaps the comment could be improved, I suppose it could be > confusing... Yes, without looking I'm pretty sure you're right about what the buffer is and isn't used for. I think both the +3 and the +LDBL_MANT_DIG/4 are artifacts of proto-musl code long ago where things were done differently and floating point code was also in the main printf_core function and did naive floating point math. Maybe these should be fixed with a separate patch first (which I could make and explain what I recall of the history) so this unrelated change isn't a distraction from the %b patches. Rich ^ permalink raw reply [flat|nested] 26+ messages in thread
* [musl] [PATCH v3 0/1] vfprintf: support C23 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 2023-04-15 12:28 ` [musl] [PATCH v2 0/1] " Gabriel Ravier @ 2024-08-27 23:12 ` Gabriel Ravier 2024-08-27 23:12 ` [musl] [PATCH v3 1/1] " Gabriel Ravier 2 siblings, 1 reply; 26+ messages in thread From: Gabriel Ravier @ 2024-08-27 23:12 UTC (permalink / raw) To: musl; +Cc: Gabriel Ravier This updated version of the patch: - rebases it on latest musl (the old version of the patch fails to apply on current git) - clarifies the comment before the declaration of buf slightly to make it less potentially confusing - adjusts the commit message since C2x is now officially C23 Gabriel Ravier (1): vfprintf: support C23 b and B conversion specifiers src/stdio/vfprintf.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) -- 2.46.0 ^ permalink raw reply [flat|nested] 26+ messages in thread
* [musl] [PATCH v3 1/1] vfprintf: support C23 b and B conversion specifiers 2024-08-27 23:12 ` [musl] [PATCH v3 0/1] vfprintf: support C23 b and B " Gabriel Ravier @ 2024-08-27 23:12 ` Gabriel Ravier 0 siblings, 0 replies; 26+ messages in thread From: Gabriel Ravier @ 2024-08-27 23:12 UTC (permalink / raw) To: musl; +Cc: Gabriel Ravier These specifiers allow for formatted output of binary integers, and have been added to C23 through N2630. The uppoercase B specifier is not made entirely mandatory by C23, as only lowercase specifiers are reserved for the standard, and thus an implementation could have been using uppercase B for an unrelated extension, but C23 still has a note stating it is recommended practice to implement it as the uppercase counterpart of the b specifier. 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 | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c index 360d723a..ec51aa3c 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') = INT, S('C') = UINT, @@ -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') = UINT, 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, } }; @@ -150,6 +155,12 @@ static const char xdigits[16] = { "0123456789ABCDEF" }; +static char *fmt_b(uintmax_t x, char *s) +{ + for (; x; x>>=1) *--s = '0' + (x&1); + return s; +} + static char *fmt_x(uintmax_t x, char *s, int lower) { for (; x; x>>=4) *--s = xdigits[(x&15)]|lower; @@ -431,7 +442,12 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg, unsigned st, ps; int cnt=0, l=0; size_t i; - char buf[sizeof(uintmax_t)*3]; + /* This buffer is used for integer conversions. As such, it needs + * to be able to contain the full representation of a number (without a + * prefix/padding or null terminator) in base 2, 8, 10 or 16, with base + * 2 having the largest possible requirement of as many characters as + * the amount of bits in the largest possible integer type */ + char buf[sizeof(uintmax_t)*CHAR_BIT]; const char *prefix; int t, pl; wchar_t wc[2], *ws; @@ -528,7 +544,7 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg, if (ferror(f)) return -1; z = buf + sizeof(buf); - prefix = "-+ 0X0x"; + prefix = "-+ 0X0x0B0b"; pl = 0; t = s[-1]; @@ -558,6 +574,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.46.0 ^ permalink raw reply [flat|nested] 26+ messages in thread
end of thread, other threads:[~2024-08-27 23:12 UTC | newest] Thread overview: 26+ 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 2023-04-15 12:28 ` [musl] [PATCH v2 0/1] " Gabriel Ravier 2023-04-15 12:28 ` [musl] [PATCH v2 1/1] " Gabriel Ravier 2023-04-15 12:52 ` Jₑₙₛ Gustedt 2023-04-15 13:15 ` Gabriel Ravier 2023-04-15 14:15 ` Jₑₙₛ Gustedt 2023-04-16 6:51 ` Jₑₙₛ Gustedt 2023-04-16 13:20 ` Gabriel Ravier 2023-04-16 14:39 ` Rich Felker 2024-08-27 23:12 ` [musl] [PATCH v3 0/1] vfprintf: support C23 b and B " Gabriel Ravier 2024-08-27 23:12 ` [musl] [PATCH v3 1/1] " 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).