1 /* Test for user-defined types in vfprintf.
2 Copyright (C) 2017-2024 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
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/>. */
19 /* This test contains a printf format specifier, %P, with a custom
20 type which is a long/double pair. If a precision is specified,
21 this indicates the number of such pairs which constitute the
24 #include <array_length.h>
30 #include <support/check.h>
31 #include <support/support.h>
32 #include <support/test-driver.h>
35 /* Initialized by do_test using register_printf_type. */
45 my_va_arg_function (void *mem
, va_list *ap
)
48 printf ("info: %s (%p) called\n", __func__
, mem
);
50 struct two_argument
*pair
= mem
;
51 pair
->i
= va_arg (*ap
, long);
52 pair
->d
= va_arg (*ap
, double);
56 my_printf_function (FILE *fp
, const struct printf_info
*info
,
57 const void *const *args
)
60 printf ("info: %s (%p, %p, {%p}@%p) called for %%%lc (prec %d)\n",
61 __func__
, fp
, info
, args
[0], args
, (wint_t) info
->spec
,
64 TEST_COMPARE (info
->wide
, fwide (fp
, 0) > 0);
66 TEST_VERIFY (info
->spec
== 'P');
73 if (fputwc (L
'{', fp
) < 0)
78 if (fputc ('{', fp
) < 0)
90 for (size_t i
= 0; i
< nargs
; ++i
)
96 if (fputwc (L
',', fp
) < 0)
101 if (fputc (',', fp
) < 0)
107 /* NB: Triple pointer indirection. ARGS is an array of void *,
108 and those pointers point to a pointer to the memory area
109 supplied to my_va_arg_function. */
110 struct two_argument
*pair
= *(void **) args
[i
];
113 ret
= fwprintf (fp
, L
"(%ld, %f)", pair
->i
, pair
->d
);
115 ret
= fprintf (fp
, "(%ld, %f)", pair
->i
, pair
->d
);
124 if (fputwc (L
'}', fp
) < 0)
129 if (fputc ('}', fp
) < 0)
138 my_arginfo_function (const struct printf_info
*info
,
139 size_t n
, int *argtypes
, int *size
)
141 /* Avoid recursion. */
142 if (info
->spec
!= 'P')
144 if (test_verbose
> 0)
145 printf ("info: %s (%p, %zu, %p, %p) called for %%%lc (prec %d)\n",
146 __func__
, info
, n
, argtypes
, size
, (wint_t) info
->spec
,
149 TEST_VERIFY_EXIT (n
>= 1);
156 size_t to_fill
= nargs
;
159 for (size_t i
= 0; i
< to_fill
; ++i
)
161 argtypes
[i
] = user_type
;
162 size
[i
] = sizeof (struct two_argument
);
164 if (test_verbose
> 0)
165 printf ("info: %s return value: %zu\n", __func__
, nargs
);
172 user_type
= register_printf_type (my_va_arg_function
);
173 if (test_verbose
> 0)
174 printf ("info: allocated user type: %d\n", user_type
);
175 TEST_VERIFY_EXIT (user_type
>= PA_LAST
);
176 TEST_VERIFY_EXIT (register_printf_specifier
177 ('P', my_printf_function
, my_arginfo_function
) >= 0);
179 /* Alias declaration for asprintf, to avoid the format string
180 attribute and the associated warning. */
181 #if __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 1
182 extern int asprintf_alias (char **, const char *, ...) __asm__ ("__asprintfieee128");
184 extern int asprintf_alias (char **, const char *, ...) __asm__ ("asprintf");
186 TEST_VERIFY (asprintf_alias
== asprintf
);
188 TEST_VERIFY (asprintf_alias (&str
, "[[%P]]", 123L, 456.0) >= 0);
189 TEST_COMPARE_STRING (str
, "[[(123, 456.000000)]]");
193 TEST_VERIFY (asprintf_alias (&str
, "[[%1$P %1$P]]", 123L, 457.0) >= 0);
194 TEST_COMPARE_STRING (str
, "[[(123, 457.000000) (123, 457.000000)]]");
198 TEST_VERIFY (asprintf_alias (&str
, "%1$P %2$P %3$P %4$P %5$P %6$P",
209 TEST_VERIFY (asprintf_alias (&str
, "%1$P %2$P %3$P %4$P %5$P %6$P"
210 "%7$P %8$P %9$P %10$P %11$P %12$P",
227 TEST_VERIFY (asprintf_alias (&str
, "%1$P %2$P %3$P %4$P %5$P %6$P"
228 "%7$P %8$P %9$P %10$P %11$P %12$P"
229 "%13$P %14$P %15$P %16$P %17$P %18$P",
252 TEST_VERIFY (asprintf_alias (&str
, "%1$P %2$P %3$P %4$P %5$P %6$P"
253 "%7$P %8$P %9$P %10$P %11$P %12$P"
254 "%13$P %14$P %15$P %16$P %17$P %18$P"
255 "%19$P %20$P %21$P %22$P %23$P %24$P",
284 TEST_VERIFY (asprintf_alias (&str
, "%1$P %2$P %3$P %4$P %5$P %6$P"
285 "%7$P %8$P %9$P %10$P %11$P %12$P"
286 "%13$P %14$P %15$P %16$P %17$P %18$P"
287 "%19$P %20$P %21$P %22$P %23$P %24$P"
288 "%25$P %26$P %27$P %28$P %29$P %30$P",
323 TEST_VERIFY (asprintf_alias (&str
, "[[%1$P %1$P]]", 123L, 457.0) >= 0);
324 TEST_COMPARE_STRING (str
, "[[(123, 457.000000) (123, 457.000000)]]");
328 TEST_VERIFY (asprintf_alias (&str
, "[[%.1P]]", 1L, 2.0) >= 0);
329 TEST_COMPARE_STRING (str
, "[[{(1, 2.000000)}]]");
333 TEST_VERIFY (asprintf_alias (&str
, "[[%.2P]]", 1L, 2.0, 3L, 4.0) >= 0);
334 TEST_COMPARE_STRING (str
, "[[{(1, 2.000000),(3, 4.000000)}]]");
338 TEST_VERIFY (asprintf_alias
339 (&str
, "[[%.2P | %.3P]]",
340 /* argument 1: */ 1L, 2.0, 3L, 4.0,
341 /* argument 2: */ 5L, 6.0, 7L, 8.0, 9L, 10.0)
343 TEST_COMPARE_STRING (str
,
345 "{(1, 2.000000),(3, 4.000000)}"
347 "{(5, 6.000000),(7, 8.000000),(9, 10.000000)}"
351 /* The following subtest fails due to bug 21534. */
354 TEST_VERIFY (asprintf_alias
355 (&str
, "[[%1$.2P | %2$.3P | %1$.2P]]",
356 /* argument 1: */ 1L, 2.0, 3L, 4.0,
357 /* argument 2: */ 5L, 6.0, 7L, 8.0, 9L, 10.0)
359 TEST_COMPARE_STRING (str
,
361 "{(1, 2.000000),(3, 4.000000)}"
363 "{(5, 6.000000),(7, 8.000000),(9, 10.000000)}"
365 "{(1, 2.000000),(3, 4.000000)}"
370 /* Wide variants of the tests above. */
373 TEST_VERIFY (swprintf (buf
, array_length (buf
), L
"[[%P]]", 123L, 456.0)
375 TEST_COMPARE_STRING_WIDE (buf
, L
"[[(123, 456.000000)]]");
377 TEST_VERIFY (swprintf (buf
, array_length (buf
), L
"[[%1$P %1$P]]",
379 TEST_COMPARE_STRING_WIDE (buf
, L
"[[(123, 457.000000) (123, 457.000000)]]");
381 TEST_VERIFY (swprintf (buf
, array_length (buf
), L
"[[%.1P]]", 1L, 2.0) >= 0);
382 TEST_COMPARE_STRING_WIDE (buf
, L
"[[{(1, 2.000000)}]]");
384 TEST_VERIFY (swprintf (buf
, array_length (buf
), L
"[[%.2P]]",
385 1L, 2.0, 3L, 4.0) >= 0);
386 TEST_COMPARE_STRING_WIDE (buf
, L
"[[{(1, 2.000000),(3, 4.000000)}]]");
388 TEST_VERIFY (swprintf
389 (buf
, array_length (buf
), L
"[[%.2P | %.3P]]",
390 /* argument 1: */ 1L, 2.0, 3L, 4.0,
391 /* argument 2: */ 5L, 6.0, 7L, 8.0, 9L, 10.0)
393 TEST_COMPARE_STRING_WIDE (buf
,
395 "{(1, 2.000000),(3, 4.000000)}"
397 "{(5, 6.000000),(7, 8.000000),(9, 10.000000)}"
400 /* The following subtest fails due to bug 21534. */
402 TEST_VERIFY (swprintf
403 (&buf
, array_length (buf
), L
"[[%1$.2P | %2$.3P | %1$.2P]]",
404 /* argument 1: */ 1L, 2.0, 3L, 4.0,
405 /* argument 2: */ 5L, 6.0, 7L, 8.0, 9L, 10.0)
407 TEST_COMPARE_STRING_WIDE (buf
,
409 "{(1, 2.000000),(3, 4.000000)}"
411 "{(5, 6.000000),(7, 8.000000),(9, 10.000000)}"
413 "{(1, 2.000000),(3, 4.000000)}"
420 #include <support/test-driver.c>