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 6e033f5af51d0d2213f30eff4a84bcdedd39550b Author: Marco Casaroli <[email protected]> AuthorDate: Thu Nov 5 15:53:44 2026 +0100 libs/libc/stream: Add the C23 wN and wfN lengths to printf(). With the option LIBC_PRINTF_C23 on, printf() takes the length modifiers wN and wfN for the sizes 8, 16, 32 and 64, as in %w64d and %wf16x. The parser sets the flags of the standard length with this size, so the argument, the conversion and the numbered arguments work as for that length. LIBC_PRINTF_SHORT and LIBC_PRINTF_LONG_LONG apply in the same way. Any other size stays an unknown conversion. With the option off, all of them are unknown conversions, so %w64d prints as text. 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 | 7 ++-- libs/libc/stream/lib_libvsprintf.c | 86 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 3 deletions(-) diff --git a/libs/libc/stdio/Kconfig b/libs/libc/stdio/Kconfig index 2fd24d14401..745977ea366 100644 --- a/libs/libc/stdio/Kconfig +++ b/libs/libc/stdio/Kconfig @@ -143,9 +143,10 @@ 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. + Enables %b and %B, the binary output of an integer, and the wN and + wfN length modifiers, as in %w64d and %wf32x. 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" diff --git a/libs/libc/stream/lib_libvsprintf.c b/libs/libc/stream/lib_libvsprintf.c index 0b8b6f18de7..eb0d16bf6d3 100644 --- a/libs/libc/stream/lib_libvsprintf.c +++ b/libs/libc/stream/lib_libvsprintf.c @@ -393,6 +393,80 @@ static int vsprintf_putnum(FAR struct lib_outstream_s *stream, return len; } +#ifdef CONFIG_LIBC_PRINTF_C23 +/* Parse the rest of wN or wfN, and set the flags of the length that has this + * size. Return false for any other N, with fmt after the w. + */ + +static bool vsprintf_wnlength(FAR const IPTR char **fmtp, + FAR uint16_t *flags) +{ + FAR const IPTR char *fmt = *fmtp; + size_t size; + int bits = 0; + bool fast; + int ch; + + ch = fmt_char(fmt); + fast = ch == 'f'; + if (fast) + { + ch = fmt_char(fmt); + } + + while (ch >= '0' && ch <= '9' && bits < 100) + { + bits = 10 * bits + (ch - '0'); + ch = fmt_char(fmt); + } + + fmt_ungetc(fmt); + + switch (bits) + { + case 8: + size = fast ? sizeof(int_fast8_t) : sizeof(int8_t); + break; + + case 16: + size = fast ? sizeof(int_fast16_t) : sizeof(int16_t); + break; + + case 32: + size = fast ? sizeof(int_fast32_t) : sizeof(int32_t); + break; + + case 64: + size = sizeof(int64_t); + break; + + default: + return false; + } + + *fmtp = fmt; + + if (size == sizeof(signed char)) + { + *flags |= FL_SHORT | FL_REPD_TYPE; + } + else if (size == sizeof(short) && size != sizeof(int)) + { + *flags |= FL_SHORT; + } + else if (size == sizeof(long) && size != sizeof(int)) + { + *flags |= FL_LONG; + } + else if (size != sizeof(int)) + { + *flags |= FL_LONG | FL_REPD_TYPE; + } + + return true; +} +#endif + #ifdef CONFIG_LIBC_PRINTF_HEXFLOAT static size_t vsprintf_puthex(FAR struct lib_outstream_s *stream, FAR struct hexfloat_s *hex, uint16_t flags, @@ -847,6 +921,18 @@ set_star: } } +#ifdef CONFIG_LIBC_PRINTF_C23 + if (c == 'w') + { + if (vsprintf_wnlength(&fmt, &flags)) + { + continue; + } + + break; /* An unknown size: the rest of the format is text */ + } +#endif + if (c == 'j') { /* Same as long long if available. Otherwise, long. */
