This is an automated email from the ASF dual-hosted git repository. acassis pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 096eaab879a35cef4126ecb01a36a62345230639 Author: Marco Casaroli <[email protected]> AuthorDate: Thu Nov 5 15:52:16 2026 +0100 libs/libc/stream: Add an option for %b and %B of C23 in printf(). printf() took %b and %B as unknown conversions. Add the option LIBC_PRINTF_C23, on in the Full profile, and off in the Minimal and Default profiles. With the option off they stay unknown conversions: the rest of the format prints as text and no argument is read. The conversion prints the integer in binary, with the prefix 0b or 0B for the # flag. The conversion buffer has room for all bits of the integer when the option is on. Part of https://github.com/apache/nuttx/issues/21467 Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Marco Casaroli <[email protected]> --- libs/libc/stdio/Kconfig | 8 +++++++ libs/libc/stream/lib_libvsprintf.c | 43 +++++++++++++++++++++++++++++++++++--- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/libs/libc/stdio/Kconfig b/libs/libc/stdio/Kconfig index 342063804da..2fd24d14401 100644 --- a/libs/libc/stdio/Kconfig +++ b/libs/libc/stdio/Kconfig @@ -139,6 +139,14 @@ config LIBC_PRINTF_HEXFLOAT does not need LIBC_FLOATINGPOINT and it pulls in no soft-float code. Without it, printf() reads the argument and prints "?". +config LIBC_PRINTF_C23 + bool "Enable the C23 conversions in printf" + default LIBC_PRINTF_FULL + ---help--- + Enables %b and %B, the binary output of an integer. Without it, + they are unknown conversions: printf() prints the rest of the format + as text and reads no more arguments. + config LIBC_FLOATINGPOINT bool "Enable floating point in printf" default LIBC_PRINTF_FULL || (!DEFAULT_SMALL && ARCH_FPU && !LIBC_PRINTF_MINIMAL) diff --git a/libs/libc/stream/lib_libvsprintf.c b/libs/libc/stream/lib_libvsprintf.c index c65400f0199..0b8b6f18de7 100644 --- a/libs/libc/stream/lib_libvsprintf.c +++ b/libs/libc/stream/lib_libvsprintf.c @@ -104,6 +104,18 @@ #define FL_FLTEXP 0x4000 #define FL_FLTFIX 0x8000 +/* %b and %B: only an integer conversion has this bit. A flag that is 0 lets + * the compiler remove the code of its feature. + */ + +#ifdef CONFIG_LIBC_PRINTF_C23 +# define FL_ALTBIN 0x8000 +# define fmt_isbinary(c) (((c) | 0x20) == 'b') +#else +# define FL_ALTBIN 0 +# define fmt_isbinary(c) 0 +#endif + /* The # flag. FL_ALT stays for the prefix of %p. A flag that is 0 lets the * compiler remove the code of its feature. */ @@ -513,7 +525,11 @@ static int vsprintf_internal(FAR struct lib_outstream_s *stream, int prec; union { +#ifdef CONFIG_LIBC_PRINTF_C23 + char __buf[sizeof(ultoa_uint_t) * CHAR_BIT]; /* -1 in binary */ +#else char __buf[22]; /* Size for -1 in octal, without '\0' */ +#endif #ifdef CONFIG_LIBC_FLOATINGPOINT struct dtoa_s __dtoa; #endif @@ -920,7 +936,7 @@ set_star: type = FL_IS_LDOUBLE(flags) ? TYPE_LONG_DOUBLE : TYPE_DOUBLE; } else if (c == 'i' || c == 'd' || c == 'u' || c == 'p' || - c == 'o' || c == 'x' || c == 'X') + c == 'o' || c == 'x' || c == 'X' || fmt_isbinary(c)) { if ((flags & FL_LONG) == 0) { @@ -1641,7 +1657,8 @@ str_lpad: c = __ultoa_invert(x, buf, 10) - buf; } } - else if (c != 'u' && c != 'o' && c != 'p' && (c | 0x20) != 'x') + else if (c != 'u' && c != 'o' && c != 'p' && (c | 0x20) != 'x' && + !fmt_isbinary(c)) { /* An unknown conversion, or the end of the format. The size of * the argument is not known, so read no more arguments. Print the @@ -1816,6 +1833,25 @@ str_lpad: base = 16; break; +#ifdef CONFIG_LIBC_PRINTF_C23 + case 'B': + if ((flags & FL_ALT_FORM) != 0) + { + flags |= FL_ALTUPP; + } + + /* FALLTHROUGH */ + + case 'b': + if ((flags & FL_ALT_FORM) != 0) + { + flags |= FL_ALTHEX | FL_ALTBIN; + } + + base = 2; + break; +#endif + default: /* 'X' */ if ((flags & FL_ALT_FORM) != 0) { @@ -1914,8 +1950,9 @@ str_lpad: stream_putc('0', stream); if (FL_ALT_IS_HEX(flags)) { + ch = (flags & FL_ALTBIN) != 0 ? 'b' : 'x'; stream_putc(FL_ALT_FORM != 0 && (flags & FL_ALTUPP) != 0 ? - 'X' : 'x', stream); + ch - 0x20 : ch, stream); } } else if ((flags & (FL_NEGATIVE | FL_PLUS | FL_SPACE)) != 0)
