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;