xref: /freebsd/lib/libc/tests/stdio/swscanf_test.c (revision 086ce467adec42d58414fdb4d54c2b6819cf0c07)
1 /*-
2  * Copyright (c) 2023 Dag-Erling Smørgrav
3  *
4  * SPDX-License-Identifier: BSD-2-Clause
5  */
6 
7 #include <limits.h>
8 #include <locale.h>
9 #include <stdint.h>
10 #include <stdio.h>
11 #include <wchar.h>
12 
13 #include <atf-c.h>
14 
15 #define L(s) L ## s
16 
17 static const struct swscanf_test_case {
18 	wchar_t input[8];
19 	struct {
20 		int ret, val, len;
21 	} b, o, d, x, i;
22 } swscanf_test_cases[] = {
23 //	input		binary		octal		decimal		hexadecimal	automatic
24 	// all digits
25 	{ L"0",		{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 }, },
26 	{ L"1",		{ 1,   1, 1 },	{ 1,   1, 1 },	{ 1,   1, 1 },	{ 1,   1, 1 },	{ 1,   1, 1 }, },
27 	{ L"2",		{ 0,   0, 0 },	{ 1,   2, 1 },	{ 1,   2, 1 },	{ 1,   2, 1 },	{ 1,   2, 1 }, },
28 	{ L"3",		{ 0,   0, 0 },	{ 1,   3, 1 },	{ 1,   3, 1 },	{ 1,   3, 1 },	{ 1,   3, 1 }, },
29 	{ L"4",		{ 0,   0, 0 },	{ 1,   4, 1 },	{ 1,   4, 1 },	{ 1,   4, 1 },	{ 1,   4, 1 }, },
30 	{ L"5",		{ 0,   0, 0 },	{ 1,   5, 1 },	{ 1,   5, 1 },	{ 1,   5, 1 },	{ 1,   5, 1 }, },
31 	{ L"6",		{ 0,   0, 0 },	{ 1,   6, 1 },	{ 1,   6, 1 },	{ 1,   6, 1 },	{ 1,   6, 1 }, },
32 	{ L"7",		{ 0,   0, 0 },	{ 1,   7, 1 },	{ 1,   7, 1 },	{ 1,   7, 1 },	{ 1,   7, 1 }, },
33 	{ L"8",		{ 0,   0, 0 },	{ 0,   0, 0 },	{ 1,   8, 1 },	{ 1,   8, 1 },	{ 1,   8, 1 }, },
34 	{ L"9",		{ 0,   0, 0 },	{ 0,   0, 0 },	{ 1,   9, 1 },	{ 1,   9, 1 },	{ 1,   9, 1 }, },
35 	{ L"A",		{ 0,   0, 0 },	{ 0,   0, 0 },	{ 0,   0, 0 },	{ 1,  10, 1 },	{ 0,   0, 0 }, },
36 	{ L"B",		{ 0,   0, 0 },	{ 0,   0, 0 },	{ 0,   0, 0 },	{ 1,  11, 1 },	{ 0,   0, 0 }, },
37 	{ L"C",		{ 0,   0, 0 },	{ 0,   0, 0 },	{ 0,   0, 0 },	{ 1,  12, 1 },	{ 0,   0, 0 }, },
38 	{ L"D",		{ 0,   0, 0 },	{ 0,   0, 0 },	{ 0,   0, 0 },	{ 1,  13, 1 },	{ 0,   0, 0 }, },
39 	{ L"E",		{ 0,   0, 0 },	{ 0,   0, 0 },	{ 0,   0, 0 },	{ 1,  14, 1 },	{ 0,   0, 0 }, },
40 	{ L"F",		{ 0,   0, 0 },	{ 0,   0, 0 },	{ 0,   0, 0 },	{ 1,  15, 1 },	{ 0,   0, 0 }, },
41 	{ L"X",		{ 0,   0, 0 },	{ 0,   0, 0 },	{ 0,   0, 0 },	{ 0,   0, 0 },	{ 0,   0, 0 }, },
42 	{ L"a",		{ 0,   0, 0 },	{ 0,   0, 0 },	{ 0,   0, 0 },	{ 1,  10, 1 },	{ 0,   0, 0 }, },
43 	{ L"b",		{ 0,   0, 0 },	{ 0,   0, 0 },	{ 0,   0, 0 },	{ 1,  11, 1 },	{ 0,   0, 0 }, },
44 	{ L"c",		{ 0,   0, 0 },	{ 0,   0, 0 },	{ 0,   0, 0 },	{ 1,  12, 1 },	{ 0,   0, 0 }, },
45 	{ L"d",		{ 0,   0, 0 },	{ 0,   0, 0 },	{ 0,   0, 0 },	{ 1,  13, 1 },	{ 0,   0, 0 }, },
46 	{ L"e",		{ 0,   0, 0 },	{ 0,   0, 0 },	{ 0,   0, 0 },	{ 1,  14, 1 },	{ 0,   0, 0 }, },
47 	{ L"f",		{ 0,   0, 0 },	{ 0,   0, 0 },	{ 0,   0, 0 },	{ 1,  15, 1 },	{ 0,   0, 0 }, },
48 	{ L"x",		{ 0,   0, 0 },	{ 0,   0, 0 },	{ 0,   0, 0 },	{ 0,   0, 0 },	{ 0,   0, 0 }, },
49 	// all digits with leading zero
50 	{ L"00",	{ 1,   0, 2 },	{ 1,   0, 2 },	{ 1,   0, 2 },	{ 1,   0, 2 },	{ 1,   0, 2 }, },
51 	{ L"01",	{ 1,   1, 2 },	{ 1,   1, 2 },	{ 1,   1, 2 },	{ 1,   1, 2 },	{ 1,   1, 2 }, },
52 	{ L"02",	{ 1,   0, 1 },	{ 1,   2, 2 },	{ 1,   2, 2 },	{ 1,   2, 2 },	{ 1,   2, 2 }, },
53 	{ L"03",	{ 1,   0, 1 },	{ 1,   3, 2 },	{ 1,   3, 2 },	{ 1,   3, 2 },	{ 1,   3, 2 }, },
54 	{ L"04",	{ 1,   0, 1 },	{ 1,   4, 2 },	{ 1,   4, 2 },	{ 1,   4, 2 },	{ 1,   4, 2 }, },
55 	{ L"05",	{ 1,   0, 1 },	{ 1,   5, 2 },	{ 1,   5, 2 },	{ 1,   5, 2 },	{ 1,   5, 2 }, },
56 	{ L"06",	{ 1,   0, 1 },	{ 1,   6, 2 },	{ 1,   6, 2 },	{ 1,   6, 2 },	{ 1,   6, 2 }, },
57 	{ L"07",	{ 1,   0, 1 },	{ 1,   7, 2 },	{ 1,   7, 2 },	{ 1,   7, 2 },	{ 1,   7, 2 }, },
58 	{ L"08",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   8, 2 },	{ 1,   8, 2 },	{ 1,   0, 1 }, },
59 	{ L"09",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   9, 2 },	{ 1,   9, 2 },	{ 1,   0, 1 }, },
60 	{ L"0A",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,  10, 2 },	{ 1,   0, 1 }, },
61 	{ L"0B",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,  11, 2 },	{ 1,   0, 1 }, },
62 	{ L"0C",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,  12, 2 },	{ 1,   0, 1 }, },
63 	{ L"0D",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,  13, 2 },	{ 1,   0, 1 }, },
64 	{ L"0E",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,  14, 2 },	{ 1,   0, 1 }, },
65 	{ L"0F",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,  15, 2 },	{ 1,   0, 1 }, },
66 	{ L"0X",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 }, },
67 	{ L"0a",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,  10, 2 },	{ 1,   0, 1 }, },
68 	{ L"0b",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,  11, 2 },	{ 1,   0, 1 }, },
69 	{ L"0c",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,  12, 2 },	{ 1,   0, 1 }, },
70 	{ L"0d",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,  13, 2 },	{ 1,   0, 1 }, },
71 	{ L"0e",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,  14, 2 },	{ 1,   0, 1 }, },
72 	{ L"0f",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,  15, 2 },	{ 1,   0, 1 }, },
73 	{ L"0x",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 }, },
74 	// all digits with two leading zeroes
75 	{ L"000",	{ 1,   0, 3 },	{ 1,   0, 3 },	{ 1,   0, 3 },	{ 1,   0, 3 },	{ 1,   0, 3 }, },
76 	{ L"001",	{ 1,   1, 3 },	{ 1,   1, 3 },	{ 1,   1, 3 },	{ 1,   1, 3 },	{ 1,   1, 3 }, },
77 	{ L"002",	{ 1,   0, 2 },	{ 1,   2, 3 },	{ 1,   2, 3 },	{ 1,   2, 3 },	{ 1,   2, 3 }, },
78 	{ L"003",	{ 1,   0, 2 },	{ 1,   3, 3 },	{ 1,   3, 3 },	{ 1,   3, 3 },	{ 1,   3, 3 }, },
79 	{ L"004",	{ 1,   0, 2 },	{ 1,   4, 3 },	{ 1,   4, 3 },	{ 1,   4, 3 },	{ 1,   4, 3 }, },
80 	{ L"005",	{ 1,   0, 2 },	{ 1,   5, 3 },	{ 1,   5, 3 },	{ 1,   5, 3 },	{ 1,   5, 3 }, },
81 	{ L"006",	{ 1,   0, 2 },	{ 1,   6, 3 },	{ 1,   6, 3 },	{ 1,   6, 3 },	{ 1,   6, 3 }, },
82 	{ L"007",	{ 1,   0, 2 },	{ 1,   7, 3 },	{ 1,   7, 3 },	{ 1,   7, 3 },	{ 1,   7, 3 }, },
83 	{ L"008",	{ 1,   0, 2 },	{ 1,   0, 2 },	{ 1,   8, 3 },	{ 1,   8, 3 },	{ 1,   0, 2 }, },
84 	{ L"009",	{ 1,   0, 2 },	{ 1,   0, 2 },	{ 1,   9, 3 },	{ 1,   9, 3 },	{ 1,   0, 2 }, },
85 	{ L"00A",	{ 1,   0, 2 },	{ 1,   0, 2 },	{ 1,   0, 2 },	{ 1,  10, 3 },	{ 1,   0, 2 }, },
86 	{ L"00B",	{ 1,   0, 2 },	{ 1,   0, 2 },	{ 1,   0, 2 },	{ 1,  11, 3 },	{ 1,   0, 2 }, },
87 	{ L"00C",	{ 1,   0, 2 },	{ 1,   0, 2 },	{ 1,   0, 2 },	{ 1,  12, 3 },	{ 1,   0, 2 }, },
88 	{ L"00D",	{ 1,   0, 2 },	{ 1,   0, 2 },	{ 1,   0, 2 },	{ 1,  13, 3 },	{ 1,   0, 2 }, },
89 	{ L"00E",	{ 1,   0, 2 },	{ 1,   0, 2 },	{ 1,   0, 2 },	{ 1,  14, 3 },	{ 1,   0, 2 }, },
90 	{ L"00F",	{ 1,   0, 2 },	{ 1,   0, 2 },	{ 1,   0, 2 },	{ 1,  15, 3 },	{ 1,   0, 2 }, },
91 	{ L"00X",	{ 1,   0, 2 },	{ 1,   0, 2 },	{ 1,   0, 2 },	{ 1,   0, 2 },	{ 1,   0, 2 }, },
92 	{ L"00a",	{ 1,   0, 2 },	{ 1,   0, 2 },	{ 1,   0, 2 },	{ 1,  10, 3 },	{ 1,   0, 2 }, },
93 	{ L"00b",	{ 1,   0, 2 },	{ 1,   0, 2 },	{ 1,   0, 2 },	{ 1,  11, 3 },	{ 1,   0, 2 }, },
94 	{ L"00c",	{ 1,   0, 2 },	{ 1,   0, 2 },	{ 1,   0, 2 },	{ 1,  12, 3 },	{ 1,   0, 2 }, },
95 	{ L"00d",	{ 1,   0, 2 },	{ 1,   0, 2 },	{ 1,   0, 2 },	{ 1,  13, 3 },	{ 1,   0, 2 }, },
96 	{ L"00e",	{ 1,   0, 2 },	{ 1,   0, 2 },	{ 1,   0, 2 },	{ 1,  14, 3 },	{ 1,   0, 2 }, },
97 	{ L"00f",	{ 1,   0, 2 },	{ 1,   0, 2 },	{ 1,   0, 2 },	{ 1,  15, 3 },	{ 1,   0, 2 }, },
98 	{ L"00x",	{ 1,   0, 2 },	{ 1,   0, 2 },	{ 1,   0, 2 },	{ 1,   0, 2 },	{ 1,   0, 2 }, },
99 	// all digits with leading one
100 	{ L"10",	{ 1,   2, 2 },	{ 1,   8, 2 },	{ 1,  10, 2 },	{ 1,  16, 2 },	{ 1,  10, 2 }, },
101 	{ L"11",	{ 1,   3, 2 },	{ 1,   9, 2 },	{ 1,  11, 2 },	{ 1,  17, 2 },	{ 1,  11, 2 }, },
102 	{ L"12",	{ 1,   1, 1 },	{ 1,  10, 2 },	{ 1,  12, 2 },	{ 1,  18, 2 },	{ 1,  12, 2 }, },
103 	{ L"13",	{ 1,   1, 1 },	{ 1,  11, 2 },	{ 1,  13, 2 },	{ 1,  19, 2 },	{ 1,  13, 2 }, },
104 	{ L"14",	{ 1,   1, 1 },	{ 1,  12, 2 },	{ 1,  14, 2 },	{ 1,  20, 2 },	{ 1,  14, 2 }, },
105 	{ L"15",	{ 1,   1, 1 },	{ 1,  13, 2 },	{ 1,  15, 2 },	{ 1,  21, 2 },	{ 1,  15, 2 }, },
106 	{ L"16",	{ 1,   1, 1 },	{ 1,  14, 2 },	{ 1,  16, 2 },	{ 1,  22, 2 },	{ 1,  16, 2 }, },
107 	{ L"17",	{ 1,   1, 1 },	{ 1,  15, 2 },	{ 1,  17, 2 },	{ 1,  23, 2 },	{ 1,  17, 2 }, },
108 	{ L"18",	{ 1,   1, 1 },	{ 1,   1, 1 },	{ 1,  18, 2 },	{ 1,  24, 2 },	{ 1,  18, 2 }, },
109 	{ L"19",	{ 1,   1, 1 },	{ 1,   1, 1 },	{ 1,  19, 2 },	{ 1,  25, 2 },	{ 1,  19, 2 }, },
110 	{ L"1A",	{ 1,   1, 1 },	{ 1,   1, 1 },	{ 1,   1, 1 },	{ 1,  26, 2 },	{ 1,   1, 1 }, },
111 	{ L"1B",	{ 1,   1, 1 },	{ 1,   1, 1 },	{ 1,   1, 1 },	{ 1,  27, 2 },	{ 1,   1, 1 }, },
112 	{ L"1C",	{ 1,   1, 1 },	{ 1,   1, 1 },	{ 1,   1, 1 },	{ 1,  28, 2 },	{ 1,   1, 1 }, },
113 	{ L"1D",	{ 1,   1, 1 },	{ 1,   1, 1 },	{ 1,   1, 1 },	{ 1,  29, 2 },	{ 1,   1, 1 }, },
114 	{ L"1E",	{ 1,   1, 1 },	{ 1,   1, 1 },	{ 1,   1, 1 },	{ 1,  30, 2 },	{ 1,   1, 1 }, },
115 	{ L"1F",	{ 1,   1, 1 },	{ 1,   1, 1 },	{ 1,   1, 1 },	{ 1,  31, 2 },	{ 1,   1, 1 }, },
116 	{ L"1X",	{ 1,   1, 1 },	{ 1,   1, 1 },	{ 1,   1, 1 },	{ 1,   1, 1 },	{ 1,   1, 1 }, },
117 	{ L"1a",	{ 1,   1, 1 },	{ 1,   1, 1 },	{ 1,   1, 1 },	{ 1,  26, 2 },	{ 1,   1, 1 }, },
118 	{ L"1b",	{ 1,   1, 1 },	{ 1,   1, 1 },	{ 1,   1, 1 },	{ 1,  27, 2 },	{ 1,   1, 1 }, },
119 	{ L"1c",	{ 1,   1, 1 },	{ 1,   1, 1 },	{ 1,   1, 1 },	{ 1,  28, 2 },	{ 1,   1, 1 }, },
120 	{ L"1d",	{ 1,   1, 1 },	{ 1,   1, 1 },	{ 1,   1, 1 },	{ 1,  29, 2 },	{ 1,   1, 1 }, },
121 	{ L"1e",	{ 1,   1, 1 },	{ 1,   1, 1 },	{ 1,   1, 1 },	{ 1,  30, 2 },	{ 1,   1, 1 }, },
122 	{ L"1f",	{ 1,   1, 1 },	{ 1,   1, 1 },	{ 1,   1, 1 },	{ 1,  31, 2 },	{ 1,   1, 1 }, },
123 	{ L"1x",	{ 1,   1, 1 },	{ 1,   1, 1 },	{ 1,   1, 1 },	{ 1,   1, 1 },	{ 1,   1, 1 }, },
124 	// all digits with leading binary prefix
125 	{ L"0b0",	{ 1,   0, 3 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1, 176, 3 },	{ 1,   0, 3 }, },
126 	{ L"0b1",	{ 1,   1, 3 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1, 177, 3 },	{ 1,   1, 3 }, },
127 	{ L"0b2",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1, 178, 3 },	{ 1,   0, 1 }, },
128 	{ L"0b3",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1, 179, 3 },	{ 1,   0, 1 }, },
129 	{ L"0b4",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1, 180, 3 },	{ 1,   0, 1 }, },
130 	{ L"0b5",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1, 181, 3 },	{ 1,   0, 1 }, },
131 	{ L"0b6",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1, 182, 3 },	{ 1,   0, 1 }, },
132 	{ L"0b7",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1, 183, 3 },	{ 1,   0, 1 }, },
133 	{ L"0b8",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1, 184, 3 },	{ 1,   0, 1 }, },
134 	{ L"0b9",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1, 185, 3 },	{ 1,   0, 1 }, },
135 	{ L"0bA",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1, 186, 3 },	{ 1,   0, 1 }, },
136 	{ L"0bB",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1, 187, 3 },	{ 1,   0, 1 }, },
137 	{ L"0bC",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1, 188, 3 },	{ 1,   0, 1 }, },
138 	{ L"0bD",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1, 189, 3 },	{ 1,   0, 1 }, },
139 	{ L"0bE",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1, 190, 3 },	{ 1,   0, 1 }, },
140 	{ L"0bF",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1, 191, 3 },	{ 1,   0, 1 }, },
141 	{ L"0bX",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,  11, 2 },	{ 1,   0, 1 }, },
142 	{ L"0ba",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1, 186, 3 },	{ 1,   0, 1 }, },
143 	{ L"0bb",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1, 187, 3 },	{ 1,   0, 1 }, },
144 	{ L"0bc",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1, 188, 3 },	{ 1,   0, 1 }, },
145 	{ L"0bd",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1, 189, 3 },	{ 1,   0, 1 }, },
146 	{ L"0be",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1, 190, 3 },	{ 1,   0, 1 }, },
147 	{ L"0bf",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1, 191, 3 },	{ 1,   0, 1 }, },
148 	{ L"0bx",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,  11, 2 },	{ 1,   0, 1 }, },
149 	// all digits with leading hexadecimal prefix
150 	{ L"0x0",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 3 },	{ 1,   0, 3 }, },
151 	{ L"0x1",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   1, 3 },	{ 1,   1, 3 }, },
152 	{ L"0x2",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   2, 3 },	{ 1,   2, 3 }, },
153 	{ L"0x3",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   3, 3 },	{ 1,   3, 3 }, },
154 	{ L"0x4",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   4, 3 },	{ 1,   4, 3 }, },
155 	{ L"0x5",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   5, 3 },	{ 1,   5, 3 }, },
156 	{ L"0x6",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   6, 3 },	{ 1,   6, 3 }, },
157 	{ L"0x7",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   7, 3 },	{ 1,   7, 3 }, },
158 	{ L"0x8",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   8, 3 },	{ 1,   8, 3 }, },
159 	{ L"0x9",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   9, 3 },	{ 1,   9, 3 }, },
160 	{ L"0xA",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,  10, 3 },	{ 1,  10, 3 }, },
161 	{ L"0xB",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,  11, 3 },	{ 1,  11, 3 }, },
162 	{ L"0xC",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,  12, 3 },	{ 1,  12, 3 }, },
163 	{ L"0xD",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,  13, 3 },	{ 1,  13, 3 }, },
164 	{ L"0xE",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,  14, 3 },	{ 1,  14, 3 }, },
165 	{ L"0xF",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,  15, 3 },	{ 1,  15, 3 }, },
166 	{ L"0xX",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 }, },
167 	{ L"0xa",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,  10, 3 },	{ 1,  10, 3 }, },
168 	{ L"0xb",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,  11, 3 },	{ 1,  11, 3 }, },
169 	{ L"0xc",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,  12, 3 },	{ 1,  12, 3 }, },
170 	{ L"0xd",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,  13, 3 },	{ 1,  13, 3 }, },
171 	{ L"0xe",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,  14, 3 },	{ 1,  14, 3 }, },
172 	{ L"0xf",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,  15, 3 },	{ 1,  15, 3 }, },
173 	{ L"0xX",	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 },	{ 1,   0, 1 }, },
174 	// terminator
175 	{ L"" }
176 };
177 
178 #define SWSCANF_TEST(string, format, expret, expval, explen)		\
179 	do {								\
180 		int ret = 0, val = 0, len = 0;				\
181 		ret = swscanf(string, format L"%n", &val, &len);	\
182 		ATF_CHECK_EQ(expret, ret);				\
183 		if (expret && ret) {					\
184 			ATF_CHECK_EQ(expval, val);			\
185 			ATF_CHECK_EQ(explen, len);			\
186 		}							\
187 	} while (0)
188 
189 ATF_TC_WITHOUT_HEAD(swscanf_b);
190 ATF_TC_BODY(swscanf_b, tc)
191 {
192 	const struct swscanf_test_case *stc;
193 	wchar_t input[16];
194 
195 	for (stc = swscanf_test_cases; *stc->input; stc++) {
196 		wcscpy(input + 1, stc->input);
197 		SWSCANF_TEST(input + 1, L"%b", stc->b.ret, stc->b.val, stc->b.len);
198 		input[0] = L'+';
199 		SWSCANF_TEST(input, L"%b", stc->b.ret, stc->b.val, stc->b.len ? stc->b.len + 1 : 0);
200 		input[0] = L'-';
201 		SWSCANF_TEST(input, L"%b", stc->b.ret, -stc->b.val, stc->b.len ? stc->b.len + 1 : 0);
202 	}
203 }
204 
205 ATF_TC_WITHOUT_HEAD(swscanf_o);
206 ATF_TC_BODY(swscanf_o, tc)
207 {
208 	const struct swscanf_test_case *stc;
209 	wchar_t input[16];
210 
211 	for (stc = swscanf_test_cases; *stc->input; stc++) {
212 		wcscpy(input + 1, stc->input);
213 		SWSCANF_TEST(input + 1, L"%o", stc->o.ret, stc->o.val, stc->o.len);
214 		input[0] = L'+';
215 		SWSCANF_TEST(input, L"%o", stc->o.ret, stc->o.val, stc->o.len ? stc->o.len + 1 : 0);
216 		input[0] = L'-';
217 		SWSCANF_TEST(input, L"%o", stc->o.ret, -stc->o.val, stc->o.len ? stc->o.len + 1 : 0);
218 	}
219 }
220 
221 ATF_TC_WITHOUT_HEAD(swscanf_d);
222 ATF_TC_BODY(swscanf_d, tc)
223 {
224 	const struct swscanf_test_case *stc;
225 	wchar_t input[16];
226 
227 	for (stc = swscanf_test_cases; *stc->input; stc++) {
228 		wcscpy(input + 1, stc->input);
229 		SWSCANF_TEST(input + 1, L"%d", stc->d.ret, stc->d.val, stc->d.len);
230 		input[0] = L'+';
231 		SWSCANF_TEST(input, L"%d", stc->d.ret, stc->d.val, stc->d.len ? stc->d.len + 1 : 0);
232 		input[0] = L'-';
233 		SWSCANF_TEST(input, L"%d", stc->d.ret, -stc->d.val, stc->d.len ? stc->d.len + 1 : 0);
234 	}
235 }
236 
237 ATF_TC_WITHOUT_HEAD(swscanf_x);
238 ATF_TC_BODY(swscanf_x, tc)
239 {
240 	const struct swscanf_test_case *stc;
241 	wchar_t input[16];
242 
243 	for (stc = swscanf_test_cases; *stc->input; stc++) {
244 		wcscpy(input + 1, stc->input);
245 		SWSCANF_TEST(input + 1, L"%x", stc->x.ret, stc->x.val, stc->x.len);
246 		input[0] = L'+';
247 		SWSCANF_TEST(input, L"%x", stc->x.ret, stc->x.val, stc->x.len ? stc->x.len + 1 : 0);
248 		input[0] = L'-';
249 		SWSCANF_TEST(input, L"%x", stc->x.ret, -stc->x.val, stc->x.len ? stc->x.len + 1 : 0);
250 	}
251 }
252 
253 ATF_TC_WITHOUT_HEAD(swscanf_i);
254 ATF_TC_BODY(swscanf_i, tc)
255 {
256 	const struct swscanf_test_case *stc;
257 	wchar_t input[16];
258 
259 	for (stc = swscanf_test_cases; *stc->input; stc++) {
260 		wcscpy(input + 1, stc->input);
261 		SWSCANF_TEST(input + 1, L"%i", stc->i.ret, stc->i.val, stc->i.len);
262 		input[0] = L'+';
263 		SWSCANF_TEST(input, L"%i", stc->i.ret, stc->i.val, stc->i.len ? stc->i.len + 1 : 0);
264 		input[0] = L'-';
265 		SWSCANF_TEST(input, L"%i", stc->i.ret, -stc->i.val, stc->i.len ? stc->i.len + 1 : 0);
266 	}
267 }
268 
269 ATF_TC_WITHOUT_HEAD(swscanf_wN);
270 ATF_TC_BODY(swscanf_wN, tc)
271 {
272 	const wchar_t x00[] = L"0x00";
273 	const wchar_t x7f[] = L"0x7fffffffffffffff";
274 	const wchar_t xff[] = L"0xffffffffffffffff";
275 
276 #define SWSCANF_WN_TEST(N, imin, umax)					\
277 	do {								\
278 		int##N##_t i;						\
279 		uint##N##_t u;						\
280 		ATF_CHECK_EQ(1, swscanf(x00, L"%w" L(#N) L"i", &i));	\
281 		ATF_CHECK_EQ(0, i);					\
282 		ATF_CHECK_EQ(1, swscanf(x7f, L"%w" L(#N) L"i", &i));	\
283 		ATF_CHECK_EQ(imin, i);					\
284 		ATF_CHECK_EQ(1, swscanf(x00, L"%w" L(#N) L"x", &u));	\
285 		ATF_CHECK_EQ(0, u);					\
286 		ATF_CHECK_EQ(1, swscanf(xff, L"%w" L(#N) L"x", &u));	\
287 		ATF_CHECK_EQ(umax, u);					\
288 	} while (0)
289 	SWSCANF_WN_TEST(8, -1, UCHAR_MAX);
290 	SWSCANF_WN_TEST(16, -1, USHRT_MAX);
291 	SWSCANF_WN_TEST(32, -1, UINT_MAX);
292 	SWSCANF_WN_TEST(64, LLONG_MAX, ULLONG_MAX);
293 #undef SWSCANF_WN_TEST
294 
295 	ATF_CHECK_EQ(0, swscanf(x00, L"%wi", (int *)NULL));
296 	ATF_CHECK_EQ(0, swscanf(x00, L"%w1i", (int *)NULL));
297 	ATF_CHECK_EQ(0, swscanf(x00, L"%w128i", (int *)NULL));
298 }
299 
300 ATF_TC_WITHOUT_HEAD(swscanf_wfN);
301 ATF_TC_BODY(swscanf_wfN, tc)
302 {
303 	const wchar_t x00[] = L"0x00";
304 	const wchar_t x7f[] = L"0x7fffffffffffffff";
305 	const wchar_t xff[] = L"0xffffffffffffffff";
306 
307 #define SWSCANF_WFN_TEST(N, imin, umax)					\
308 	do {								\
309 		int_fast##N##_t i;					\
310 		uint_fast##N##_t u;					\
311 		ATF_CHECK_EQ(1, swscanf(x00, L"%wf" L(#N) L"i", &i));	\
312 		ATF_CHECK_EQ(0, i);					\
313 		ATF_CHECK_EQ(1, swscanf(x7f, L"%wf" L(#N) L"i", &i));	\
314 		ATF_CHECK_EQ(imin, i);					\
315 		ATF_CHECK_EQ(1, swscanf(x00, L"%wf" L(#N) L"x", &u));	\
316 		ATF_CHECK_EQ(0, u);					\
317 		ATF_CHECK_EQ(1, swscanf(xff, L"%wf" L(#N) L"x", &u));	\
318 		ATF_CHECK_EQ(umax, u);					\
319 	} while (0)
320 	SWSCANF_WFN_TEST(8, -1, UINT_MAX);
321 	SWSCANF_WFN_TEST(16, -1, UINT_MAX);
322 	SWSCANF_WFN_TEST(32, -1, UINT_MAX);
323 	SWSCANF_WFN_TEST(64, LLONG_MAX, ULLONG_MAX);
324 #undef SWSCANF_WFN_TEST
325 
326 	ATF_CHECK_EQ(0, swscanf(x00, L"%wfi", (int *)NULL));
327 	ATF_CHECK_EQ(0, swscanf(x00, L"%wf1i", (int *)NULL));
328 	ATF_CHECK_EQ(0, swscanf(x00, L"%wf128i", (int *)NULL));
329 }
330 
331 /*
332  * Test termination cases: non-numeric character, fixed width, EOF
333  */
334 ATF_TC_WITHOUT_HEAD(swscanf_termination);
335 ATF_TC_BODY(swscanf_termination, tc)
336 {
337 	int a = 0, b = 0, c = 0;
338 	wchar_t d = 0;
339 
340 	ATF_CHECK_EQ(4, swscanf(L"3.1415", L"%d%lc%2d%d", &a, &d, &b, &c));
341 	ATF_CHECK_EQ(3, a);
342 	ATF_CHECK_EQ(14, b);
343 	ATF_CHECK_EQ(15, c);
344 	ATF_CHECK_EQ(L'.', d);
345 }
346 
347 ATF_TP_ADD_TCS(tp)
348 {
349 	setlocale(LC_NUMERIC, "en_US.UTF-8");
350 	ATF_TP_ADD_TC(tp, swscanf_b);
351 	ATF_TP_ADD_TC(tp, swscanf_o);
352 	ATF_TP_ADD_TC(tp, swscanf_d);
353 	ATF_TP_ADD_TC(tp, swscanf_x);
354 	ATF_TP_ADD_TC(tp, swscanf_i);
355 	ATF_TP_ADD_TC(tp, swscanf_wN);
356 	ATF_TP_ADD_TC(tp, swscanf_wfN);
357 	ATF_TP_ADD_TC(tp, swscanf_termination);
358 	return (atf_no_error());
359 }
360