C2x printf %wN, %wfN support (bug 24466)

ISO C2x defines printf length modifiers wN (for intN_t / int_leastN_t
/ uintN_t / uint_leastN_t) and wfN (for int_fastN_t / uint_fastN_t).
Add support for those length modifiers (such a feature was previously
requested in bug 24466).  scanf support is to be added separately.
GCC 13 has format checking support for these modifiers.

When used with the support for registering format specifiers, these
modifiers are translated to existing flags in struct printf_info,
rather than trying to add some way of distinguishing them without
breaking the printf_info ABI.  C2x requires an error to be returned
for unsupported values of N; this is implemented for printf-family
functions, but the parse_printf_format interface doesn't support error
returns, so such an error gets discarded by that function.

Tested for x86_64 and x86.
This commit is contained in:
Joseph Myers 2023-06-19 18:52:12 +00:00
parent 8022fc7d51
commit 5f83b2674e
11 changed files with 851 additions and 15 deletions

7
NEWS
View File

@ -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.

View File

@ -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}.

View File

@ -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 \

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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);
CHECK_PRINTF ("4553207", "%w32o", (uint_least32_t) 1234567);
CHECK_PRINTF ("1234567", "%w32u", (uint_least32_t) 1234567);
CHECK_PRINTF ("12d687", "%w32x", (uint_least32_t) 1234567);
CHECK_PRINTF ("12D687", "%w32X", (uint_least32_t) 1234567);
CHECK_PRINTF (" 1234567", "%9w32d", (int_least32_t) 1234567);
CHECK_PRINTF (" 1234567", "%*w32d", 9, (int_least32_t) 1234567);
CHECK_PRINTF ("0x12d687", "%#w32x", (uint_least32_t) 1234567);
CHECK_PRINTF ("001234567", "%.9w32d", (int_least32_t) 1234567);
CHECK_PRINTF ("001234567", "%.*w32d", 9, (int_least32_t) 1234567);
CHECK_PRINTF (" 001234567", "%12.9w32d", (int_least32_t) 1234567);
CHECK_PRINTF (" 001234567", "%*.9w32d", 12, (int_least32_t) 1234567);
CHECK_PRINTF (" 001234567", "%12.*w32d", 9, (int_least32_t) 1234567);
CHECK_PRINTF (" 001234567", "%*.*w32d", 12, 9, (int_least32_t) 1234567);
CHECK_PRINTF ("001234567 ", "%-12.9w32d", (int_least32_t) 1234567);
CHECK_PRINTF ("001234567 ", "%-*.9w32d", 12, (int_least32_t) 1234567);
CHECK_PRINTF ("001234567 ", "%-12.*w32d", 9, (int_least32_t) 1234567);
CHECK_PRINTF ("001234567 ", "%-*.*w32d", 12, 9, (int_least32_t) 1234567);
{
int_least32_t ln = -1;
CHECK_PRINTF ("12345", "%d%w32n", 12345, &ln);
TEST_COMPARE (ln, 5);
}
/* Test positional argument handling. */
CHECK_PRINTF ("test 123456 test2 234567", "%4$s %3$w32d %2$s %1$w32d",
INT32_C (234567), "test2", INT32_C (123456), "test");
}
static void
test_wf32 (void)
{
CHAR buf[1024];
_Static_assert (sizeof (int_fast32_t) == sizeof (long int),
"test assumes size of int_fast32_t");
CHECK_PRINTF ("1234567", "%wf32d", (int_fast32_t) 1234567);
CHECK_PRINTF ("-1234567", "%wf32d", (int_fast32_t) -1234567);
CHECK_PRINTF ("1234567", "%wf32i", (int_fast32_t) 1234567);
CHECK_PRINTF ("-1234567", "%wf32i", (int_fast32_t) -1234567);
CHECK_PRINTF ("100101101011010000111", "%wf32b", (uint_fast32_t) 1234567);
CHECK_PRINTF ("100101101011010000111", "%wf32B", (uint_fast32_t) 1234567);
CHECK_PRINTF ("4553207", "%wf32o", (uint_fast32_t) 1234567);
CHECK_PRINTF ("1234567", "%wf32u", (uint_fast32_t) 1234567);
CHECK_PRINTF ("12d687", "%wf32x", (uint_fast32_t) 1234567);
CHECK_PRINTF ("12D687", "%wf32X", (uint_fast32_t) 1234567);
CHECK_PRINTF (" 1234567", "%9wf32d", (int_fast32_t) 1234567);
CHECK_PRINTF (" 1234567", "%*wf32d", 9, (int_fast32_t) 1234567);
CHECK_PRINTF ("0x12d687", "%#wf32x", (uint_fast32_t) 1234567);
CHECK_PRINTF ("001234567", "%.9wf32d", (int_fast32_t) 1234567);
CHECK_PRINTF ("001234567", "%.*wf32d", 9, (int_fast32_t) 1234567);
CHECK_PRINTF (" 001234567", "%12.9wf32d", (int_fast32_t) 1234567);
CHECK_PRINTF (" 001234567", "%*.9wf32d", 12, (int_fast32_t) 1234567);
CHECK_PRINTF (" 001234567", "%12.*wf32d", 9, (int_fast32_t) 1234567);
CHECK_PRINTF (" 001234567", "%*.*wf32d", 12, 9, (int_fast32_t) 1234567);
CHECK_PRINTF ("001234567 ", "%-12.9wf32d", (int_fast32_t) 1234567);
CHECK_PRINTF ("001234567 ", "%-*.9wf32d", 12, (int_fast32_t) 1234567);
CHECK_PRINTF ("001234567 ", "%-12.*wf32d", 9, (int_fast32_t) 1234567);
CHECK_PRINTF ("001234567 ", "%-*.*wf32d", 12, 9, (int_fast32_t) 1234567);
{
int_fast32_t n = -1;
CHECK_PRINTF ("12345", "%d%wf32n", 12345, &n);
TEST_COMPARE (n, 5);
}
/* Test positional argument handling. */
CHECK_PRINTF ("test 123456 test2 234567", "%4$s %3$wf32d %2$s %1$wf32d",
(int_fast32_t) 234567, "test2", (int_fast32_t) 123456, "test");
#if INT_FAST32_MAX > 0x7fffffff
CHECK_PRINTF ("12345678901", "%wf32d", (int_fast32_t) 12345678901LL);
CHECK_PRINTF ("-12345678901", "%wf32d", (int_fast32_t) -12345678901LL);
CHECK_PRINTF ("12345678901", "%wf32i", (int_fast32_t) 12345678901LL);
CHECK_PRINTF ("-12345678901", "%wf32i", (int_fast32_t) -12345678901LL);
CHECK_PRINTF ("1011011111110111000001110000110101", "%wf32b",
(uint_fast32_t) 12345678901LL);
CHECK_PRINTF ("1011011111110111000001110000110101", "%wf32B",
(uint_fast32_t) 12345678901LL);
CHECK_PRINTF ("133767016065", "%wf32o", (uint_fast32_t) 12345678901LL);
CHECK_PRINTF ("12345678901", "%wf32u", (uint_fast32_t) 12345678901LL);
CHECK_PRINTF ("2dfdc1c35", "%wf32x", (uint_fast32_t) 12345678901LL);
CHECK_PRINTF ("2DFDC1C35", "%wf32X", (uint_fast32_t) 12345678901LL);
CHECK_PRINTF (" 12345678901", "%13wf32d", (int_fast32_t) 12345678901LL);
CHECK_PRINTF (" 12345678901", "%*wf32d", 13, (int_fast32_t) 12345678901LL);
CHECK_PRINTF ("0x2dfdc1c35", "%#wf32x", (uint_fast32_t) 12345678901LL);
CHECK_PRINTF ("0012345678901", "%.13wf32d", (int_fast32_t) 12345678901LL);
CHECK_PRINTF ("0012345678901", "%.*wf32d", 13, (int_fast32_t) 12345678901LL);
CHECK_PRINTF (" 0012345678901", "%16.13wf32d",
(int_fast32_t) 12345678901LL);
CHECK_PRINTF (" 0012345678901", "%*.13wf32d", 16,
(int_fast32_t) 12345678901LL);
CHECK_PRINTF (" 0012345678901", "%16.*wf32d", 13,
(int_fast32_t) 12345678901LL);
CHECK_PRINTF (" 0012345678901", "%*.*wf32d", 16, 13,
(int_fast32_t) 12345678901LL);
CHECK_PRINTF ("0012345678901 ", "%-16.13wf32d",
(int_fast32_t) 12345678901LL);
CHECK_PRINTF ("0012345678901 ", "%-*.13wf32d", 16,
(int_fast32_t) 12345678901LL);
CHECK_PRINTF ("0012345678901 ", "%-16.*wf32d", 13,
(int_fast32_t) 12345678901LL);
CHECK_PRINTF ("0012345678901 ", "%-*.*wf32d", 16, 13,
(int_fast32_t) 12345678901LL);
/* Test positional argument handling. */
CHECK_PRINTF ("test 123456789012 test2 234567890123",
"%4$s %3$wf32d %2$s %1$wf32d",
(int_fast32_t) 234567890123ULL, "test2",
(int_fast32_t) 123456789012ULL, "test");
#endif
}
static void
test_w64 (void)
{
CHAR buf[1024];
CHECK_PRINTF ("12345678901", "%w64d", (int64_t) 12345678901LL);
CHECK_PRINTF ("-12345678901", "%w64d", (int64_t) -12345678901LL);
CHECK_PRINTF ("12345678901", "%w64i", (int64_t) 12345678901LL);
CHECK_PRINTF ("-12345678901", "%w64i", (int64_t) -12345678901LL);
CHECK_PRINTF ("1011011111110111000001110000110101", "%w64b",
(uint64_t) 12345678901LL);
CHECK_PRINTF ("1011011111110111000001110000110101", "%w64B",
(uint64_t) 12345678901LL);
CHECK_PRINTF ("133767016065", "%w64o", (uint64_t) 12345678901LL);
CHECK_PRINTF ("12345678901", "%w64u", (uint64_t) 12345678901LL);
CHECK_PRINTF ("2dfdc1c35", "%w64x", (uint64_t) 12345678901LL);
CHECK_PRINTF ("2DFDC1C35", "%w64X", (uint64_t) 12345678901LL);
CHECK_PRINTF (" 12345678901", "%13w64d", (int64_t) 12345678901LL);
CHECK_PRINTF (" 12345678901", "%*w64d", 13, (int64_t) 12345678901LL);
CHECK_PRINTF ("0x2dfdc1c35", "%#w64x", (uint64_t) 12345678901LL);
CHECK_PRINTF ("0012345678901", "%.13w64d", (int64_t) 12345678901LL);
CHECK_PRINTF ("0012345678901", "%.*w64d", 13, (int64_t) 12345678901LL);
CHECK_PRINTF (" 0012345678901", "%16.13w64d", (int64_t) 12345678901LL);
CHECK_PRINTF (" 0012345678901", "%*.13w64d", 16, (int64_t) 12345678901LL);
CHECK_PRINTF (" 0012345678901", "%16.*w64d", 13, (int64_t) 12345678901LL);
CHECK_PRINTF (" 0012345678901", "%*.*w64d", 16, 13,
(int64_t) 12345678901LL);
CHECK_PRINTF ("0012345678901 ", "%-16.13w64d", (int64_t) 12345678901LL);
CHECK_PRINTF ("0012345678901 ", "%-*.13w64d", 16, (int64_t) 12345678901LL);
CHECK_PRINTF ("0012345678901 ", "%-16.*w64d", 13, (int64_t) 12345678901LL);
CHECK_PRINTF ("0012345678901 ", "%-*.*w64d", 16, 13,
(int64_t) 12345678901LL);
{
int64_t n = -1;
CHECK_PRINTF ("12345", "%d%w64n", 12345, &n);
TEST_COMPARE (n, 5);
}
CHECK_PRINTF ("12345678901", "%w64d", (int_least64_t) 12345678901LL);
CHECK_PRINTF ("-12345678901", "%w64d", (int_least64_t) -12345678901LL);
CHECK_PRINTF ("12345678901", "%w64i", (int_least64_t) 12345678901LL);
CHECK_PRINTF ("-12345678901", "%w64i", (int_least64_t) -12345678901LL);
CHECK_PRINTF ("1011011111110111000001110000110101", "%w64b",
(uint_least64_t) 12345678901LL);
CHECK_PRINTF ("1011011111110111000001110000110101", "%w64B",
(uint_least64_t) 12345678901LL);
CHECK_PRINTF ("133767016065", "%w64o", (uint_least64_t) 12345678901LL);
CHECK_PRINTF ("12345678901", "%w64u", (uint_least64_t) 12345678901LL);
CHECK_PRINTF ("2dfdc1c35", "%w64x", (uint_least64_t) 12345678901LL);
CHECK_PRINTF ("2DFDC1C35", "%w64X", (uint_least64_t) 12345678901LL);
CHECK_PRINTF (" 12345678901", "%13w64d", (int_least64_t) 12345678901LL);
CHECK_PRINTF (" 12345678901", "%*w64d", 13, (int_least64_t) 12345678901LL);
CHECK_PRINTF ("0x2dfdc1c35", "%#w64x", (uint_least64_t) 12345678901LL);
CHECK_PRINTF ("0012345678901", "%.13w64d", (int_least64_t) 12345678901LL);
CHECK_PRINTF ("0012345678901", "%.*w64d", 13, (int_least64_t) 12345678901LL);
CHECK_PRINTF (" 0012345678901", "%16.13w64d",
(int_least64_t) 12345678901LL);
CHECK_PRINTF (" 0012345678901", "%*.13w64d", 16,
(int_least64_t) 12345678901LL);
CHECK_PRINTF (" 0012345678901", "%16.*w64d", 13,
(int_least64_t) 12345678901LL);
CHECK_PRINTF (" 0012345678901", "%*.*w64d", 16, 13,
(int_least64_t) 12345678901LL);
CHECK_PRINTF ("0012345678901 ", "%-16.13w64d",
(int_least64_t) 12345678901LL);
CHECK_PRINTF ("0012345678901 ", "%-*.13w64d", 16,
(int_least64_t) 12345678901LL);
CHECK_PRINTF ("0012345678901 ", "%-16.*w64d", 13,
(int_least64_t) 12345678901LL);
CHECK_PRINTF ("0012345678901 ", "%-*.*w64d", 16, 13,
(int_least64_t) 12345678901LL);
{
int_least64_t ln = -1;
CHECK_PRINTF ("12345", "%d%w64n", 12345, &ln);
TEST_COMPARE (ln, 5);
}
/* Test positional argument handling. */
CHECK_PRINTF ("test 123456789012 test2 234567890123",
"%4$s %3$w64d %2$s %1$w64d",
INT64_C (234567890123), "test2",
INT64_C (123456789012), "test");
}
static void
test_wf64 (void)
{
CHAR buf[1024];
_Static_assert (sizeof (int_fast64_t) == sizeof (long long int),
"test assumes size of int_fast64_t");
CHECK_PRINTF ("12345678901", "%wf64d", (int_fast64_t) 12345678901LL);
CHECK_PRINTF ("-12345678901", "%wf64d", (int_fast64_t) -12345678901LL);
CHECK_PRINTF ("12345678901", "%wf64i", (int_fast64_t) 12345678901LL);
CHECK_PRINTF ("-12345678901", "%wf64i", (int_fast64_t) -12345678901LL);
CHECK_PRINTF ("1011011111110111000001110000110101", "%wf64b",
(uint_fast64_t) 12345678901LL);
CHECK_PRINTF ("1011011111110111000001110000110101", "%wf64B",
(uint_fast64_t) 12345678901LL);
CHECK_PRINTF ("133767016065", "%wf64o", (uint_fast64_t) 12345678901LL);
CHECK_PRINTF ("12345678901", "%wf64u", (uint_fast64_t) 12345678901LL);
CHECK_PRINTF ("2dfdc1c35", "%wf64x", (uint_fast64_t) 12345678901LL);
CHECK_PRINTF ("2DFDC1C35", "%wf64X", (uint_fast64_t) 12345678901LL);
CHECK_PRINTF (" 12345678901", "%13wf64d", (int_fast64_t) 12345678901LL);
CHECK_PRINTF (" 12345678901", "%*wf64d", 13, (int_fast64_t) 12345678901LL);
CHECK_PRINTF ("0x2dfdc1c35", "%#wf64x", (uint_fast64_t) 12345678901LL);
CHECK_PRINTF ("0012345678901", "%.13wf64d", (int_fast64_t) 12345678901LL);
CHECK_PRINTF ("0012345678901", "%.*wf64d", 13, (int_fast64_t) 12345678901LL);
CHECK_PRINTF (" 0012345678901", "%16.13wf64d",
(int_fast64_t) 12345678901LL);
CHECK_PRINTF (" 0012345678901", "%*.13wf64d", 16,
(int_fast64_t) 12345678901LL);
CHECK_PRINTF (" 0012345678901", "%16.*wf64d", 13,
(int_fast64_t) 12345678901LL);
CHECK_PRINTF (" 0012345678901", "%*.*wf64d", 16, 13,
(int_fast64_t) 12345678901LL);
CHECK_PRINTF ("0012345678901 ", "%-16.13wf64d",
(int_fast64_t) 12345678901LL);
CHECK_PRINTF ("0012345678901 ", "%-*.13wf64d", 16,
(int_fast64_t) 12345678901LL);
CHECK_PRINTF ("0012345678901 ", "%-16.*wf64d", 13,
(int_fast64_t) 12345678901LL);
CHECK_PRINTF ("0012345678901 ", "%-*.*wf64d", 16, 13,
(int_fast64_t) 12345678901LL);
{
int_fast64_t n = -1;
CHECK_PRINTF ("12345", "%d%wf64n", 12345, &n);
TEST_COMPARE (n, 5);
}
/* Test positional argument handling. */
CHECK_PRINTF ("test 123456789012 test2 234567890123",
"%4$s %3$wf64d %2$s %1$wf64d",
(int_fast64_t) 234567890123ULL, "test2",
(int_fast64_t) 123456789012ULL, "test");
}
static int
do_test (void)
{
test_w8 ();
test_wf8 ();
test_w16 ();
test_wf16 ();
test_w32 ();
test_wf32 ();
test_w64 ();
test_wf64 ();
/* Bad N in %wN and %wfN are required to produce an error return
from printf functions (and can also be seen to be invalid at
compile time). */
DIAG_PUSH_NEEDS_COMMENT;
DIAG_IGNORE_NEEDS_COMMENT (13, "-Wformat");
DIAG_IGNORE_NEEDS_COMMENT (13, "-Wformat-extra-args");
CHAR buf[1024];
CHECK_PRINTF_ERR ("%w1d", 123);
CHECK_PRINTF_ERR ("%w123d", 123);
CHECK_PRINTF_ERR ("%w99999999999999999999d", 123);
CHECK_PRINTF_ERR ("%wf1d", 123);
CHECK_PRINTF_ERR ("%wf123d", 123);
CHECK_PRINTF_ERR ("%wf99999999999999999999d", 123);
CHECK_PRINTF_ERR ("%1$w1d", 123);
CHECK_PRINTF_ERR ("%1$w123d", 123);
CHECK_PRINTF_ERR ("%1$w99999999999999999999d", 123);
CHECK_PRINTF_ERR ("%1$wf1d", 123);
CHECK_PRINTF_ERR ("%1$wf123d", 123);
CHECK_PRINTF_ERR ("%1$wf99999999999999999999d", 123);
DIAG_POP_NEEDS_COMMENT;
return 0;
}
DIAG_POP_NEEDS_COMMENT;
#include <support/test-driver.c>

View File

@ -0,0 +1,26 @@
/* Test printf formats for intN_t, int_leastN_t and int_fastN_t types.
Narrow string version.
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/>. */
#define SNPRINTF snprintf
#define TEST_COMPARE_STRING_MACRO TEST_COMPARE_STRING
#define STRLEN strlen
#define CHAR char
#define L_(C) C
#include <tst-printf-intn-main.c>

View File

@ -315,7 +315,7 @@ static const uint8_t jump_table[] =
/* 'h' */ 10, /* 'i' */ 15, /* 'j' */ 28, 0,
/* 'l' */ 11, /* 'm' */ 24, /* 'n' */ 23, /* 'o' */ 17,
/* 'p' */ 22, /* 'q' */ 12, 0, /* 's' */ 21,
/* 't' */ 27, /* 'u' */ 16, 0, 0,
/* 't' */ 27, /* 'u' */ 16, 0, /* 'w' */ 31,
/* 'x' */ 18, 0, /* 'z' */ 13
};
@ -356,7 +356,7 @@ static const uint8_t jump_table[] =
#define STEP0_3_TABLE \
/* Step 0: at the beginning. */ \
static JUMP_TABLE_TYPE step0_jumps[31] = \
static JUMP_TABLE_TYPE step0_jumps[32] = \
{ \
REF (form_unknown), \
REF (flag_space), /* for ' ' */ \
@ -389,9 +389,10 @@ static const uint8_t jump_table[] =
REF (mod_intmax_t), /* for 'j' */ \
REF (flag_i18n), /* for 'I' */ \
REF (form_binary), /* for 'B', 'b' */ \
REF (mod_bitwidth), /* for 'w' */ \
}; \
/* Step 1: after processing width. */ \
static JUMP_TABLE_TYPE step1_jumps[31] = \
static JUMP_TABLE_TYPE step1_jumps[32] = \
{ \
REF (form_unknown), \
REF (form_unknown), /* for ' ' */ \
@ -424,9 +425,10 @@ static const uint8_t jump_table[] =
REF (mod_intmax_t), /* for 'j' */ \
REF (form_unknown), /* for 'I' */ \
REF (form_binary), /* for 'B', 'b' */ \
REF (mod_bitwidth), /* for 'w' */ \
}; \
/* Step 2: after processing precision. */ \
static JUMP_TABLE_TYPE step2_jumps[31] = \
static JUMP_TABLE_TYPE step2_jumps[32] = \
{ \
REF (form_unknown), \
REF (form_unknown), /* for ' ' */ \
@ -459,9 +461,10 @@ static const uint8_t jump_table[] =
REF (mod_intmax_t), /* for 'j' */ \
REF (form_unknown), /* for 'I' */ \
REF (form_binary), /* for 'B', 'b' */ \
REF (mod_bitwidth), /* for 'w' */ \
}; \
/* Step 3a: after processing first 'h' modifier. */ \
static JUMP_TABLE_TYPE step3a_jumps[31] = \
static JUMP_TABLE_TYPE step3a_jumps[32] = \
{ \
REF (form_unknown), \
REF (form_unknown), /* for ' ' */ \
@ -494,9 +497,10 @@ static const uint8_t jump_table[] =
REF (form_unknown), /* for 'j' */ \
REF (form_unknown), /* for 'I' */ \
REF (form_binary), /* for 'B', 'b' */ \
REF (form_unknown), /* for 'w' */ \
}; \
/* Step 3b: after processing first 'l' modifier. */ \
static JUMP_TABLE_TYPE step3b_jumps[31] = \
static JUMP_TABLE_TYPE step3b_jumps[32] = \
{ \
REF (form_unknown), \
REF (form_unknown), /* for ' ' */ \
@ -529,11 +533,12 @@ static const uint8_t jump_table[] =
REF (form_unknown), /* for 'j' */ \
REF (form_unknown), /* for 'I' */ \
REF (form_binary), /* for 'B', 'b' */ \
REF (form_unknown), /* for 'w' */ \
}
#define STEP4_TABLE \
/* Step 4: processing format specifier. */ \
static JUMP_TABLE_TYPE step4_jumps[31] = \
static JUMP_TABLE_TYPE step4_jumps[32] = \
{ \
REF (form_unknown), \
REF (form_unknown), /* for ' ' */ \
@ -566,6 +571,7 @@ static const uint8_t jump_table[] =
REF (form_unknown), /* for 'j' */ \
REF (form_unknown), /* for 'I' */ \
REF (form_binary), /* for 'B', 'b' */ \
REF (form_unknown), /* for 'w' */ \
}
/* Handle positional format specifiers. */
@ -886,6 +892,56 @@ Xprintf_buffer (struct Xprintf_buffer *buf, const CHAR_T *format,
is_long = sizeof (intmax_t) > sizeof (unsigned int);
JUMP (*++f, step4_jumps);
/* Process 'wN' or 'wfN' modifier. */
LABEL (mod_bitwidth):
++f;
bool is_fast = false;
if (*f == L_('f'))
{
++f;
is_fast = true;
}
int bitwidth = 0;
if (ISDIGIT (*f))
bitwidth = read_int (&f);
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:
is_char = 1;
break;
case 16:
is_short = 1;
break;
case 32:
break;
case 64:
is_long_double = 1;
is_long = 1;
break;
default:
/* ISO C requires this error to be detected. */
__set_errno (EINVAL);
Xprintf_buffer_mark_failed (buf);
goto all_done;
}
JUMP (*f, step4_jumps);
/* Process current format. */
while (1)
{
@ -1053,11 +1109,19 @@ printf_positional (struct Xprintf_buffer * buf, const CHAR_T *format,
}
/* Parse the format specifier. */
bool failed;
#ifdef COMPILE_WPRINTF
nargs += __parse_one_specwc (f, nargs, &specs[nspecs], &max_ref_arg);
nargs += __parse_one_specwc (f, nargs, &specs[nspecs], &max_ref_arg,
&failed);
#else
nargs += __parse_one_specmb (f, nargs, &specs[nspecs], &max_ref_arg);
nargs += __parse_one_specmb (f, nargs, &specs[nspecs], &max_ref_arg,
&failed);
#endif
if (failed)
{
Xprintf_buffer_mark_failed (buf);
goto all_done;
}
}
/* Determine the number of arguments the format string consumes. */

View File

@ -170,6 +170,7 @@ tests := \
tst-wcstol-binary-gnu2x \
tst-wcstol-locale \
tst-wprintf-binary \
tst-wprintf-intn \
tst-wscanf-binary-c11 \
tst-wscanf-binary-c2x \
tst-wscanf-binary-gnu11 \

26
wcsmbs/tst-wprintf-intn.c Normal file
View File

@ -0,0 +1,26 @@
/* Test printf formats for intN_t, int_leastN_t and int_fastN_t types.
Wide string version.
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/>. */
#define SNPRINTF swprintf
#define TEST_COMPARE_STRING_MACRO TEST_COMPARE_STRING_WIDE
#define STRLEN wcslen
#define CHAR wchar_t
#define L_(C) L ## C
#include "../stdio-common/tst-printf-intn-main.c"