1 /* Test for user-defined types in vfprintf.
2 Copyright (C) 2017-2022 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
, "[[%.1P]]", 1L, 2.0) >= 0);
199 TEST_COMPARE_STRING (str
, "[[{(1, 2.000000)}]]");
203 TEST_VERIFY (asprintf_alias (&str
, "[[%.2P]]", 1L, 2.0, 3L, 4.0) >= 0);
204 TEST_COMPARE_STRING (str
, "[[{(1, 2.000000),(3, 4.000000)}]]");
208 TEST_VERIFY (asprintf_alias
209 (&str
, "[[%.2P | %.3P]]",
210 /* argument 1: */ 1L, 2.0, 3L, 4.0,
211 /* argument 2: */ 5L, 6.0, 7L, 8.0, 9L, 10.0)
213 TEST_COMPARE_STRING (str
,
215 "{(1, 2.000000),(3, 4.000000)}"
217 "{(5, 6.000000),(7, 8.000000),(9, 10.000000)}"
221 /* The following subtest fails due to bug 21534. */
224 TEST_VERIFY (asprintf_alias
225 (&str
, "[[%1$.2P | %2$.3P | %1$.2P]]",
226 /* argument 1: */ 1L, 2.0, 3L, 4.0,
227 /* argument 2: */ 5L, 6.0, 7L, 8.0, 9L, 10.0)
229 TEST_COMPARE_STRING (str
,
231 "{(1, 2.000000),(3, 4.000000)}"
233 "{(5, 6.000000),(7, 8.000000),(9, 10.000000)}"
235 "{(1, 2.000000),(3, 4.000000)}"
240 /* Wide variants of the tests above. */
243 TEST_VERIFY (swprintf (buf
, array_length (buf
), L
"[[%P]]", 123L, 456.0)
245 TEST_COMPARE_STRING_WIDE (buf
, L
"[[(123, 456.000000)]]");
247 TEST_VERIFY (swprintf (buf
, array_length (buf
), L
"[[%1$P %1$P]]",
249 TEST_COMPARE_STRING_WIDE (buf
, L
"[[(123, 457.000000) (123, 457.000000)]]");
251 TEST_VERIFY (swprintf (buf
, array_length (buf
), L
"[[%.1P]]", 1L, 2.0) >= 0);
252 TEST_COMPARE_STRING_WIDE (buf
, L
"[[{(1, 2.000000)}]]");
254 TEST_VERIFY (swprintf (buf
, array_length (buf
), L
"[[%.2P]]",
255 1L, 2.0, 3L, 4.0) >= 0);
256 TEST_COMPARE_STRING_WIDE (buf
, L
"[[{(1, 2.000000),(3, 4.000000)}]]");
258 TEST_VERIFY (swprintf
259 (buf
, array_length (buf
), L
"[[%.2P | %.3P]]",
260 /* argument 1: */ 1L, 2.0, 3L, 4.0,
261 /* argument 2: */ 5L, 6.0, 7L, 8.0, 9L, 10.0)
263 TEST_COMPARE_STRING_WIDE (buf
,
265 "{(1, 2.000000),(3, 4.000000)}"
267 "{(5, 6.000000),(7, 8.000000),(9, 10.000000)}"
270 /* The following subtest fails due to bug 21534. */
272 TEST_VERIFY (swprintf
273 (&buf
, array_length (buf
), L
"[[%1$.2P | %2$.3P | %1$.2P]]",
274 /* argument 1: */ 1L, 2.0, 3L, 4.0,
275 /* argument 2: */ 5L, 6.0, 7L, 8.0, 9L, 10.0)
277 TEST_COMPARE_STRING_WIDE (buf
,
279 "{(1, 2.000000),(3, 4.000000)}"
281 "{(5, 6.000000),(7, 8.000000),(9, 10.000000)}"
283 "{(1, 2.000000),(3, 4.000000)}"
290 #include <support/test-driver.c>