aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS7
-rw-r--r--manual/stdio.texi18
-rw-r--r--stdio-common/Makefile1
-rw-r--r--stdio-common/printf-parse.h9
-rw-r--r--stdio-common/printf-parsemb.c56
-rw-r--r--stdio-common/printf-prs.c3
-rw-r--r--stdio-common/tst-printf-intn-main.c637
-rw-r--r--stdio-common/tst-printf-intn.c26
-rw-r--r--stdio-common/vfprintf-internal.c82
-rw-r--r--wcsmbs/Makefile1
-rw-r--r--wcsmbs/tst-wprintf-intn.c26
11 files changed, 851 insertions, 15 deletions
diff --git a/NEWS b/NEWS
index 7a4df85f08..7cec03cc76 100644
--- a/NEWS
+++ b/NEWS
@@ -21,6 +21,13 @@ Major new features:
* PRIb* and PRIB* macros from C2X have been added to <inttypes.h>.
+* printf-family functions now support the wN format length modifiers for
+ arguments of type intN_t, int_leastN_t, uintN_t or uint_leastN_t (for
+ example, %w32d to print int32_t or int_least32_t in decimal, or %w32x
+ to print uint32_t or uint_least32_t in hexadecimal) and the wfN format
+ length modifiers for arguments of type int_fastN_t or uint_fastN_t, as
+ specified in draft ISO C2X.
+
* A new tunable, glibc.pthread.stack_hugetlb, can be used to disable
Transparent Huge Pages (THP) in stack allocation at pthread_create.
diff --git a/manual/stdio.texi b/manual/stdio.texi
index 3820a24f3e..a981e6512a 100644
--- a/manual/stdio.texi
+++ b/manual/stdio.texi
@@ -2028,6 +2028,24 @@ Specifies that the argument is a @code{ptrdiff_t}.
This modifier was introduced in @w{ISO C99}.
+@item w@var{n}
+Specifies that the argument is a @code{int@var{n}_t} or
+@code{int_least@var{n}_t} (which are the same type), for conversions
+taking signed integers, or @code{uint@var{n}_t} or
+@code{uint_least@var{n}_t} (which are the same type), for conversions
+taking unsigned integers. If the type is narrower than @code{int},
+the promoted argument is converted back to the specified type.
+
+This modifier was introduced in @w{ISO C2X}.
+
+@item wf@var{n}
+Specifies that the argument is a @code{int_fast@var{n}_t} or
+@code{uint_fast@var{n}_t}, as appropriate. If the type is narrower
+than @code{int}, the promoted argument is converted back to the
+specified type.
+
+This modifier was introduced in @w{ISO C2X}.
+
@item z
@itemx Z
Specifies that the argument is a @code{size_t}.
diff --git a/stdio-common/Makefile b/stdio-common/Makefile
index 4c15b97683..8871ec7668 100644
--- a/stdio-common/Makefile
+++ b/stdio-common/Makefile
@@ -219,6 +219,7 @@ tests := \
tst-printf-bz25691 \
tst-printf-fp-free \
tst-printf-fp-leak \
+ tst-printf-intn \
tst-printf-oct \
tst-printf-round \
tst-printfsz \
diff --git a/stdio-common/printf-parse.h b/stdio-common/printf-parse.h
index b25181496c..57673a331d 100644
--- a/stdio-common/printf-parse.h
+++ b/stdio-common/printf-parse.h
@@ -93,14 +93,17 @@ __find_specwc (const unsigned int *format)
with the parsed details. POSN is the number of arguments already
consumed. At most MAXTYPES - POSN types are filled in TYPES. Return
the number of args consumed by this spec; *MAX_REF_ARG is updated so it
- remains the highest argument index used. */
+ remains the highest argument index used. *FAILED is set to indicate
+ whether parsing failed and printf should return with an error status. */
extern size_t __parse_one_specmb (const unsigned char *format, size_t posn,
struct printf_spec *spec,
- size_t *max_ref_arg) attribute_hidden;
+ size_t *max_ref_arg,
+ bool *failed) attribute_hidden;
extern size_t __parse_one_specwc (const unsigned int *format, size_t posn,
struct printf_spec *spec,
- size_t *max_ref_arg) attribute_hidden;
+ size_t *max_ref_arg,
+ bool *failed) attribute_hidden;
diff --git a/stdio-common/printf-parsemb.c b/stdio-common/printf-parsemb.c
index c5d2704b02..414cbc7223 100644
--- a/stdio-common/printf-parsemb.c
+++ b/stdio-common/printf-parsemb.c
@@ -56,14 +56,17 @@ size_t
attribute_hidden
#ifdef COMPILE_WPRINTF
__parse_one_specwc (const UCHAR_T *format, size_t posn,
- struct printf_spec *spec, size_t *max_ref_arg)
+ struct printf_spec *spec, size_t *max_ref_arg,
+ bool *failed)
#else
__parse_one_specmb (const UCHAR_T *format, size_t posn,
- struct printf_spec *spec, size_t *max_ref_arg)
+ struct printf_spec *spec, size_t *max_ref_arg,
+ bool *failed)
#endif
{
unsigned int n;
size_t nargs = 0;
+ bool is_fast;
/* Skip the '%'. */
++format;
@@ -81,6 +84,8 @@ __parse_one_specmb (const UCHAR_T *format, size_t posn,
spec->info.wide = sizeof (UCHAR_T) > 1;
spec->info.is_binary128 = 0;
+ *failed = false;
+
/* Test for positional argument. */
if (ISDIGIT (*format))
{
@@ -298,6 +303,53 @@ __parse_one_specmb (const UCHAR_T *format, size_t posn,
#endif
spec->info.is_long = sizeof (uintmax_t) > sizeof (unsigned int);
break;
+ case L_('w'):
+ is_fast = false;
+ if (*format == L_('f'))
+ {
+ ++format;
+ is_fast = true;
+ }
+ int bitwidth = 0;
+ if (ISDIGIT (*format))
+ bitwidth = read_int (&format);
+ if (is_fast)
+ switch (bitwidth)
+ {
+ case 8:
+ bitwidth = INT_FAST8_WIDTH;
+ break;
+ case 16:
+ bitwidth = INT_FAST16_WIDTH;
+ break;
+ case 32:
+ bitwidth = INT_FAST32_WIDTH;
+ break;
+ case 64:
+ bitwidth = INT_FAST64_WIDTH;
+ break;
+ }
+ switch (bitwidth)
+ {
+ case 8:
+ spec->info.is_char = 1;
+ break;
+ case 16:
+ spec->info.is_short = 1;
+ break;
+ case 32:
+ break;
+ case 64:
+ spec->info.is_long_double = 1;
+ spec->info.is_long = 1;
+ break;
+ default:
+ /* ISO C requires this error to be detected. */
+ __set_errno (EINVAL);
+ *failed = true;
+ break;
+ }
+ break;
default:
/* Not a recognized modifier. Backup. */
--format;
diff --git a/stdio-common/printf-prs.c b/stdio-common/printf-prs.c
index 2408a2e328..9d8bf306e4 100644
--- a/stdio-common/printf-prs.c
+++ b/stdio-common/printf-prs.c
@@ -63,6 +63,7 @@ parse_printf_format (const char *fmt, size_t n, int *argtypes)
size_t max_ref_arg; /* Highest index used in a positional arg. */
struct printf_spec spec;
const unsigned char *f = (const unsigned char *) fmt;
+ bool failed;
nargs = 0;
max_ref_arg = 0;
@@ -71,7 +72,7 @@ parse_printf_format (const char *fmt, size_t n, int *argtypes)
for (f = __find_specmb (f); *f != '\0'; f = spec.next_fmt)
{
/* Parse this spec. */
- nargs += __parse_one_specmb (f, nargs, &spec, &max_ref_arg);
+ nargs += __parse_one_specmb (f, nargs, &spec, &max_ref_arg, &failed);
/* If the width is determined by an argument, it is an int. */
if (spec.width_arg != -1 && (size_t) spec.width_arg < n)
diff --git a/stdio-common/tst-printf-intn-main.c b/stdio-common/tst-printf-intn-main.c
new file mode 100644
index 0000000000..bd70e9de73
--- /dev/null
+++ b/stdio-common/tst-printf-intn-main.c
@@ -0,0 +1,637 @@
+/* Test printf formats for intN_t, int_leastN_t and int_fastN_t types.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <wchar.h>
+
+#include <libc-diag.h>
+#include <support/check.h>
+
+/* GCC does not know the %wN or %wfN length modifiers before GCC 13. */
+DIAG_PUSH_NEEDS_COMMENT;
+#if !__GNUC_PREREQ (13, 0)
+DIAG_IGNORE_NEEDS_COMMENT (12, "-Wformat");
+DIAG_IGNORE_NEEDS_COMMENT (12, "-Wformat-extra-args");
+#endif
+
+#define CHECK_PRINTF(EXPECTED, FMT, ...) \
+ do \
+ { \
+ int ret = SNPRINTF (buf, sizeof buf / sizeof buf[0], L_(FMT), \
+ __VA_ARGS__); \
+ TEST_COMPARE_STRING_MACRO (buf, L_(EXPECTED)); \
+ TEST_COMPARE (ret, STRLEN (L_(EXPECTED))); \
+ } \
+ while (0)
+
+#define CHECK_PRINTF_ERR(FMT, ...) \
+ do \
+ { \
+ int ret = SNPRINTF (buf, sizeof buf / sizeof buf[0], L_(FMT), \
+ __VA_ARGS__); \
+ TEST_VERIFY (ret < 0); \
+ TEST_COMPARE (errno, EINVAL); \
+ } \
+ while (0)
+
+static void
+test_w8 (void)
+{
+ CHAR buf[1024];
+ CHECK_PRINTF ("123", "%w8d", (int8_t) 123);
+ CHECK_PRINTF ("-123", "%w8d", (int8_t) -123);
+ CHECK_PRINTF ("123", "%w8i", (int8_t) 123);
+ CHECK_PRINTF ("-123", "%w8i", (int8_t) -123);
+ CHECK_PRINTF ("1111011", "%w8b", (uint8_t) 123);
+ CHECK_PRINTF ("1111011", "%w8B", (uint8_t) 123);
+ CHECK_PRINTF ("173", "%w8o", (uint8_t) 123);
+ CHECK_PRINTF ("123", "%w8u", (uint8_t) 123);
+ CHECK_PRINTF ("7b", "%w8x", (uint8_t) 123);
+ CHECK_PRINTF ("7B", "%w8X", (uint8_t) 123);
+ CHECK_PRINTF (" 123", "%5w8d", (int8_t) 123);
+ CHECK_PRINTF (" 123", "%*w8d", 5, (int8_t) 123);
+ CHECK_PRINTF ("0x7b", "%#w8x", (uint8_t) 123);
+ CHECK_PRINTF ("00123", "%.5w8d", (int8_t) 123);
+ CHECK_PRINTF ("00123", "%.*w8d", 5, (int8_t) 123);
+ CHECK_PRINTF (" 00123", "%8.5w8d", (int8_t) 123);
+ CHECK_PRINTF (" 00123", "%*.5w8d", 8, (int8_t) 123);
+ CHECK_PRINTF (" 00123", "%8.*w8d", 5, (int8_t) 123);
+ CHECK_PRINTF (" 00123", "%*.*w8d", 8, 5, (int8_t) 123);
+ CHECK_PRINTF ("00123 ", "%-8.5w8d", (int8_t) 123);
+ CHECK_PRINTF ("00123 ", "%-*.5w8d", 8, (int8_t) 123);
+ CHECK_PRINTF ("00123 ", "%-8.*w8d", 5, (int8_t) 123);
+ CHECK_PRINTF ("00123 ", "%-*.*w8d", 8, 5, (int8_t) 123);
+ {
+ int8_t n = -1;
+ CHECK_PRINTF ("12345", "%d%w8n", 12345, &n);
+ TEST_COMPARE (n, 5);
+ }
+ CHECK_PRINTF ("123", "%w8d", (int_least8_t) 123);
+ CHECK_PRINTF ("-123", "%w8d", (int_least8_t) -123);
+ CHECK_PRINTF ("123", "%w8i", (int_least8_t) 123);
+ CHECK_PRINTF ("-123", "%w8i", (int_least8_t) -123);
+ CHECK_PRINTF ("1111011", "%w8b", (uint_least8_t) 123);
+ CHECK_PRINTF ("1111011", "%w8B", (uint_least8_t) 123);
+ CHECK_PRINTF ("173", "%w8o", (uint_least8_t) 123);
+ CHECK_PRINTF ("123", "%w8u", (uint_least8_t) 123);
+ CHECK_PRINTF ("7b", "%w8x", (uint_least8_t) 123);
+ CHECK_PRINTF ("7B", "%w8X", (uint_least8_t) 123);
+ CHECK_PRINTF (" 123", "%5w8d", (int_least8_t) 123);
+ CHECK_PRINTF (" 123", "%*w8d", 5, (int_least8_t) 123);
+ CHECK_PRINTF ("0x7b", "%#w8x", (uint_least8_t) 123);
+ CHECK_PRINTF ("00123", "%.5w8d", (int_least8_t) 123);
+ CHECK_PRINTF ("00123", "%.*w8d", 5, (int_least8_t) 123);
+ CHECK_PRINTF (" 00123", "%8.5w8d", (int_least8_t) 123);
+ CHECK_PRINTF (" 00123", "%*.5w8d", 8, (int_least8_t) 123);
+ CHECK_PRINTF (" 00123", "%8.*w8d", 5, (int_least8_t) 123);
+ CHECK_PRINTF (" 00123", "%*.*w8d", 8, 5, (int_least8_t) 123);
+ CHECK_PRINTF ("00123 ", "%-8.5w8d", (int_least8_t) 123);
+ CHECK_PRINTF ("00123 ", "%-*.5w8d", 8, (int_least8_t) 123);
+ CHECK_PRINTF ("00123 ", "%-8.*w8d", 5, (int_least8_t) 123);
+ CHECK_PRINTF ("00123 ", "%-*.*w8d", 8, 5, (int_least8_t) 123);
+ {
+ int_least8_t ln = -1;
+ CHECK_PRINTF ("12345", "%d%w8n", 12345, &ln);
+ TEST_COMPARE (ln, 5);
+ }
+ /* Test truncation of value in promoted type not representable in
+ narrower type. */
+ CHECK_PRINTF ("57", "%w8d", 12345);
+ CHECK_PRINTF ("-57", "%w8d", -12345);
+ CHECK_PRINTF ("-121", "%w8d", 1234567);
+ CHECK_PRINTF ("121", "%w8d", -1234567);
+ CHECK_PRINTF ("135", "%w8u", 1234567);
+ /* Test positional argument handling. */
+ CHECK_PRINTF ("test 10 test2 20", "%4$s %3$w8d %2$s %1$w8d",
+ 276, "test2", 266, "test");
+}
+
+static void
+test_wf8 (void)
+{
+ CHAR buf[1024];
+ _Static_assert (sizeof (int_fast8_t) == sizeof (char),
+ "test assumes size of int_fast8_t");
+ CHECK_PRINTF ("123", "%wf8d", (int_fast8_t) 123);
+ CHECK_PRINTF ("-123", "%wf8d", (int_fast8_t) -123);
+ CHECK_PRINTF ("123", "%wf8i", (int_fast8_t) 123);
+ CHECK_PRINTF ("-123", "%wf8i", (int_fast8_t) -123);
+ CHECK_PRINTF ("1111011", "%wf8b", (uint_fast8_t) 123);
+ CHECK_PRINTF ("1111011", "%wf8B", (uint_fast8_t) 123);
+ CHECK_PRINTF ("173", "%wf8o", (uint_fast8_t) 123);
+ CHECK_PRINTF ("123", "%wf8u", (uint_fast8_t) 123);
+ CHECK_PRINTF ("7b", "%wf8x", (uint_fast8_t) 123);
+ CHECK_PRINTF ("7B", "%wf8X", (uint_fast8_t) 123);
+ CHECK_PRINTF (" 123", "%5w8d", (int_fast8_t) 123);
+ CHECK_PRINTF (" 123", "%*w8d", 5, (int_fast8_t) 123);
+ CHECK_PRINTF ("0x7b", "%#w8x", (uint_fast8_t) 123);
+ CHECK_PRINTF ("00123", "%.5w8d", (int_fast8_t) 123);
+ CHECK_PRINTF ("00123", "%.*w8d", 5, (int_fast8_t) 123);
+ CHECK_PRINTF (" 00123", "%8.5w8d", (int_fast8_t) 123);
+ CHECK_PRINTF (" 00123", "%*.5w8d", 8, (int_fast8_t) 123);
+ CHECK_PRINTF (" 00123", "%8.*w8d", 5, (int_fast8_t) 123);
+ CHECK_PRINTF (" 00123", "%*.*w8d", 8, 5, (int_fast8_t) 123);
+ CHECK_PRINTF ("00123 ", "%-8.5w8d", (int_fast8_t) 123);
+ CHECK_PRINTF ("00123 ", "%-*.5w8d", 8, (int_fast8_t) 123);
+ CHECK_PRINTF ("00123 ", "%-8.*w8d", 5, (int_fast8_t) 123);
+ CHECK_PRINTF ("00123 ", "%-*.*w8d", 8, 5, (int_fast8_t) 123);
+ {
+ int_fast8_t n = -1;
+ CHECK_PRINTF ("12345", "%d%wf8n", 12345, &n);
+ TEST_COMPARE (n, 5);
+ }
+ /* Test truncation of value in promoted type not representable in
+ narrower type. */
+ CHECK_PRINTF ("57", "%wf8d", 12345);
+ CHECK_PRINTF ("-57", "%wf8d", -12345);
+ CHECK_PRINTF ("-121", "%wf8d", 1234567);
+ CHECK_PRINTF ("121", "%wf8d", -1234567);
+ CHECK_PRINTF ("135", "%wf8u", 1234567);
+ /* Test positional argument handling. */
+ CHECK_PRINTF ("test 10 test2 20", "%4$s %3$wf8d %2$s %1$wf8d",
+ 276, "test2", 266, "test");
+}
+
+static void
+test_w16 (void)
+{
+ CHAR buf[1024];
+ CHECK_PRINTF ("12345", "%w16d", (int16_t) 12345);
+ CHECK_PRINTF ("-12345", "%w16d", (int16_t) -12345);
+ CHECK_PRINTF ("12345", "%w16i", (int16_t) 12345);
+ CHECK_PRINTF ("-12345", "%w16i", (int16_t) -12345);
+ CHECK_PRINTF ("11000000111001", "%w16b", (uint16_t) 12345);
+ CHECK_PRINTF ("11000000111001", "%w16B", (uint16_t) 12345);
+ CHECK_PRINTF ("30071", "%w16o", (uint16_t) 12345);
+ CHECK_PRINTF ("12345", "%w16u", (uint16_t) 12345);
+ CHECK_PRINTF ("303a", "%w16x", (uint16_t) 12346);
+ CHECK_PRINTF ("303A", "%w16X", (uint16_t) 12346);
+ CHECK_PRINTF (" 12345", "%7w16d", (int16_t) 12345);
+ CHECK_PRINTF (" 12345", "%*w16d", 7, (int16_t) 12345);
+ CHECK_PRINTF ("0x3039", "%#w16x", (uint16_t) 12345);
+ CHECK_PRINTF ("0012345", "%.7w16d", (int16_t) 12345);
+ CHECK_PRINTF ("0012345", "%.*w16d", 7, (int16_t) 12345);
+ CHECK_PRINTF (" 0012345", "%10.7w16d", (int16_t) 12345);
+ CHECK_PRINTF (" 0012345", "%*.7w16d", 10, (int16_t) 12345);
+ CHECK_PRINTF (" 0012345", "%10.*w16d", 7, (int16_t) 12345);
+ CHECK_PRINTF (" 0012345", "%*.*w16d", 10, 7, (int16_t) 12345);
+ CHECK_PRINTF ("0012345 ", "%-10.7w16d", (int16_t) 12345);
+ CHECK_PRINTF ("0012345 ", "%-*.7w16d", 10, (int16_t) 12345);
+ CHECK_PRINTF ("0012345 ", "%-10.*w16d", 7, (int16_t) 12345);
+ CHECK_PRINTF ("0012345 ", "%-*.*w16d", 10, 7, (int16_t) 12345);
+ {
+ int16_t n = -1;
+ CHECK_PRINTF ("12345", "%d%w16n", 12345, &n);
+ TEST_COMPARE (n, 5);
+ }
+ CHECK_PRINTF ("12345", "%w16d", (int_least16_t) 12345);
+ CHECK_PRINTF ("-12345", "%w16d", (int_least16_t) -12345);
+ CHECK_PRINTF ("12345", "%w16i", (int_least16_t) 12345);
+ CHECK_PRINTF ("-12345", "%w16i", (int_least16_t) -12345);
+ CHECK_PRINTF ("11000000111001", "%w16b", (uint_least16_t) 12345);
+ CHECK_PRINTF ("11000000111001", "%w16B", (uint_least16_t) 12345);
+ CHECK_PRINTF ("30071", "%w16o", (uint_least16_t) 12345);
+ CHECK_PRINTF ("12345", "%w16u", (uint_least16_t) 12345);
+ CHECK_PRINTF ("303a", "%w16x", (uint_least16_t) 12346);
+ CHECK_PRINTF ("303A", "%w16X", (uint_least16_t) 12346);
+ CHECK_PRINTF (" 12345", "%7w16d", (int_least16_t) 12345);
+ CHECK_PRINTF (" 12345", "%*w16d", 7, (int_least16_t) 12345);
+ CHECK_PRINTF ("0x3039", "%#w16x", (uint_least16_t) 12345);
+ CHECK_PRINTF ("0012345", "%.7w16d", (int_least16_t) 12345);
+ CHECK_PRINTF ("0012345", "%.*w16d", 7, (int_least16_t) 12345);
+ CHECK_PRINTF (" 0012345", "%10.7w16d", (int_least16_t) 12345);
+ CHECK_PRINTF (" 0012345", "%*.7w16d", 10, (int_least16_t) 12345);
+ CHECK_PRINTF (" 0012345", "%10.*w16d", 7, (int_least16_t) 12345);
+ CHECK_PRINTF (" 0012345", "%*.*w16d", 10, 7, (int_least16_t) 12345);
+ CHECK_PRINTF ("0012345 ", "%-10.7w16d", (int_least16_t) 12345);
+ CHECK_PRINTF ("0012345 ", "%-*.7w16d", 10, (int_least16_t) 12345);
+ CHECK_PRINTF ("0012345 ", "%-10.*w16d", 7, (int_least16_t) 12345);
+ CHECK_PRINTF ("0012345 ", "%-*.*w16d", 10, 7, (int_least16_t) 12345);
+ {
+ int_least16_t ln = -1;
+ CHECK_PRINTF ("12345", "%d%w16n", 12345, &ln);
+ TEST_COMPARE (ln, 5);
+ }
+ /* Test truncation of value in promoted type not representable in
+ narrower type. */
+ CHECK_PRINTF ("4464", "%w16d", 70000);
+ CHECK_PRINTF ("-4464", "%w16d", -70000);
+ CHECK_PRINTF ("-7616", "%w16d", 123456);
+ CHECK_PRINTF ("7616", "%w16d", -123456);
+ CHECK_PRINTF ("57920", "%w16u", 123456);
+ /* Test positional argument handling. */
+ CHECK_PRINTF ("test 10 test2 20", "%4$s %3$w16d %2$s %1$w16d",
+ 65556, "test2", 65546, "test");
+}
+
+static void
+test_wf16 (void)
+{
+ CHAR buf[1024];
+ _Static_assert (sizeof (int_fast16_t) == sizeof (long int),
+ "test assumes size of int_fast16_t");
+ CHECK_PRINTF ("1234567", "%wf16d", (int_fast16_t) 1234567);
+ CHECK_PRINTF ("-1234567", "%wf16d", (int_fast16_t) -1234567);
+ CHECK_PRINTF ("1234567", "%wf16i", (int_fast16_t) 1234567);
+ CHECK_PRINTF ("-1234567", "%wf16i", (int_fast16_t) -1234567);
+ CHECK_PRINTF ("100101101011010000111", "%wf16b", (uint_fast16_t) 1234567);
+ CHECK_PRINTF ("100101101011010000111", "%wf16B", (uint_fast16_t) 1234567);
+ CHECK_PRINTF ("4553207", "%wf16o", (uint_fast16_t) 1234567);
+ CHECK_PRINTF ("1234567", "%wf16u", (uint_fast16_t) 1234567);
+ CHECK_PRINTF ("12d687", "%wf16x", (uint_fast16_t) 1234567);
+ CHECK_PRINTF ("12D687", "%wf16X", (uint_fast16_t) 1234567);
+ CHECK_PRINTF (" 1234567", "%9wf16d", (int_fast16_t) 1234567);
+ CHECK_PRINTF (" 1234567", "%*wf16d", 9, (int_fast16_t) 1234567);
+ CHECK_PRINTF ("0x12d687", "%#wf16x", (uint_fast16_t) 1234567);
+ CHECK_PRINTF ("001234567", "%.9wf16d", (int_fast16_t) 1234567);
+ CHECK_PRINTF ("001234567", "%.*wf16d", 9, (int_fast16_t) 1234567);
+ CHECK_PRINTF (" 001234567", "%12.9wf16d", (int_fast16_t) 1234567);
+ CHECK_PRINTF (" 001234567", "%*.9wf16d", 12, (int_fast16_t) 1234567);
+ CHECK_PRINTF (" 001234567", "%12.*wf16d", 9, (int_fast16_t) 1234567);
+ CHECK_PRINTF (" 001234567", "%*.*wf16d", 12, 9, (int_fast16_t) 1234567);
+ CHECK_PRINTF ("001234567 ", "%-12.9wf16d", (int_fast16_t) 1234567);
+ CHECK_PRINTF ("001234567 ", "%-*.9wf16d", 12, (int_fast16_t) 1234567);
+ CHECK_PRINTF ("001234567 ", "%-12.*wf16d", 9, (int_fast16_t) 1234567);
+ CHECK_PRINTF ("001234567 ", "%-*.*wf16d", 12, 9, (int_fast16_t) 1234567);
+ {
+ int_fast16_t n = -1;
+ CHECK_PRINTF ("12345", "%d%wf16n", 12345, &n);
+ TEST_COMPARE (n, 5);
+ }
+ /* Test positional argument handling. */
+ CHECK_PRINTF ("test 123456 test2 234567", "%4$s %3$wf16d %2$s %1$wf16d",
+ (int_fast16_t) 234567, "test2", (int_fast16_t) 123456, "test");
+#if INT_FAST16_MAX > 0x7fffffff
+ CHECK_PRINTF ("12345678901", "%wf16d", (int_fast16_t) 12345678901LL);
+ CHECK_PRINTF ("-12345678901", "%wf16d", (int_fast16_t) -12345678901LL);
+ CHECK_PRINTF ("12345678901", "%wf16i", (int_fast16_t) 12345678901LL);
+ CHECK_PRINTF ("-12345678901", "%wf16i", (int_fast16_t) -12345678901LL);
+ CHECK_PRINTF ("1011011111110111000001110000110101", "%wf16b",
+ (uint_fast16_t) 12345678901LL);
+ CHECK_PRINTF ("1011011111110111000001110000110101", "%wf16B",
+ (uint_fast16_t) 12345678901LL);
+ CHECK_PRINTF ("133767016065", "%wf16o", (uint_fast16_t) 12345678901LL);
+ CHECK_PRINTF ("12345678901", "%wf16u", (uint_fast16_t) 12345678901LL);
+ CHECK_PRINTF ("2dfdc1c35", "%wf16x", (uint_fast16_t) 12345678901LL);
+ CHECK_PRINTF ("2DFDC1C35", "%wf16X", (uint_fast16_t) 12345678901LL);
+ CHECK_PRINTF (" 12345678901", "%13wf16d", (int_fast16_t) 12345678901LL);
+ CHECK_PRINTF (" 12345678901", "%*wf16d", 13, (int_fast16_t) 12345678901LL);
+ CHECK_PRINTF ("0x2dfdc1c35", "%#wf16x", (uint_fast16_t) 12345678901LL);
+ CHECK_PRINTF ("0012345678901", "%.13wf16d", (int_fast16_t) 12345678901LL);
+ CHECK_PRINTF ("0012345678901", "%.*wf16d", 13, (int_fast16_t) 12345678901LL);
+ CHECK_PRINTF (" 0012345678901", "%16.13wf16d",
+ (int_fast16_t) 12345678901LL);
+ CHECK_PRINTF (" 0012345678901", "%*.13wf16d", 16,
+ (int_fast16_t) 12345678901LL);
+ CHECK_PRINTF (" 0012345678901", "%16.*wf16d", 13,
+ (int_fast16_t) 12345678901LL);
+ CHECK_PRINTF (" 0012345678901", "%*.*wf16d", 16, 13,
+ (int_fast16_t) 12345678901LL);
+ CHECK_PRINTF ("0012345678901 ", "%-16.13wf16d",
+ (int_fast16_t) 12345678901LL);
+ CHECK_PRINTF ("0012345678901 ", "%-*.13wf16d", 16,
+ (int_fast16_t) 12345678901LL);
+ CHECK_PRINTF ("0012345678901 ", "%-16.*wf16d", 13,
+ (int_fast16_t) 12345678901LL);
+ CHECK_PRINTF ("0012345678901 ", "%-*.*wf16d", 16, 13,
+ (int_fast16_t) 12345678901LL);
+ /* Test positional argument handling. */
+ CHECK_PRINTF ("test 123456789012 test2 234567890123",
+ "%4$s %3$wf16d %2$s %1$wf16d",
+ (int_fast16_t) 234567890123ULL, "test2",
+ (int_fast16_t) 123456789012ULL, "test");
+#endif
+}
+
+static void
+test_w32 (void)
+{
+ CHAR buf[1024];
+ CHECK_PRINTF ("1234567", "%w32d", (int32_t) 1234567);
+ CHECK_PRINTF ("-1234567", "%w32d", (int32_t) -1234567);
+ CHECK_PRINTF ("1234567", "%w32i", (int32_t) 1234567);
+ CHECK_PRINTF ("-1234567", "%w32i", (int32_t) -1234567);
+ CHECK_PRINTF ("100101101011010000111", "%w32b", (uint32_t) 1234567);
+ CHECK_PRINTF ("100101101011010000111", "%w32B", (uint32_t) 1234567);
+ CHECK_PRINTF ("4553207", "%w32o", (uint32_t) 1234567);
+ CHECK_PRINTF ("1234567", "%w32u", (uint32_t) 1234567);
+ CHECK_PRINTF ("12d687", "%w32x", (uint32_t) 1234567);
+ CHECK_PRINTF ("12D687", "%w32X", (uint32_t) 1234567);
+ CHECK_PRINTF (" 1234567", "%9w32d", (int32_t) 1234567);
+ CHECK_PRINTF (" 1234567", "%*w32d", 9, (int32_t) 1234567);
+ CHECK_PRINTF ("0x12d687", "%#w32x", (uint32_t) 1234567);
+ CHECK_PRINTF ("001234567", "%.9w32d", (int32_t) 1234567);
+ CHECK_PRINTF ("001234567", "%.*w32d", 9, (int32_t) 1234567);
+ CHECK_PRINTF (" 001234567", "%12.9w32d", (int32_t) 1234567);
+ CHECK_PRINTF (" 001234567", "%*.9w32d", 12, (int32_t) 1234567);
+ CHECK_PRINTF (" 001234567", "%12.*w32d", 9, (int32_t) 1234567);
+ CHECK_PRINTF (" 001234567", "%*.*w32d", 12, 9, (int32_t) 1234567);
+ CHECK_PRINTF ("001234567 ", "%-12.9w32d", (int32_t) 1234567);
+ CHECK_PRINTF ("001234567 ", "%-*.9w32d", 12, (int32_t) 1234567);
+ CHECK_PRINTF ("001234567 ", "%-12.*w32d", 9, (int32_t) 1234567);
+ CHECK_PRINTF ("001234567 ", "%-*.*w32d", 12, 9, (int32_t) 1234567);
+ {
+ int32_t n = -1;
+ CHECK_PRINTF ("12345", "%d%w32n", 12345, &n);
+ TEST_COMPARE (n, 5);
+ }
+ CHECK_PRINTF ("1234567", "%w32d", (int_least32_t) 1234567);
+ CHECK_PRINTF ("-1234567", "%w32d", (int_least32_t) -1234567);
+ CHECK_PRINTF ("1234567", "%w32i", (int_least32_t) 1234567);
+ CHECK_PRINTF ("-1234567", "%w32i", (int_least32_t) -1234567);
+ CHECK_PRINTF ("100101101011010000111", "%w32b", (uint_least32_t) 1234567);
+ CHECK_PRINTF ("100101101011010000111", "%w32B", (uint_least32_t) 1234567);