git: 3c96ab9f1d28 - stable/14 - libc: Implement N2680.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 07 Sep 2023 20:28:56 UTC
The branch stable/14 has been updated by des:
URL: https://cgit.FreeBSD.org/src/commit/?id=3c96ab9f1d2855e1a2a1660648ecef597678eaa3
commit 3c96ab9f1d2855e1a2a1660648ecef597678eaa3
Author: Dag-Erling Smørgrav <des@FreeBSD.org>
AuthorDate: 2023-09-07 06:14:44 +0000
Commit: Dag-Erling Smørgrav <des@FreeBSD.org>
CommitDate: 2023-09-07 20:28:31 +0000
libc: Implement N2680.
This adds specific width length modifiers in the form of wN and wfN (where N is 8, 16, 32, or 64) which allow printing intN_t and int_fastN_t without resorting to casts or PRI macros.
Reviewed by: imp, emaste
Differential Revision: https://reviews.freebsd.org/D41725
(cherry picked from commit bce0bef3c6abab92c7ac8cc23b7cc632a382721e)
libc: Add test cases for N2680.
This adds test cases for %wN and %wfN to the printf(3) and scanf(3) tests.
While here, fix a few nits in the N2630 test cases.
Reviewed by: imp
Differential Revision: https://reviews.freebsd.org/D41743
(cherry picked from commit 12b1c1e3fb446021a881d9815465137843fca50b)
Approved by: re (gjb)
---
lib/libc/stdio/printf.3 | 4 +-
lib/libc/stdio/printflocal.h | 1 +
lib/libc/stdio/scanf.3 | 30 ++++++++++++++-
lib/libc/stdio/vfprintf.c | 44 ++++++++++++++++++++++
lib/libc/stdio/vfscanf.c | 40 ++++++++++++++++++++
lib/libc/stdio/vfwprintf.c | 44 ++++++++++++++++++++++
lib/libc/stdio/vfwscanf.c | 40 ++++++++++++++++++++
lib/libc/tests/stdio/snprintf_test.c | 66 ++++++++++++++++++++++++++++++++
lib/libc/tests/stdio/sscanf_test.c | 65 ++++++++++++++++++++++++++++++++
lib/libc/tests/stdio/swprintf_test.c | 66 ++++++++++++++++++++++++++++++++
lib/libc/tests/stdio/swscanf_test.c | 73 ++++++++++++++++++++++++++++++++++--
11 files changed, 468 insertions(+), 5 deletions(-)
diff --git a/lib/libc/stdio/printf.3 b/lib/libc/stdio/printf.3
index 110851e2a421..a7b0c7399e2e 100644
--- a/lib/libc/stdio/printf.3
+++ b/lib/libc/stdio/printf.3
@@ -31,7 +31,7 @@
.\"
.\" @(#)printf.3 8.1 (Berkeley) 6/4/93
.\"
-.Dd August 21, 2023
+.Dd September 5, 2023
.Dt PRINTF 3
.Os
.Sh NAME
@@ -342,6 +342,8 @@ conversion:
.It Cm ll No (ell ell) Ta Vt "long long" Ta Vt "unsigned long long" Ta Vt "long long *"
.It Cm j Ta Vt intmax_t Ta Vt uintmax_t Ta Vt "intmax_t *"
.It Cm t Ta Vt ptrdiff_t Ta (see note) Ta Vt "ptrdiff_t *"
+.It Cm w Ns Ar N Ta Vt intN_t Ta Vt uintN_t Ta Vt "intN_t *"
+.It Cm wf Ns Ar N Ta Vt int_fastN_t Ta Vt uint_fastN_t Ta Vt "int_fastN_t *"
.It Cm z Ta (see note) Ta Vt size_t Ta (see note)
.It Cm q Em (deprecated) Ta Vt quad_t Ta Vt u_quad_t Ta Vt "quad_t *"
.El
diff --git a/lib/libc/stdio/printflocal.h b/lib/libc/stdio/printflocal.h
index 3594f75d0050..f3d0d3e9e216 100644
--- a/lib/libc/stdio/printflocal.h
+++ b/lib/libc/stdio/printflocal.h
@@ -49,6 +49,7 @@
#define PTRDIFFT 0x800 /* ptrdiff_t */
#define INTMAXT 0x1000 /* intmax_t */
#define CHARINT 0x2000 /* print char using int format */
+#define FASTINT 0x4000 /* int_fastN_t */
/*
* Macros for converting digits to letters and vice versa
diff --git a/lib/libc/stdio/scanf.3 b/lib/libc/stdio/scanf.3
index 6cefdb133983..b8d2360c5e76 100644
--- a/lib/libc/stdio/scanf.3
+++ b/lib/libc/stdio/scanf.3
@@ -31,7 +31,7 @@
.\"
.\" @(#)scanf.3 8.2 (Berkeley) 12/11/93
.\"
-.Dd August 21, 2023
+.Dd September 5, 2023
.Dt SCANF 3
.Os
.Sh NAME
@@ -217,6 +217,34 @@ and the next pointer is a pointer to a
.Vt ptrdiff_t
(rather than
.Vt int ) .
+.It Cm w Ns Ar N
+.Po
+where
+.Ar N
+is 8, 16, 32, or 64
+.Pc
+Indicates that the conversion will be one of
+.Cm bdioux
+or
+.Cm n
+and the next pointer is a pointer to a
+.Vt intN_t
+(rather than
+.Vt int ) .
+.It Cm wf Ns Ar N
+.Po
+where
+.Ar N
+is 8, 16, 32, or 64
+.Pc
+Indicates that the conversion will be one of
+.Cm bdioux
+or
+.Cm n
+and the next pointer is a pointer to a
+.Vt int_fastN_t
+(rather than
+.Vt int ) .
.It Cm z
Indicates that the conversion will be one of
.Cm bdioux
diff --git a/lib/libc/stdio/vfprintf.c b/lib/libc/stdio/vfprintf.c
index 5e5a9b5e31c1..8ce77626fb6f 100644
--- a/lib/libc/stdio/vfprintf.c
+++ b/lib/libc/stdio/vfprintf.c
@@ -610,6 +610,49 @@ reswitch: switch (ch) {
case 't':
flags |= PTRDIFFT;
goto rflag;
+ case 'w':
+ /*
+ * Fixed-width integer types. On all platforms we
+ * support, int8_t is equivalent to char, int16_t
+ * is equivalent to short, int32_t is equivalent
+ * to int, int64_t is equivalent to long long int.
+ * Furthermore, int_fast8_t, int_fast16_t and
+ * int_fast32_t are equivalent to int, and
+ * int_fast64_t is equivalent to long long int.
+ */
+ flags &= ~(CHARINT|SHORTINT|LONGINT|LLONGINT|INTMAXT);
+ if (fmt[0] == 'f') {
+ flags |= FASTINT;
+ fmt++;
+ } else {
+ flags &= ~FASTINT;
+ }
+ if (fmt[0] == '8') {
+ if (!(flags & FASTINT))
+ flags |= CHARINT;
+ else
+ /* no flag set = 32 */ ;
+ fmt += 1;
+ } else if (fmt[0] == '1' && fmt[1] == '6') {
+ if (!(flags & FASTINT))
+ flags |= SHORTINT;
+ else
+ /* no flag set = 32 */ ;
+ fmt += 2;
+ } else if (fmt[0] == '3' && fmt[1] == '2') {
+ /* no flag set = 32 */ ;
+ fmt += 2;
+ } else if (fmt[0] == '6' && fmt[1] == '4') {
+ flags |= LLONGINT;
+ fmt += 2;
+ } else {
+ if (flags & FASTINT) {
+ flags &= ~FASTINT;
+ fmt--;
+ }
+ goto invalid;
+ }
+ goto rflag;
case 'z':
flags |= SIZET;
goto rflag;
@@ -932,6 +975,7 @@ number: if ((dprec = prec) >= 0)
default: /* "%?" prints ?, unless ? is NUL */
if (ch == '\0')
goto done;
+invalid:
/* pretend it was %c with argument ch */
cp = buf;
*cp = ch;
diff --git a/lib/libc/stdio/vfscanf.c b/lib/libc/stdio/vfscanf.c
index 9727c9e70c34..fa2e865f33f9 100644
--- a/lib/libc/stdio/vfscanf.c
+++ b/lib/libc/stdio/vfscanf.c
@@ -75,6 +75,7 @@ static char sccsid[] = "@(#)vfscanf.c 8.1 (Berkeley) 6/4/93";
#define SUPPRESS 0x08 /* *: suppress assignment */
#define POINTER 0x10 /* p: void * (as hex) */
#define NOSKIP 0x20 /* [ or c: do not skip blanks */
+#define FASTINT 0x200 /* wfN: int_fastN_t */
#define LONGLONG 0x400 /* ll: long long (+ deprecated q: quad) */
#define INTMAXT 0x800 /* j: intmax_t */
#define PTRDIFFT 0x1000 /* t: ptrdiff_t */
@@ -555,6 +556,45 @@ literal:
case 't':
flags |= PTRDIFFT;
goto again;
+ case 'w':
+ /*
+ * Fixed-width integer types. On all platforms we
+ * support, int8_t is equivalent to char, int16_t
+ * is equivalent to short, int32_t is equivalent
+ * to int, int64_t is equivalent to long long int.
+ * Furthermore, int_fast8_t, int_fast16_t and
+ * int_fast32_t are equivalent to int, and
+ * int_fast64_t is equivalent to long long int.
+ */
+ flags &= ~(SHORTSHORT|SHORT|LONG|LONGLONG|SIZET|INTMAXT|PTRDIFFT);
+ if (fmt[0] == 'f') {
+ flags |= FASTINT;
+ fmt++;
+ } else {
+ flags &= ~FASTINT;
+ }
+ if (fmt[0] == '8') {
+ if (!(flags & FASTINT))
+ flags |= SHORTSHORT;
+ else
+ /* no flag set = 32 */ ;
+ fmt += 1;
+ } else if (fmt[0] == '1' && fmt[1] == '6') {
+ if (!(flags & FASTINT))
+ flags |= SHORT;
+ else
+ /* no flag set = 32 */ ;
+ fmt += 2;
+ } else if (fmt[0] == '3' && fmt[1] == '2') {
+ /* no flag set = 32 */ ;
+ fmt += 2;
+ } else if (fmt[0] == '6' && fmt[1] == '4') {
+ flags |= LONGLONG;
+ fmt += 2;
+ } else {
+ goto match_failure;
+ }
+ goto again;
case 'z':
flags |= SIZET;
goto again;
diff --git a/lib/libc/stdio/vfwprintf.c b/lib/libc/stdio/vfwprintf.c
index 259a86467ea7..d298ed03f521 100644
--- a/lib/libc/stdio/vfwprintf.c
+++ b/lib/libc/stdio/vfwprintf.c
@@ -681,6 +681,49 @@ reswitch: switch (ch) {
case 't':
flags |= PTRDIFFT;
goto rflag;
+ case 'w':
+ /*
+ * Fixed-width integer types. On all platforms we
+ * support, int8_t is equivalent to char, int16_t
+ * is equivalent to short, int32_t is equivalent
+ * to int, int64_t is equivalent to long long int.
+ * Furthermore, int_fast8_t, int_fast16_t and
+ * int_fast32_t are equivalent to int, and
+ * int_fast64_t is equivalent to long long int.
+ */
+ flags &= ~(CHARINT|SHORTINT|LONGINT|LLONGINT|INTMAXT);
+ if (fmt[0] == 'f') {
+ flags |= FASTINT;
+ fmt++;
+ } else {
+ flags &= ~FASTINT;
+ }
+ if (fmt[0] == '8') {
+ if (!(flags & FASTINT))
+ flags |= CHARINT;
+ else
+ /* no flag set = 32 */ ;
+ fmt += 1;
+ } else if (fmt[0] == '1' && fmt[1] == '6') {
+ if (!(flags & FASTINT))
+ flags |= SHORTINT;
+ else
+ /* no flag set = 32 */ ;
+ fmt += 2;
+ } else if (fmt[0] == '3' && fmt[1] == '2') {
+ /* no flag set = 32 */ ;
+ fmt += 2;
+ } else if (fmt[0] == '6' && fmt[1] == '4') {
+ flags |= LLONGINT;
+ fmt += 2;
+ } else {
+ if (flags & FASTINT) {
+ flags &= ~FASTINT;
+ fmt--;
+ }
+ goto invalid;
+ }
+ goto rflag;
case 'z':
flags |= SIZET;
goto rflag;
@@ -993,6 +1036,7 @@ number: if ((dprec = prec) >= 0)
default: /* "%?" prints ?, unless ? is NUL */
if (ch == '\0')
goto done;
+invalid:
/* pretend it was %c with argument ch */
cp = buf;
*cp = ch;
diff --git a/lib/libc/stdio/vfwscanf.c b/lib/libc/stdio/vfwscanf.c
index b03c9dba0699..e2c730b5e7a9 100644
--- a/lib/libc/stdio/vfwscanf.c
+++ b/lib/libc/stdio/vfwscanf.c
@@ -73,6 +73,7 @@ static char sccsid[] = "@(#)vfscanf.c 8.1 (Berkeley) 6/4/93";
#define SUPPRESS 0x08 /* *: suppress assignment */
#define POINTER 0x10 /* p: void * (as hex) */
#define NOSKIP 0x20 /* [ or c: do not skip blanks */
+#define FASTINT 0x200 /* wfN: int_fastN_t */
#define LONGLONG 0x400 /* ll: long long (+ deprecated q: quad) */
#define INTMAXT 0x800 /* j: intmax_t */
#define PTRDIFFT 0x1000 /* t: ptrdiff_t */
@@ -539,6 +540,45 @@ literal:
case 't':
flags |= PTRDIFFT;
goto again;
+ case 'w':
+ /*
+ * Fixed-width integer types. On all platforms we
+ * support, int8_t is equivalent to char, int16_t
+ * is equivalent to short, int32_t is equivalent
+ * to int, int64_t is equivalent to long long int.
+ * Furthermore, int_fast8_t, int_fast16_t and
+ * int_fast32_t are equivalent to int, and
+ * int_fast64_t is equivalent to long long int.
+ */
+ flags &= ~(SHORTSHORT|SHORT|LONG|LONGLONG|SIZET|INTMAXT|PTRDIFFT);
+ if (fmt[0] == 'f') {
+ flags |= FASTINT;
+ fmt++;
+ } else {
+ flags &= ~FASTINT;
+ }
+ if (fmt[0] == '8') {
+ if (!(flags & FASTINT))
+ flags |= SHORTSHORT;
+ else
+ /* no flag set = 32 */ ;
+ fmt += 1;
+ } else if (fmt[0] == '1' && fmt[1] == '6') {
+ if (!(flags & FASTINT))
+ flags |= SHORT;
+ else
+ /* no flag set = 32 */ ;
+ fmt += 2;
+ } else if (fmt[0] == '3' && fmt[1] == '2') {
+ /* no flag set = 32 */ ;
+ fmt += 2;
+ } else if (fmt[0] == '6' && fmt[1] == '4') {
+ flags |= LONGLONG;
+ fmt += 2;
+ } else {
+ goto match_failure;
+ }
+ goto again;
case 'z':
flags |= SIZET;
goto again;
diff --git a/lib/libc/tests/stdio/snprintf_test.c b/lib/libc/tests/stdio/snprintf_test.c
index 10d938435b96..323356b37a7d 100644
--- a/lib/libc/tests/stdio/snprintf_test.c
+++ b/lib/libc/tests/stdio/snprintf_test.c
@@ -127,6 +127,70 @@ ATF_TC_BODY(snprintf_X, tc)
SNPRINTF_TEST("0X007FFFFFFF", "%#012X", INT_MAX);
}
+ATF_TC_WITHOUT_HEAD(snprintf_wN);
+ATF_TC_BODY(snprintf_wN, tc)
+{
+ SNPRINTF_TEST("0", "%w8d", (int8_t)0);
+ SNPRINTF_TEST("-128", "%w8d", (int8_t)CHAR_MIN);
+ SNPRINTF_TEST("127", "%w8d", (int8_t)CHAR_MAX);
+ SNPRINTF_TEST("0", "%w8u", (uint8_t)0);
+ SNPRINTF_TEST("255", "%w8u", (uint8_t)UCHAR_MAX);
+
+ SNPRINTF_TEST("0", "%w16d", (int16_t)0);
+ SNPRINTF_TEST("-32768", "%w16d", (int16_t)SHRT_MIN);
+ SNPRINTF_TEST("32767", "%w16d", (int16_t)SHRT_MAX);
+ SNPRINTF_TEST("0", "%w16u", (uint16_t)0);
+ SNPRINTF_TEST("65535", "%w16u", (uint16_t)USHRT_MAX);
+
+ SNPRINTF_TEST("0", "%w32d", (int32_t)0);
+ SNPRINTF_TEST("-2147483648", "%w32d", (int32_t)INT_MIN);
+ SNPRINTF_TEST("2147483647", "%w32d", (int32_t)INT_MAX);
+ SNPRINTF_TEST("0", "%w32u", (uint32_t)0);
+ SNPRINTF_TEST("4294967295", "%w32u", (uint32_t)UINT_MAX);
+
+ SNPRINTF_TEST("0", "%w64d", (int64_t)0);
+ SNPRINTF_TEST("-9223372036854775808", "%w64d", (int64_t)LLONG_MIN);
+ SNPRINTF_TEST("9223372036854775807", "%w64d", (int64_t)LLONG_MAX);
+ SNPRINTF_TEST("0", "%w64u", (uint64_t)0);
+ SNPRINTF_TEST("18446744073709551615", "%w64u", (uint64_t)ULLONG_MAX);
+
+ SNPRINTF_TEST("wd", "%wd", 0);
+ SNPRINTF_TEST("w1d", "%w1d", 0);
+ SNPRINTF_TEST("w128d", "%w128d", 0);
+}
+
+ATF_TC_WITHOUT_HEAD(snprintf_wfN);
+ATF_TC_BODY(snprintf_wfN, tc)
+{
+ SNPRINTF_TEST("0", "%wf8d", (int_fast8_t)0);
+ SNPRINTF_TEST("-2147483648", "%wf8d", (int_fast8_t)INT_MIN);
+ SNPRINTF_TEST("2147483647", "%wf8d", (int_fast8_t)INT_MAX);
+ SNPRINTF_TEST("0", "%wf8u", (uint8_t)0);
+ SNPRINTF_TEST("4294967295", "%wf8u", (uint_fast8_t)UINT_MAX);
+
+ SNPRINTF_TEST("0", "%wf16d", (int_fast16_t)0);
+ SNPRINTF_TEST("-2147483648", "%wf16d", (int_fast16_t)INT_MIN);
+ SNPRINTF_TEST("2147483647", "%wf16d", (int_fast16_t)INT_MAX);
+ SNPRINTF_TEST("0", "%wf16u", (uint16_t)0);
+ SNPRINTF_TEST("4294967295", "%wf16u", (uint_fast16_t)UINT_MAX);
+
+ SNPRINTF_TEST("0", "%wf32d", (int_fast32_t)0);
+ SNPRINTF_TEST("-2147483648", "%wf32d", (int_fast32_t)INT_MIN);
+ SNPRINTF_TEST("2147483647", "%wf32d", (int_fast32_t)INT_MAX);
+ SNPRINTF_TEST("0", "%wf32u", (uint32_t)0);
+ SNPRINTF_TEST("4294967295", "%wf32u", (uint_fast32_t)UINT_MAX);
+
+ SNPRINTF_TEST("0", "%wf64d", (int_fast64_t)0);
+ SNPRINTF_TEST("-9223372036854775808", "%wf64d", (int_fast64_t)LLONG_MIN);
+ SNPRINTF_TEST("9223372036854775807", "%wf64d", (int_fast64_t)LLONG_MAX);
+ SNPRINTF_TEST("0", "%wf64u", (uint64_t)0);
+ SNPRINTF_TEST("18446744073709551615", "%wf64u", (uint_fast64_t)ULLONG_MAX);
+
+ SNPRINTF_TEST("wfd", "%wfd", 0);
+ SNPRINTF_TEST("wf1d", "%wf1d", 0);
+ SNPRINTF_TEST("wf128d", "%wf128d", 0);
+}
+
ATF_TP_ADD_TCS(tp)
{
setlocale(LC_NUMERIC, "en_US.UTF-8");
@@ -135,5 +199,7 @@ ATF_TP_ADD_TCS(tp)
ATF_TP_ADD_TC(tp, snprintf_d);
ATF_TP_ADD_TC(tp, snprintf_x);
ATF_TP_ADD_TC(tp, snprintf_X);
+ ATF_TP_ADD_TC(tp, snprintf_wN);
+ ATF_TP_ADD_TC(tp, snprintf_wfN);
return (atf_no_error());
}
diff --git a/lib/libc/tests/stdio/sscanf_test.c b/lib/libc/tests/stdio/sscanf_test.c
index 462b4a6586da..e916873d38c3 100644
--- a/lib/libc/tests/stdio/sscanf_test.c
+++ b/lib/libc/tests/stdio/sscanf_test.c
@@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
+#include <limits.h>
#include <locale.h>
#include <stdint.h>
#include <stdio.h>
@@ -237,6 +238,68 @@ ATF_TC_BODY(sscanf_i, tc)
}
}
+ATF_TC_WITHOUT_HEAD(sscanf_wN);
+ATF_TC_BODY(sscanf_wN, tc)
+{
+ const char x00[] = "0x00";
+ const char x7f[] = "0x7fffffffffffffff";
+ const char xff[] = "0xffffffffffffffff";
+
+#define SSCANF_WN_TEST(N, imin, umax) \
+ do { \
+ int##N##_t i; \
+ uint##N##_t u; \
+ ATF_CHECK_EQ(1, sscanf(x00, "%w" #N "i", &i)); \
+ ATF_CHECK_EQ(0, i); \
+ ATF_CHECK_EQ(1, sscanf(x7f, "%w" #N "i", &i)); \
+ ATF_CHECK_EQ(imin, i); \
+ ATF_CHECK_EQ(1, sscanf(x00, "%w" #N "x", &u)); \
+ ATF_CHECK_EQ(0, u); \
+ ATF_CHECK_EQ(1, sscanf(xff, "%w" #N "x", &u)); \
+ ATF_CHECK_EQ(umax, u); \
+ } while (0)
+ SSCANF_WN_TEST(8, -1, UCHAR_MAX);
+ SSCANF_WN_TEST(16, -1, USHRT_MAX);
+ SSCANF_WN_TEST(32, -1, UINT_MAX);
+ SSCANF_WN_TEST(64, LLONG_MAX, ULLONG_MAX);
+#undef SSCANF_WN_TEST
+
+ ATF_CHECK_EQ(0, sscanf(x00, "%wi", (int *)NULL));
+ ATF_CHECK_EQ(0, sscanf(x00, "%w1i", (int *)NULL));
+ ATF_CHECK_EQ(0, sscanf(x00, "%w128i", (int *)NULL));
+}
+
+ATF_TC_WITHOUT_HEAD(sscanf_wfN);
+ATF_TC_BODY(sscanf_wfN, tc)
+{
+ const char x00[] = "0x00";
+ const char x7f[] = "0x7fffffffffffffff";
+ const char xff[] = "0xffffffffffffffff";
+
+#define SSCANF_WFN_TEST(N, imin, umax) \
+ do { \
+ int_fast##N##_t i; \
+ uint_fast##N##_t u; \
+ ATF_CHECK_EQ(1, sscanf(x00, "%wf" #N "i", &i)); \
+ ATF_CHECK_EQ(0, i); \
+ ATF_CHECK_EQ(1, sscanf(x7f, "%wf" #N "i", &i)); \
+ ATF_CHECK_EQ(imin, i); \
+ ATF_CHECK_EQ(1, sscanf(x00, "%wf" #N "x", &u)); \
+ ATF_CHECK_EQ(0, u); \
+ ATF_CHECK_EQ(1, sscanf(xff, "%wf" #N "x", &u)); \
+ ATF_CHECK_EQ(umax, u); \
+ } while (0)
+ SSCANF_WFN_TEST(8, -1, UINT_MAX);
+ SSCANF_WFN_TEST(16, -1, UINT_MAX);
+ SSCANF_WFN_TEST(32, -1, UINT_MAX);
+ SSCANF_WFN_TEST(64, LLONG_MAX, ULLONG_MAX);
+#undef SSCANF_WFN_TEST
+
+ ATF_CHECK_EQ(0, sscanf(x00, "%wfi", (int *)NULL));
+ ATF_CHECK_EQ(0, sscanf(x00, "%wf1i", (int *)NULL));
+ ATF_CHECK_EQ(0, sscanf(x00, "%wf128i", (int *)NULL));
+}
+
/*
* Test termination cases: non-numeric character, fixed width, EOF
*/
@@ -261,6 +324,8 @@ ATF_TP_ADD_TCS(tp)
ATF_TP_ADD_TC(tp, sscanf_d);
ATF_TP_ADD_TC(tp, sscanf_x);
ATF_TP_ADD_TC(tp, sscanf_i);
+ ATF_TP_ADD_TC(tp, sscanf_wN);
+ ATF_TP_ADD_TC(tp, sscanf_wfN);
ATF_TP_ADD_TC(tp, sscanf_termination);
return (atf_no_error());
}
diff --git a/lib/libc/tests/stdio/swprintf_test.c b/lib/libc/tests/stdio/swprintf_test.c
index 23859b5cd2e1..f5dde349412b 100644
--- a/lib/libc/tests/stdio/swprintf_test.c
+++ b/lib/libc/tests/stdio/swprintf_test.c
@@ -128,6 +128,70 @@ ATF_TC_BODY(swprintf_X, tc)
SWPRINTF_TEST("0X007FFFFFFF", "%#012X", INT_MAX);
}
+ATF_TC_WITHOUT_HEAD(swprintf_wN);
+ATF_TC_BODY(swprintf_wN, tc)
+{
+ SWPRINTF_TEST("0", "%w8d", (int8_t)0);
+ SWPRINTF_TEST("-128", "%w8d", (int8_t)CHAR_MIN);
+ SWPRINTF_TEST("127", "%w8d", (int8_t)CHAR_MAX);
+ SWPRINTF_TEST("0", "%w8u", (uint8_t)0);
+ SWPRINTF_TEST("255", "%w8u", (uint8_t)UCHAR_MAX);
+
+ SWPRINTF_TEST("0", "%w16d", (int16_t)0);
+ SWPRINTF_TEST("-32768", "%w16d", (int16_t)SHRT_MIN);
+ SWPRINTF_TEST("32767", "%w16d", (int16_t)SHRT_MAX);
+ SWPRINTF_TEST("0", "%w16u", (uint16_t)0);
+ SWPRINTF_TEST("65535", "%w16u", (uint16_t)USHRT_MAX);
+
+ SWPRINTF_TEST("0", "%w32d", (int32_t)0);
+ SWPRINTF_TEST("-2147483648", "%w32d", (int32_t)INT_MIN);
+ SWPRINTF_TEST("2147483647", "%w32d", (int32_t)INT_MAX);
+ SWPRINTF_TEST("0", "%w32u", (uint32_t)0);
+ SWPRINTF_TEST("4294967295", "%w32u", (uint32_t)UINT_MAX);
+
+ SWPRINTF_TEST("0", "%w64d", (int64_t)0);
+ SWPRINTF_TEST("-9223372036854775808", "%w64d", (int64_t)LLONG_MIN);
+ SWPRINTF_TEST("9223372036854775807", "%w64d", (int64_t)LLONG_MAX);
+ SWPRINTF_TEST("0", "%w64u", (uint64_t)0);
+ SWPRINTF_TEST("18446744073709551615", "%w64u", (uint64_t)ULLONG_MAX);
+
+ SWPRINTF_TEST("wd", "%wd", 0);
+ SWPRINTF_TEST("w1d", "%w1d", 0);
+ SWPRINTF_TEST("w128d", "%w128d", 0);
+}
+
+ATF_TC_WITHOUT_HEAD(swprintf_wfN);
+ATF_TC_BODY(swprintf_wfN, tc)
+{
+ SWPRINTF_TEST("0", "%wf8d", (int_fast8_t)0);
+ SWPRINTF_TEST("-2147483648", "%wf8d", (int_fast8_t)INT_MIN);
+ SWPRINTF_TEST("2147483647", "%wf8d", (int_fast8_t)INT_MAX);
+ SWPRINTF_TEST("0", "%wf8u", (uint8_t)0);
+ SWPRINTF_TEST("4294967295", "%wf8u", (uint_fast8_t)UINT_MAX);
+
+ SWPRINTF_TEST("0", "%wf16d", (int_fast16_t)0);
+ SWPRINTF_TEST("-2147483648", "%wf16d", (int_fast16_t)INT_MIN);
+ SWPRINTF_TEST("2147483647", "%wf16d", (int_fast16_t)INT_MAX);
+ SWPRINTF_TEST("0", "%wf16u", (uint16_t)0);
+ SWPRINTF_TEST("4294967295", "%wf16u", (uint_fast16_t)UINT_MAX);
+
+ SWPRINTF_TEST("0", "%wf32d", (int_fast32_t)0);
+ SWPRINTF_TEST("-2147483648", "%wf32d", (int_fast32_t)INT_MIN);
+ SWPRINTF_TEST("2147483647", "%wf32d", (int_fast32_t)INT_MAX);
+ SWPRINTF_TEST("0", "%wf32u", (uint32_t)0);
+ SWPRINTF_TEST("4294967295", "%wf32u", (uint_fast32_t)UINT_MAX);
+
+ SWPRINTF_TEST("0", "%wf64d", (int_fast64_t)0);
+ SWPRINTF_TEST("-9223372036854775808", "%wf64d", (int_fast64_t)LLONG_MIN);
+ SWPRINTF_TEST("9223372036854775807", "%wf64d", (int_fast64_t)LLONG_MAX);
+ SWPRINTF_TEST("0", "%wf64u", (uint64_t)0);
+ SWPRINTF_TEST("18446744073709551615", "%wf64u", (uint_fast64_t)ULLONG_MAX);
+
+ SWPRINTF_TEST("wfd", "%wfd", 0);
+ SWPRINTF_TEST("wf1d", "%wf1d", 0);
+ SWPRINTF_TEST("wf128d", "%wf128d", 0);
+}
+
ATF_TP_ADD_TCS(tp)
{
setlocale(LC_NUMERIC, "en_US.UTF-8");
@@ -136,5 +200,7 @@ ATF_TP_ADD_TCS(tp)
ATF_TP_ADD_TC(tp, swprintf_d);
ATF_TP_ADD_TC(tp, swprintf_x);
ATF_TP_ADD_TC(tp, swprintf_X);
+ ATF_TP_ADD_TC(tp, swprintf_wN);
+ ATF_TP_ADD_TC(tp, swprintf_wfN);
return (atf_no_error());
}
diff --git a/lib/libc/tests/stdio/swscanf_test.c b/lib/libc/tests/stdio/swscanf_test.c
index 10eaf786e5fa..f7ad30b963a7 100644
--- a/lib/libc/tests/stdio/swscanf_test.c
+++ b/lib/libc/tests/stdio/swscanf_test.c
@@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
+#include <limits.h>
#include <locale.h>
#include <stdint.h>
#include <stdio.h>
@@ -11,6 +12,8 @@
#include <atf-c.h>
+#define L(s) L ## s
+
static const struct swscanf_test_case {
wchar_t input[8];
struct {
@@ -150,7 +153,7 @@ static const struct swscanf_test_case {
#define SWSCANF_TEST(string, format, expret, expval, explen) \
do { \
int ret = 0, val = 0, len = 0; \
- ret = swscanf(string, format "%n", &val, &len); \
+ ret = swscanf(string, format L"%n", &val, &len); \
ATF_CHECK_EQ(expret, ret); \
if (expret && ret) { \
ATF_CHECK_EQ(expval, val); \
@@ -238,6 +241,68 @@ ATF_TC_BODY(swscanf_i, tc)
}
}
+ATF_TC_WITHOUT_HEAD(swscanf_wN);
+ATF_TC_BODY(swscanf_wN, tc)
+{
+ const wchar_t x00[] = L"0x00";
+ const wchar_t x7f[] = L"0x7fffffffffffffff";
+ const wchar_t xff[] = L"0xffffffffffffffff";
+
+#define SWSCANF_WN_TEST(N, imin, umax) \
+ do { \
+ int##N##_t i; \
+ uint##N##_t u; \
+ ATF_CHECK_EQ(1, swscanf(x00, L"%w" L(#N) L"i", &i)); \
+ ATF_CHECK_EQ(0, i); \
+ ATF_CHECK_EQ(1, swscanf(x7f, L"%w" L(#N) L"i", &i)); \
+ ATF_CHECK_EQ(imin, i); \
+ ATF_CHECK_EQ(1, swscanf(x00, L"%w" L(#N) L"x", &u)); \
+ ATF_CHECK_EQ(0, u); \
+ ATF_CHECK_EQ(1, swscanf(xff, L"%w" L(#N) L"x", &u)); \
+ ATF_CHECK_EQ(umax, u); \
+ } while (0)
+ SWSCANF_WN_TEST(8, -1, UCHAR_MAX);
+ SWSCANF_WN_TEST(16, -1, USHRT_MAX);
+ SWSCANF_WN_TEST(32, -1, UINT_MAX);
+ SWSCANF_WN_TEST(64, LLONG_MAX, ULLONG_MAX);
+#undef SWSCANF_WN_TEST
+
+ ATF_CHECK_EQ(0, swscanf(x00, L"%wi", (int *)NULL));
+ ATF_CHECK_EQ(0, swscanf(x00, L"%w1i", (int *)NULL));
+ ATF_CHECK_EQ(0, swscanf(x00, L"%w128i", (int *)NULL));
+}
+
+ATF_TC_WITHOUT_HEAD(swscanf_wfN);
+ATF_TC_BODY(swscanf_wfN, tc)
+{
+ const wchar_t x00[] = L"0x00";
+ const wchar_t x7f[] = L"0x7fffffffffffffff";
+ const wchar_t xff[] = L"0xffffffffffffffff";
+
+#define SWSCANF_WFN_TEST(N, imin, umax) \
+ do { \
+ int_fast##N##_t i; \
+ uint_fast##N##_t u; \
+ ATF_CHECK_EQ(1, swscanf(x00, L"%wf" L(#N) L"i", &i)); \
+ ATF_CHECK_EQ(0, i); \
+ ATF_CHECK_EQ(1, swscanf(x7f, L"%wf" L(#N) L"i", &i)); \
+ ATF_CHECK_EQ(imin, i); \
+ ATF_CHECK_EQ(1, swscanf(x00, L"%wf" L(#N) L"x", &u)); \
+ ATF_CHECK_EQ(0, u); \
+ ATF_CHECK_EQ(1, swscanf(xff, L"%wf" L(#N) L"x", &u)); \
+ ATF_CHECK_EQ(umax, u); \
+ } while (0)
+ SWSCANF_WFN_TEST(8, -1, UINT_MAX);
+ SWSCANF_WFN_TEST(16, -1, UINT_MAX);
+ SWSCANF_WFN_TEST(32, -1, UINT_MAX);
+ SWSCANF_WFN_TEST(64, LLONG_MAX, ULLONG_MAX);
+#undef SWSCANF_WFN_TEST
+
+ ATF_CHECK_EQ(0, swscanf(x00, L"%wfi", (int *)NULL));
+ ATF_CHECK_EQ(0, swscanf(x00, L"%wf1i", (int *)NULL));
+ ATF_CHECK_EQ(0, swscanf(x00, L"%wf128i", (int *)NULL));
+}
+
/*
* Test termination cases: non-numeric character, fixed width, EOF
*/
@@ -245,9 +310,9 @@ ATF_TC_WITHOUT_HEAD(swscanf_termination);
ATF_TC_BODY(swscanf_termination, tc)
{
int a = 0, b = 0, c = 0;
- char d = 0;
+ wchar_t d = 0;
- ATF_CHECK_EQ(4, swscanf(L"3.1415", L"%d%c%2d%d", &a, &d, &b, &c));
+ ATF_CHECK_EQ(4, swscanf(L"3.1415", L"%d%lc%2d%d", &a, &d, &b, &c));
ATF_CHECK_EQ(3, a);
ATF_CHECK_EQ(14, b);
ATF_CHECK_EQ(15, c);
@@ -262,6 +327,8 @@ ATF_TP_ADD_TCS(tp)
ATF_TP_ADD_TC(tp, swscanf_d);
ATF_TP_ADD_TC(tp, swscanf_x);
ATF_TP_ADD_TC(tp, swscanf_i);
+ ATF_TP_ADD_TC(tp, swscanf_wN);
+ ATF_TP_ADD_TC(tp, swscanf_wfN);
ATF_TP_ADD_TC(tp, swscanf_termination);
return (atf_no_error());
}