1/* Test scanf functions with C2X binary integers.
2 Copyright (C) 2022-2024 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19#include <inttypes.h>
20#include <stdarg.h>
21#include <stdio.h>
22#include <wchar.h>
23
24#include <libc-diag.h>
25#include <support/check.h>
26#include <support/xstdio.h>
27
28#define CONCAT_(X, Y, Z) X ## Y ## Z
29#define CONCAT(X, Y, Z) CONCAT_ (X, Y, Z)
30#define FNX(FN1, FN2) CONCAT (FN1, FNW, FN2)
31#ifndef STDX
32# define STDX ""
33#endif
34
35#define INFILE OBJPFX "/tst-" STDX "scanf-binary-" STD "-in"
36
37static int
38wrap_vfscanf (FILE *fp, const CHAR *format, ...)
39{
40 va_list ap;
41 va_start (ap, format);
42 int ret = FNX (vf, scanf) (s: fp, format: format, arg: ap);
43 va_end (ap);
44 return ret;
45}
46
47static int
48wrap_vscanf (const CHAR *format, ...)
49{
50 va_list ap;
51 va_start (ap, format);
52 int ret = FNX (v, scanf) (format: format, arg: ap);
53 va_end (ap);
54 return ret;
55}
56
57static int
58wrap_vsscanf (const CHAR *s, const CHAR *format, ...)
59{
60 va_list ap;
61 va_start (ap, format);
62 int ret = FNX (vs, scanf) (s: s, format: format, arg: ap);
63 va_end (ap);
64 return ret;
65}
66
67static void
68one_check (const CHAR *s, int expected, char expected_c)
69{
70 int ret;
71 FILE *fp;
72 int ret_i;
73 long int ret_l;
74 long long int ret_ll;
75 char ret_c;
76 fp = xfopen (INFILE, "w");
77 ret = FNX (fput, s) (s, fp);
78 TEST_VERIFY_EXIT (0 <= ret);
79 xfclose (fp);
80
81 if (!TEST_C2X)
82 {
83 expected = 0;
84 expected_c = s[0] == L_('-') ? s[2] : s[1];
85 }
86
87 ret = FNX (s, scanf) (s, L_("%i %c"), &ret_i, &ret_c);
88 TEST_COMPARE (ret, 2);
89 TEST_COMPARE (ret_i, expected);
90 TEST_COMPARE (ret_c, expected_c);
91 fp = xfopen (INFILE, "r");
92 ret = FNX (f, scanf) (stream: fp, L_("%i %c"), &ret_i, &ret_c);
93 TEST_COMPARE (ret, 2);
94 TEST_COMPARE (ret_i, expected);
95 TEST_COMPARE (ret_c, expected_c);
96 xfclose (fp);
97 fp = xfreopen (INFILE, "r", stdin);
98 ret = FNX (, scanf) (L_("%i %c"), &ret_i, &ret_c);
99 TEST_COMPARE (ret, 2);
100 TEST_COMPARE (ret_i, expected);
101 TEST_COMPARE (ret_c, expected_c);
102 ret = wrap_vsscanf (s, L_("%i %c"), &ret_i, &ret_c);
103 TEST_COMPARE (ret, 2);
104 TEST_COMPARE (ret_i, expected);
105 TEST_COMPARE (ret_c, expected_c);
106 fp = xfopen (INFILE, "r");
107 ret = wrap_vfscanf (fp, L_("%i %c"), &ret_i, &ret_c);
108 TEST_COMPARE (ret, 2);
109 TEST_COMPARE (ret_i, expected);
110 TEST_COMPARE (ret_c, expected_c);
111 xfclose (fp);
112 fp = xfreopen (INFILE, "r", stdin);
113 ret = wrap_vscanf (L_("%i %c"), &ret_i, &ret_c);
114 TEST_COMPARE (ret, 2);
115 TEST_COMPARE (ret_i, expected);
116 TEST_COMPARE (ret_c, expected_c);
117
118 ret = FNX (s, scanf) (s, L_("%li %c"), &ret_l, &ret_c);
119 TEST_COMPARE (ret, 2);
120 TEST_COMPARE (ret_l, expected);
121 TEST_COMPARE (ret_c, expected_c);
122 fp = xfopen (INFILE, "r");
123 ret = FNX (f, scanf) (stream: fp, L_("%li %c"), &ret_l, &ret_c);
124 TEST_COMPARE (ret, 2);
125 TEST_COMPARE (ret_l, expected);
126 TEST_COMPARE (ret_c, expected_c);
127 xfclose (fp);
128 fp = xfreopen (INFILE, "r", stdin);
129 ret = FNX (, scanf) (L_("%li %c"), &ret_l, &ret_c);
130 TEST_COMPARE (ret, 2);
131 TEST_COMPARE (ret_l, expected);
132 TEST_COMPARE (ret_c, expected_c);
133 ret = wrap_vsscanf (s, L_("%li %c"), &ret_l, &ret_c);
134 TEST_COMPARE (ret, 2);
135 TEST_COMPARE (ret_l, expected);
136 TEST_COMPARE (ret_c, expected_c);
137 fp = xfopen (INFILE, "r");
138 ret = wrap_vfscanf (fp, L_("%li %c"), &ret_l, &ret_c);
139 TEST_COMPARE (ret, 2);
140 TEST_COMPARE (ret_l, expected);
141 TEST_COMPARE (ret_c, expected_c);
142 xfclose (fp);
143 fp = xfreopen (INFILE, "r", stdin);
144 ret = wrap_vscanf (L_("%li %c"), &ret_l, &ret_c);
145 TEST_COMPARE (ret, 2);
146 TEST_COMPARE (ret_l, expected);
147 TEST_COMPARE (ret_c, expected_c);
148
149 ret = FNX (s, scanf) (s, L_("%lli %c"), &ret_ll, &ret_c);
150 TEST_COMPARE (ret, 2);
151 TEST_COMPARE (ret_ll, expected);
152 TEST_COMPARE (ret_c, expected_c);
153 fp = xfopen (INFILE, "r");
154 ret = FNX (f, scanf) (stream: fp, L_("%lli %c"), &ret_ll, &ret_c);
155 TEST_COMPARE (ret, 2);
156 TEST_COMPARE (ret_ll, expected);
157 TEST_COMPARE (ret_c, expected_c);
158 xfclose (fp);
159 fp = xfreopen (INFILE, "r", stdin);
160 ret = FNX (, scanf) (L_("%lli %c"), &ret_ll, &ret_c);
161 TEST_COMPARE (ret, 2);
162 TEST_COMPARE (ret_ll, expected);
163 TEST_COMPARE (ret_c, expected_c);
164 ret = wrap_vsscanf (s, L_("%lli %c"), &ret_ll, &ret_c);
165 TEST_COMPARE (ret, 2);
166 TEST_COMPARE (ret_ll, expected);
167 TEST_COMPARE (ret_c, expected_c);
168 fp = xfopen (INFILE, "r");
169 ret = wrap_vfscanf (fp, L_("%lli %c"), &ret_ll, &ret_c);
170 TEST_COMPARE (ret, 2);
171 TEST_COMPARE (ret_ll, expected);
172 TEST_COMPARE (ret_c, expected_c);
173 xfclose (fp);
174 fp = xfreopen (INFILE, "r", stdin);
175 ret = wrap_vscanf (L_("%lli %c"), &ret_ll, &ret_c);
176 TEST_COMPARE (ret, 2);
177 TEST_COMPARE (ret_ll, expected);
178 TEST_COMPARE (ret_c, expected_c);
179}
180
181/* GCC does not know the %b format before GCC 12. */
182DIAG_PUSH_NEEDS_COMMENT;
183#if !__GNUC_PREREQ (12, 0)
184DIAG_IGNORE_NEEDS_COMMENT (11, "-Wformat");
185DIAG_IGNORE_NEEDS_COMMENT (11, "-Wformat-extra-args");
186#endif
187
188static void
189one_check_b (const CHAR *s, int expected, char expected_c)
190{
191 int ret;
192 FILE *fp;
193 unsigned int ret_i;
194 unsigned long int ret_l;
195 unsigned long long int ret_ll;
196 char ret_c;
197 fp = xfopen (INFILE, "w");
198 ret = FNX (fput, s) (s, fp);
199 TEST_VERIFY_EXIT (0 <= ret);
200 xfclose (fp);
201
202 ret = FNX (s, scanf) (s, L_("%b %c"), &ret_i, &ret_c);
203 TEST_COMPARE (ret, 2);
204 TEST_COMPARE (ret_i, (unsigned int) expected);
205 TEST_COMPARE (ret_c, expected_c);
206 fp = xfopen (INFILE, "r");
207 ret = FNX (f, scanf) (stream: fp, L_("%b %c"), &ret_i, &ret_c);
208 TEST_COMPARE (ret, 2);
209 TEST_COMPARE (ret_i, (unsigned int) expected);
210 TEST_COMPARE (ret_c, expected_c);
211 xfclose (fp);
212 fp = xfreopen (INFILE, "r", stdin);
213 ret = FNX (, scanf) (L_("%b %c"), &ret_i, &ret_c);
214 TEST_COMPARE (ret, 2);
215 TEST_COMPARE (ret_i, (unsigned int) expected);
216 TEST_COMPARE (ret_c, expected_c);
217 ret = wrap_vsscanf (s, L_("%b %c"), &ret_i, &ret_c);
218 TEST_COMPARE (ret, 2);
219 TEST_COMPARE (ret_i, (unsigned int) expected);
220 TEST_COMPARE (ret_c, expected_c);
221 fp = xfopen (INFILE, "r");
222 ret = wrap_vfscanf (fp, L_("%b %c"), &ret_i, &ret_c);
223 TEST_COMPARE (ret, 2);
224 TEST_COMPARE (ret_i, (unsigned int) expected);
225 TEST_COMPARE (ret_c, expected_c);
226 xfclose (fp);
227 fp = xfreopen (INFILE, "r", stdin);
228 ret = wrap_vscanf (L_("%b %c"), &ret_i, &ret_c);
229 TEST_COMPARE (ret, 2);
230 TEST_COMPARE (ret_i, (unsigned int) expected);
231 TEST_COMPARE (ret_c, expected_c);
232
233 ret = FNX (s, scanf) (s, L_("%lb %c"), &ret_l, &ret_c);
234 TEST_COMPARE (ret, 2);
235 TEST_COMPARE (ret_l, (unsigned long int) expected);
236 TEST_COMPARE (ret_c, expected_c);
237 fp = xfopen (INFILE, "r");
238 ret = FNX (f, scanf) (stream: fp, L_("%lb %c"), &ret_l, &ret_c);
239 TEST_COMPARE (ret, 2);
240 TEST_COMPARE (ret_l, (unsigned long int) expected);
241 TEST_COMPARE (ret_c, expected_c);
242 xfclose (fp);
243 fp = xfreopen (INFILE, "r", stdin);
244 ret = FNX (, scanf) (L_("%lb %c"), &ret_l, &ret_c);
245 TEST_COMPARE (ret, 2);
246 TEST_COMPARE (ret_l, (unsigned long int) expected);
247 TEST_COMPARE (ret_c, expected_c);
248 ret = wrap_vsscanf (s, L_("%lb %c"), &ret_l, &ret_c);
249 TEST_COMPARE (ret, 2);
250 TEST_COMPARE (ret_l, (unsigned long int) expected);
251 TEST_COMPARE (ret_c, expected_c);
252 fp = xfopen (INFILE, "r");
253 ret = wrap_vfscanf (fp, L_("%lb %c"), &ret_l, &ret_c);
254 TEST_COMPARE (ret, 2);
255 TEST_COMPARE (ret_l, (unsigned long int) expected);
256 TEST_COMPARE (ret_c, expected_c);
257 xfclose (fp);
258 fp = xfreopen (INFILE, "r", stdin);
259 ret = wrap_vscanf (L_("%lb %c"), &ret_l, &ret_c);
260 TEST_COMPARE (ret, 2);
261 TEST_COMPARE (ret_l, (unsigned long int) expected);
262 TEST_COMPARE (ret_c, expected_c);
263
264 ret = FNX (s, scanf) (s, L_("%llb %c"), &ret_ll, &ret_c);
265 TEST_COMPARE (ret, 2);
266 TEST_COMPARE (ret_ll, (unsigned long long int) expected);
267 TEST_COMPARE (ret_c, expected_c);
268 fp = xfopen (INFILE, "r");
269 ret = FNX (f, scanf) (stream: fp, L_("%llb %c"), &ret_ll, &ret_c);
270 TEST_COMPARE (ret, 2);
271 TEST_COMPARE (ret_ll, (unsigned long long int) expected);
272 TEST_COMPARE (ret_c, expected_c);
273 xfclose (fp);
274 fp = xfreopen (INFILE, "r", stdin);
275 ret = FNX (, scanf) (L_("%llb %c"), &ret_ll, &ret_c);
276 TEST_COMPARE (ret, 2);
277 TEST_COMPARE (ret_ll, (unsigned long long int) expected);
278 TEST_COMPARE (ret_c, expected_c);
279 ret = wrap_vsscanf (s, L_("%llb %c"), &ret_ll, &ret_c);
280 TEST_COMPARE (ret, 2);
281 TEST_COMPARE (ret_ll, (unsigned long long int) expected);
282 TEST_COMPARE (ret_c, expected_c);
283 fp = xfopen (INFILE, "r");
284 ret = wrap_vfscanf (fp, L_("%llb %c"), &ret_ll, &ret_c);
285 TEST_COMPARE (ret, 2);
286 TEST_COMPARE (ret_ll, (unsigned long long int) expected);
287 TEST_COMPARE (ret_c, expected_c);
288 xfclose (fp);
289 fp = xfreopen (INFILE, "r", stdin);
290 ret = wrap_vscanf (L_("%llb %c"), &ret_ll, &ret_c);
291 TEST_COMPARE (ret, 2);
292 TEST_COMPARE (ret_ll, (unsigned long long int) expected);
293 TEST_COMPARE (ret_c, expected_c);
294}
295
296#define CHECK_SCNB(TYPE, MACRO, S, EXPECTED, EXPECTED_C) \
297 do \
298 { \
299 int ret; \
300 FILE *fp; \
301 TYPE ret_t; \
302 char ret_c; \
303 fp = xfopen (INFILE, "w"); \
304 ret = FNX (fput, s) (S, fp); \
305 TEST_VERIFY_EXIT (0 <= ret); \
306 xfclose (fp); \
307 ret = FNX (s, scanf) (S, L_("%") MACRO " %c", &ret_t, &ret_c); \
308 TEST_COMPARE (ret, 2); \
309 TEST_COMPARE (ret_t, EXPECTED); \
310 TEST_COMPARE (ret_c, EXPECTED_C); \
311 fp = xfopen (INFILE, "r"); \
312 ret = FNX (f, scanf) (fp, L_("%") MACRO " %c", &ret_t, &ret_c); \
313 TEST_COMPARE (ret, 2); \
314 TEST_COMPARE (ret_t, EXPECTED); \
315 TEST_COMPARE (ret_c, EXPECTED_C); \
316 xfclose (fp); \
317 fp = xfreopen (INFILE, "r", stdin); \
318 ret = FNX (, scanf) (L_("%") MACRO " %c", &ret_t, &ret_c); \
319 TEST_COMPARE (ret, 2); \
320 TEST_COMPARE (ret_t, EXPECTED); \
321 TEST_COMPARE (ret_c, EXPECTED_C); \
322 ret = wrap_vsscanf (S, L_("%") MACRO " %c", &ret_t, &ret_c); \
323 TEST_COMPARE (ret, 2); \
324 TEST_COMPARE (ret_t, EXPECTED); \
325 TEST_COMPARE (ret_c, EXPECTED_C); \
326 fp = xfopen (INFILE, "r"); \
327 ret = wrap_vfscanf (fp, L_("%") MACRO " %c", &ret_t, &ret_c); \
328 TEST_COMPARE (ret, 2); \
329 TEST_COMPARE (ret_t, EXPECTED); \
330 TEST_COMPARE (ret_c, EXPECTED_C); \
331 xfclose (fp); \
332 fp = xfreopen (INFILE, "r", stdin); \
333 ret = wrap_vscanf (L_("%") MACRO " %c", &ret_t, &ret_c); \
334 TEST_COMPARE (ret, 2); \
335 TEST_COMPARE (ret_t, EXPECTED); \
336 TEST_COMPARE (ret_c, EXPECTED_C); \
337 } \
338 while (0)
339
340static void
341one_check_scnb (const CHAR *s, int expected, char expected_c)
342{
343#if TEST_C2X || defined _GNU_SOURCE
344 CHECK_SCNB (uint8_t, SCNb8, s, (uint8_t) expected, expected_c);
345 CHECK_SCNB (uint16_t, SCNb16, s, (uint16_t) expected, expected_c);
346 CHECK_SCNB (uint32_t, SCNb32, s, (uint32_t) expected, expected_c);
347 CHECK_SCNB (uint64_t, SCNb64, s, (uint64_t) expected, expected_c);
348 CHECK_SCNB (uint_least8_t, SCNbLEAST8, s, (uint_least8_t) expected,
349 expected_c);
350 CHECK_SCNB (uint_least16_t, SCNbLEAST16, s, (uint_least16_t) expected,
351 expected_c);
352 CHECK_SCNB (uint_least32_t, SCNbLEAST32, s, (uint_least32_t) expected,
353 expected_c);
354 CHECK_SCNB (uint_least64_t, SCNbLEAST64, s, (uint_least64_t) expected,
355 expected_c);
356 CHECK_SCNB (uint_fast8_t, SCNbFAST8, s, (uint_fast8_t) expected, expected_c);
357 CHECK_SCNB (uint_fast16_t, SCNbFAST16, s, (uint_fast16_t) expected,
358 expected_c);
359 CHECK_SCNB (uint_fast32_t, SCNbFAST32, s, (uint_fast32_t) expected,
360 expected_c);
361 CHECK_SCNB (uint_fast64_t, SCNbFAST64, s, (uint_fast64_t) expected,
362 expected_c);
363 CHECK_SCNB (uintmax_t, SCNbMAX, s, (uintmax_t) expected, expected_c);
364 CHECK_SCNB (uintptr_t, SCNbPTR, s, (uintptr_t) expected, expected_c);
365#endif
366}
367
368DIAG_POP_NEEDS_COMMENT;
369
370static int
371do_test (void)
372{
373 one_check (L_("0b101 x"), expected: 5, expected_c: 'x');
374 one_check (L_("0B101 x"), expected: 5, expected_c: 'x');
375 one_check (L_("-0b11111 y"), expected: -31, expected_c: 'y');
376 one_check (L_("-0B11111 y"), expected: -31, expected_c: 'y');
377 one_check_b (L_("0b101 x"), expected: 5, expected_c: 'x');
378 one_check_b (L_("0B101 x"), expected: 5, expected_c: 'x');
379 one_check_b (L_("-0b11111 y"), expected: -31, expected_c: 'y');
380 one_check_b (L_("-0B11111 y"), expected: -31, expected_c: 'y');
381 one_check_b (L_("101 x"), expected: 5, expected_c: 'x');
382 one_check_b (L_("-11111 y"), expected: -31, expected_c: 'y');
383 one_check_scnb (L_("0b101 x"), expected: 5, expected_c: 'x');
384 one_check_scnb (L_("0B101 x"), expected: 5, expected_c: 'x');
385 one_check_scnb (L_("-0b11111 y"), expected: -31, expected_c: 'y');
386 one_check_scnb (L_("-0B11111 y"), expected: -31, expected_c: 'y');
387 one_check_scnb (L_("101 x"), expected: 5, expected_c: 'x');
388 one_check_scnb (L_("-11111 y"), expected: -31, expected_c: 'y');
389 return 0;
390}
391
392#include <support/test-driver.c>
393

source code of glibc/stdio-common/tst-scanf-binary-main.c