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

Reply via email to