assert: Reformat Makefile.
[glibc.git] / stdio-common / tst-vfprintf-user-type.c
blob7cc69dc71658978526b10d4c3f98dd36ad502ab9
1 /* Test for user-defined types in vfprintf.
2 Copyright (C) 2017-2023 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
22 argument. */
24 #include <array_length.h>
25 #include <locale.h>
26 #include <printf.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <support/check.h>
31 #include <support/support.h>
32 #include <support/test-driver.h>
33 #include <wchar.h>
35 /* Initialized by do_test using register_printf_type. */
36 static int user_type;
38 struct two_argument
40 long i;
41 double d;
44 static void
45 my_va_arg_function (void *mem, va_list *ap)
47 if (test_verbose > 0)
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);
55 static int
56 my_printf_function (FILE *fp, const struct printf_info *info,
57 const void *const *args)
59 if (test_verbose > 0)
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,
62 info->prec);
64 TEST_COMPARE (info->wide, fwide (fp, 0) > 0);
66 TEST_VERIFY (info->spec == 'P');
67 size_t nargs;
68 int printed;
69 if (info->prec >= 0)
71 if (info->wide)
73 if (fputwc (L'{', fp) < 0)
74 return -1;
76 else
78 if (fputc ('{', fp) < 0)
79 return -1;
81 nargs = info->prec;
82 printed = 1;
84 else
86 nargs = 1;
87 printed = 0;
90 for (size_t i = 0; i < nargs; ++i)
92 if (i != 0)
94 if (info->wide)
96 if (fputwc (L',', fp) < 0)
97 return -1;
99 else
101 if (fputc (',', fp) < 0)
102 return -1;
104 ++printed;
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];
111 int ret;
112 if (info->wide)
113 ret = fwprintf (fp, L"(%ld, %f)", pair->i, pair->d);
114 else
115 ret = fprintf (fp, "(%ld, %f)", pair->i, pair->d);
116 if (ret < 0)
117 return -1;
118 printed += ret;
120 if (info->prec >= 0)
122 if (info->wide)
124 if (fputwc (L'}', fp) < 0)
125 return -1;
127 else
129 if (fputc ('}', fp) < 0)
130 return -1;
132 ++printed;
134 return printed;
137 static int
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')
143 return -1;
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,
147 info->prec);
149 TEST_VERIFY_EXIT (n >= 1);
150 size_t nargs;
151 if (info->prec >= 0)
152 nargs = info->prec;
153 else
154 nargs = 1;
156 size_t to_fill = nargs;
157 if (to_fill > n)
158 to_fill = n;
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);
166 return nargs;
169 static int
170 do_test (void)
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");
183 #else
184 extern int asprintf_alias (char **, const char *, ...) __asm__ ("asprintf");
185 #endif
186 TEST_VERIFY (asprintf_alias == asprintf);
187 char *str = NULL;
188 TEST_VERIFY (asprintf_alias (&str, "[[%P]]", 123L, 456.0) >= 0);
189 TEST_COMPARE_STRING (str, "[[(123, 456.000000)]]");
190 free (str);
192 str = NULL;
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)]]");
195 free (str);
197 str = NULL;
198 TEST_VERIFY (asprintf_alias (&str, "[[%.1P]]", 1L, 2.0) >= 0);
199 TEST_COMPARE_STRING (str, "[[{(1, 2.000000)}]]");
200 free (str);
202 str = NULL;
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)}]]");
205 free (str);
207 str = NULL;
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)
212 >= 0);
213 TEST_COMPARE_STRING (str,
214 "[["
215 "{(1, 2.000000),(3, 4.000000)}"
216 " | "
217 "{(5, 6.000000),(7, 8.000000),(9, 10.000000)}"
218 "]]");
219 free (str);
221 /* The following subtest fails due to bug 21534. */
222 #if 0
223 str = NULL;
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)
228 >= 0);
229 TEST_COMPARE_STRING (str,
230 "[["
231 "{(1, 2.000000),(3, 4.000000)}"
232 " | "
233 "{(5, 6.000000),(7, 8.000000),(9, 10.000000)}"
234 " | "
235 "{(1, 2.000000),(3, 4.000000)}"
236 "]]");
237 free (str);
238 #endif
240 /* Wide variants of the tests above. */
242 wchar_t buf[200];
243 TEST_VERIFY (swprintf (buf, array_length (buf), L"[[%P]]", 123L, 456.0)
244 >= 0);
245 TEST_COMPARE_STRING_WIDE (buf, L"[[(123, 456.000000)]]");
247 TEST_VERIFY (swprintf (buf, array_length (buf), L"[[%1$P %1$P]]",
248 123L, 457.0) >= 0);
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)
262 >= 0);
263 TEST_COMPARE_STRING_WIDE (buf,
264 L"[["
265 "{(1, 2.000000),(3, 4.000000)}"
266 " | "
267 "{(5, 6.000000),(7, 8.000000),(9, 10.000000)}"
268 "]]");
270 /* The following subtest fails due to bug 21534. */
271 #if 0
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)
276 >= 0);
277 TEST_COMPARE_STRING_WIDE (buf,
278 L"[["
279 "{(1, 2.000000),(3, 4.000000)}"
280 " | "
281 "{(5, 6.000000),(7, 8.000000),(9, 10.000000)}"
282 " | "
283 "{(1, 2.000000),(3, 4.000000)}"
284 "]]");
285 #endif
287 return 0;
290 #include <support/test-driver.c>