Implement C23 printf 'w' length modifiers

wN: Specifies that a following b, d, i, o, u, x, or X
conversion specifier applies to an integer argument with
a specific width where N is a positive decimal integer with
no leading zeros

Bug: b/271903607
Test: adb shell
Change-Id: I688f6cefeb2e5c8325b007a59935a46f4116ac29
diff --git a/libc/stdio/printf_common.h b/libc/stdio/printf_common.h
index e761835..b0055f0 100644
--- a/libc/stdio/printf_common.h
+++ b/libc/stdio/printf_common.h
@@ -528,6 +528,17 @@
       case 'b':
         ADDUARG();
         break;
+      case 'w':
+        n = 0;
+        ch = *fmt++;
+        while (is_digit(ch)) {
+          APPEND_DIGIT(n, ch);
+          ch = *fmt++;
+        }
+        if (n == 64) {
+          flags |= LLONGINT;
+        }
+        goto reswitch;
       default: /* "%?" prints ?, unless ? is NUL */
         if (ch == '\0') goto done;
         break;
diff --git a/libc/stdio/vfprintf.cpp b/libc/stdio/vfprintf.cpp
index d83a5bf..b7c68dd 100644
--- a/libc/stdio/vfprintf.cpp
+++ b/libc/stdio/vfprintf.cpp
@@ -521,6 +521,34 @@
         _umax = UARG();
         base = DEC;
         goto nosign;
+      case 'w':
+        n = 0;
+        ch = *fmt++;
+        while (is_digit(ch)) {
+          APPEND_DIGIT(n, ch);
+          ch = *fmt++;
+        }
+        switch (n) {
+          case 8: {
+            flags |= CHARINT;
+            goto reswitch;
+          }
+          case 16: {
+            flags |= SHORTINT;
+            goto reswitch;
+          }
+          case 32: {
+            goto reswitch;
+          }
+          case 64: {
+            flags |= LLONGINT;
+            goto reswitch;
+          }
+          default: {
+            __fortify_fatal("%%w%d is unsupported", n);
+            break;
+          }
+        }
       case 'X':
         xdigs = xdigs_upper;
         goto hex;
diff --git a/libc/stdio/vfwprintf.cpp b/libc/stdio/vfwprintf.cpp
index 9819a73..52ae64b 100644
--- a/libc/stdio/vfwprintf.cpp
+++ b/libc/stdio/vfwprintf.cpp
@@ -510,6 +510,34 @@
         _umax = UARG();
         base = DEC;
         goto nosign;
+      case 'w':
+        n = 0;
+        ch = *fmt++;
+        while (is_digit(ch)) {
+          APPEND_DIGIT(n, ch);
+          ch = *fmt++;
+        }
+        switch (n) {
+          case 8: {
+            flags |= CHARINT;
+            goto reswitch;
+          }
+          case 16: {
+            flags |= SHORTINT;
+            goto reswitch;
+          }
+          case 32: {
+            goto reswitch;
+          }
+          case 64: {
+            flags |= LLONGINT;
+            goto reswitch;
+          }
+          default: {
+            __fortify_fatal("%%w%d is unsupported", n);
+            break;
+          }
+        }
       case 'X':
         xdigs = xdigs_upper;
         goto hex;