Work around lack of support of grouping flag.
[gnulib.git] / tests / test-vasnprintf-posix.c
1 /* Test of POSIX compatible vasnprintf() and asnprintf() functions.
2    Copyright (C) 2007 Free Software Foundation, Inc.
3
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2, or (at your option)
7    any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software Foundation,
16    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
17
18 /* Written by Bruno Haible <bruno@clisp.org>, 2007.  */
19
20 #ifdef HAVE_CONFIG_H
21 # include <config.h>
22 #endif
23
24 #include "vasnprintf.h"
25
26 #include <stdarg.h>
27 #include <stddef.h>
28 #include <stdio.h>
29 #include <stdint.h>
30 #include <stdlib.h>
31 #include <string.h>
32
33 #define ASSERT(expr) \
34   do                                                                         \
35     {                                                                        \
36       if (!(expr))                                                           \
37         {                                                                    \
38           fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \
39           abort ();                                                          \
40         }                                                                    \
41     }                                                                        \
42   while (0)
43
44 /* The Compaq (ex-DEC) C 6.4 compiler chokes on the expression 0.0 / 0.0.  */
45 #ifdef __DECC
46 static double
47 NaN ()
48 {
49   static double zero = 0.0;
50   return zero / zero;
51 }
52 #else
53 # define NaN() (0.0 / 0.0)
54 #endif
55
56 static void
57 test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...))
58 {
59   char buf[8];
60   int size;
61
62   /* Test return value convention.  */
63
64   for (size = 0; size <= 8; size++)
65     {
66       size_t length = size;
67       char *result = my_asnprintf (NULL, &length, "%d", 12345);
68       ASSERT (result != NULL);
69       ASSERT (strcmp (result, "12345") == 0);
70       ASSERT (length == 5);
71       free (result);
72     }
73
74   for (size = 0; size <= 8; size++)
75     {
76       size_t length;
77       char *result;
78
79       memcpy (buf, "DEADBEEF", 8);
80       length = size;
81       result = my_asnprintf (buf, &length, "%d", 12345);
82       ASSERT (result != NULL);
83       ASSERT (strcmp (result, "12345") == 0);
84       ASSERT (length == 5);
85       if (size < 6)
86         ASSERT (result != buf);
87       ASSERT (memcmp (buf + size, "DEADBEEF" + size, 8 - size) == 0);
88       if (result != buf)
89         free (result);
90     }
91
92   /* Test support of size specifiers as in C99.  */
93
94   {
95     size_t length;
96     char *result =
97       my_asnprintf (NULL, &length, "%ju %d", (uintmax_t) 12345671, 33, 44, 55);
98     ASSERT (result != NULL);
99     ASSERT (strcmp (result, "12345671 33") == 0);
100     ASSERT (length == strlen (result));
101     free (result);
102   }
103
104   {
105     size_t length;
106     char *result =
107       my_asnprintf (NULL, &length, "%zu %d", (size_t) 12345672, 33, 44, 55);
108     ASSERT (result != NULL);
109     ASSERT (strcmp (result, "12345672 33") == 0);
110     ASSERT (length == strlen (result));
111     free (result);
112   }
113
114   {
115     size_t length;
116     char *result =
117       my_asnprintf (NULL, &length, "%tu %d", (ptrdiff_t) 12345673, 33, 44, 55);
118     ASSERT (result != NULL);
119     ASSERT (strcmp (result, "12345673 33") == 0);
120     ASSERT (length == strlen (result));
121     free (result);
122   }
123
124   {
125     size_t length;
126     char *result =
127       my_asnprintf (NULL, &length, "%Lg %d", (long double) 1.5, 33, 44, 55);
128     ASSERT (result != NULL);
129     ASSERT (strcmp (result, "1.5 33") == 0);
130     ASSERT (length == strlen (result));
131     free (result);
132   }
133
134   /* Test the support of the 'a' and 'A' conversion specifier for hexadecimal
135      output of floating-point numbers.  */
136
137   { /* A positive number.  */
138     size_t length;
139     char *result =
140       my_asnprintf (NULL, &length, "%a %d", 3.1416015625, 33, 44, 55);
141     ASSERT (result != NULL);
142     ASSERT (strcmp (result, "0x1.922p+1 33") == 0
143             || strcmp (result, "0x3.244p+0 33") == 0
144             || strcmp (result, "0x6.488p-1 33") == 0
145             || strcmp (result, "0xc.91p-2 33") == 0);
146     ASSERT (length == strlen (result));
147     free (result);
148   }
149
150   { /* A negative number.  */
151     size_t length;
152     char *result =
153       my_asnprintf (NULL, &length, "%A %d", -3.1416015625, 33, 44, 55);
154     ASSERT (result != NULL);
155     ASSERT (strcmp (result, "-0X1.922P+1 33") == 0
156             || strcmp (result, "-0X3.244P+0 33") == 0
157             || strcmp (result, "-0X6.488P-1 33") == 0
158             || strcmp (result, "-0XC.91P-2 33") == 0);
159     ASSERT (length == strlen (result));
160     free (result);
161   }
162
163   { /* Positive zero.  */
164     size_t length;
165     char *result =
166       my_asnprintf (NULL, &length, "%a %d", 0.0, 33, 44, 55);
167     ASSERT (result != NULL);
168     ASSERT (strcmp (result, "0x0p+0 33") == 0);
169     ASSERT (length == strlen (result));
170     free (result);
171   }
172
173   { /* Negative zero.  */
174     size_t length;
175     char *result =
176       my_asnprintf (NULL, &length, "%a %d", -0.0, 33, 44, 55);
177     ASSERT (result != NULL);
178     ASSERT (strcmp (result, "-0x0p+0 33") == 0);
179     ASSERT (length == strlen (result));
180     free (result);
181   }
182
183   { /* Positive infinity.  */
184     size_t length;
185     char *result =
186       my_asnprintf (NULL, &length, "%a %d", 1.0 / 0.0, 33, 44, 55);
187     ASSERT (result != NULL);
188     ASSERT (strcmp (result, "inf 33") == 0);
189     ASSERT (length == strlen (result));
190     free (result);
191   }
192
193   { /* Negative infinity.  */
194     size_t length;
195     char *result =
196       my_asnprintf (NULL, &length, "%a %d", -1.0 / 0.0, 33, 44, 55);
197     ASSERT (result != NULL);
198     ASSERT (strcmp (result, "-inf 33") == 0);
199     ASSERT (length == strlen (result));
200     free (result);
201   }
202
203   { /* NaN.  */
204     size_t length;
205     char *result =
206       my_asnprintf (NULL, &length, "%a %d", NaN (), 33, 44, 55);
207     ASSERT (result != NULL);
208     ASSERT (strcmp (result, "nan 33") == 0);
209     ASSERT (length == strlen (result));
210     free (result);
211   }
212
213   { /* Rounding near the decimal point.  */
214     size_t length;
215     char *result =
216       my_asnprintf (NULL, &length, "%.0a %d", 1.5, 33, 44, 55);
217     ASSERT (result != NULL);
218     ASSERT (strcmp (result, "0x2p+0 33") == 0
219             || strcmp (result, "0x3p-1 33") == 0
220             || strcmp (result, "0x6p-2 33") == 0
221             || strcmp (result, "0xcp-3 33") == 0);
222     ASSERT (length == strlen (result));
223     free (result);
224   }
225
226   { /* Rounding with precision 0.  */
227     size_t length;
228     char *result =
229       my_asnprintf (NULL, &length, "%.0a %d", 1.51, 33, 44, 55);
230     ASSERT (result != NULL);
231     ASSERT (strcmp (result, "0x2p+0 33") == 0
232             || strcmp (result, "0x3p-1 33") == 0
233             || strcmp (result, "0x6p-2 33") == 0
234             || strcmp (result, "0xcp-3 33") == 0);
235     ASSERT (length == strlen (result));
236     free (result);
237   }
238
239   { /* Rounding with precision 1.  */
240     size_t length;
241     char *result =
242       my_asnprintf (NULL, &length, "%.1a %d", 1.51, 33, 44, 55);
243     ASSERT (result != NULL);
244     ASSERT (strcmp (result, "0x1.8p+0 33") == 0
245             || strcmp (result, "0x3.0p-1 33") == 0
246             || strcmp (result, "0x6.1p-2 33") == 0
247             || strcmp (result, "0xc.1p-3 33") == 0);
248     ASSERT (length == strlen (result));
249     free (result);
250   }
251
252   { /* Rounding with precision 2.  */
253     size_t length;
254     char *result =
255       my_asnprintf (NULL, &length, "%.2a %d", 1.51, 33, 44, 55);
256     ASSERT (result != NULL);
257     ASSERT (strcmp (result, "0x1.83p+0 33") == 0
258             || strcmp (result, "0x3.05p-1 33") == 0
259             || strcmp (result, "0x6.0ap-2 33") == 0
260             || strcmp (result, "0xc.14p-3 33") == 0);
261     ASSERT (length == strlen (result));
262     free (result);
263   }
264
265   { /* Rounding with precision 3.  */
266     size_t length;
267     char *result =
268       my_asnprintf (NULL, &length, "%.3a %d", 1.51, 33, 44, 55);
269     ASSERT (result != NULL);
270     ASSERT (strcmp (result, "0x1.829p+0 33") == 0
271             || strcmp (result, "0x3.052p-1 33") == 0
272             || strcmp (result, "0x6.0a4p-2 33") == 0
273             || strcmp (result, "0xc.148p-3 33") == 0);
274     ASSERT (length == strlen (result));
275     free (result);
276   }
277
278   { /* Rounding can turn a ...FFF into a ...000.  */
279     size_t length;
280     char *result =
281       my_asnprintf (NULL, &length, "%.3a %d", 1.49999, 33, 44, 55);
282     ASSERT (result != NULL);
283     ASSERT (strcmp (result, "0x1.800p+0 33") == 0
284             || strcmp (result, "0x3.000p-1 33") == 0
285             || strcmp (result, "0x6.000p-2 33") == 0
286             || strcmp (result, "0xc.000p-3 33") == 0);
287     ASSERT (length == strlen (result));
288     free (result);
289   }
290
291   { /* Rounding can turn a ...FFF into a ...000.
292        This shows a MacOS X 10.3.9 (Darwin 7.9) bug.  */
293     size_t length;
294     char *result =
295       my_asnprintf (NULL, &length, "%.1a %d", 1.999, 33, 44, 55);
296     ASSERT (result != NULL);
297     ASSERT (strcmp (result, "0x1.0p+1 33") == 0
298             || strcmp (result, "0x2.0p+0 33") == 0
299             || strcmp (result, "0x4.0p-1 33") == 0
300             || strcmp (result, "0x8.0p-2 33") == 0);
301     ASSERT (length == strlen (result));
302     free (result);
303   }
304
305   { /* Width.  */
306     size_t length;
307     char *result =
308       my_asnprintf (NULL, &length, "%10a %d", 1.75, 33, 44, 55);
309     ASSERT (result != NULL);
310     ASSERT (strcmp (result, "  0x1.cp+0 33") == 0
311             || strcmp (result, "  0x3.8p-1 33") == 0
312             || strcmp (result, "    0x7p-2 33") == 0
313             || strcmp (result, "    0xep-3 33") == 0);
314     ASSERT (length == strlen (result));
315     free (result);
316   }
317
318   { /* Small precision.  */
319     size_t length;
320     char *result =
321       my_asnprintf (NULL, &length, "%.10a %d", 1.75, 33, 44, 55);
322     ASSERT (result != NULL);
323     ASSERT (strcmp (result, "0x1.c000000000p+0 33") == 0
324             || strcmp (result, "0x3.8000000000p-1 33") == 0
325             || strcmp (result, "0x7.0000000000p-2 33") == 0
326             || strcmp (result, "0xe.0000000000p-3 33") == 0);
327     ASSERT (length == strlen (result));
328     free (result);
329   }
330
331   { /* Large precision.  */
332     size_t length;
333     char *result =
334       my_asnprintf (NULL, &length, "%.50a %d", 1.75, 33, 44, 55);
335     ASSERT (result != NULL);
336     ASSERT (strcmp (result, "0x1.c0000000000000000000000000000000000000000000000000p+0 33") == 0
337             || strcmp (result, "0x3.80000000000000000000000000000000000000000000000000p-1 33") == 0
338             || strcmp (result, "0x7.00000000000000000000000000000000000000000000000000p-2 33") == 0
339             || strcmp (result, "0xe.00000000000000000000000000000000000000000000000000p-3 33") == 0);
340     ASSERT (length == strlen (result));
341     free (result);
342   }
343
344   { /* FLAG_LEFT.  */
345     size_t length;
346     char *result =
347       my_asnprintf (NULL, &length, "%-10a %d", 1.75, 33, 44, 55);
348     ASSERT (result != NULL);
349     ASSERT (strcmp (result, "0x1.cp+0   33") == 0
350             || strcmp (result, "0x3.8p-1   33") == 0
351             || strcmp (result, "0x7p-2     33") == 0
352             || strcmp (result, "0xep-3     33") == 0);
353     ASSERT (length == strlen (result));
354     free (result);
355   }
356
357   { /* FLAG_SHOWSIGN.  */
358     size_t length;
359     char *result =
360       my_asnprintf (NULL, &length, "%+a %d", 1.75, 33, 44, 55);
361     ASSERT (result != NULL);
362     ASSERT (strcmp (result, "+0x1.cp+0 33") == 0
363             || strcmp (result, "+0x3.8p-1 33") == 0
364             || strcmp (result, "+0x7p-2 33") == 0
365             || strcmp (result, "+0xep-3 33") == 0);
366     ASSERT (length == strlen (result));
367     free (result);
368   }
369
370   { /* FLAG_SPACE.  */
371     size_t length;
372     char *result =
373       my_asnprintf (NULL, &length, "% a %d", 1.75, 33, 44, 55);
374     ASSERT (result != NULL);
375     ASSERT (strcmp (result, " 0x1.cp+0 33") == 0
376             || strcmp (result, " 0x3.8p-1 33") == 0
377             || strcmp (result, " 0x7p-2 33") == 0
378             || strcmp (result, " 0xep-3 33") == 0);
379     ASSERT (length == strlen (result));
380     free (result);
381   }
382
383   { /* FLAG_ALT.  */
384     size_t length;
385     char *result =
386       my_asnprintf (NULL, &length, "%#a %d", 1.75, 33, 44, 55);
387     ASSERT (result != NULL);
388     ASSERT (strcmp (result, "0x1.cp+0 33") == 0
389             || strcmp (result, "0x3.8p-1 33") == 0
390             || strcmp (result, "0x7.p-2 33") == 0
391             || strcmp (result, "0xe.p-3 33") == 0);
392     ASSERT (length == strlen (result));
393     free (result);
394   }
395
396   { /* FLAG_ALT.  */
397     size_t length;
398     char *result =
399       my_asnprintf (NULL, &length, "%#a %d", 1.0, 33, 44, 55);
400     ASSERT (result != NULL);
401     ASSERT (strcmp (result, "0x1.p+0 33") == 0
402             || strcmp (result, "0x2.p-1 33") == 0
403             || strcmp (result, "0x4.p-2 33") == 0
404             || strcmp (result, "0x8.p-3 33") == 0);
405     ASSERT (length == strlen (result));
406     free (result);
407   }
408
409   { /* FLAG_ZERO with finite number.  */
410     size_t length;
411     char *result =
412       my_asnprintf (NULL, &length, "%010a %d", 1.75, 33, 44, 55);
413     ASSERT (result != NULL);
414     ASSERT (strcmp (result, "0x001.cp+0 33") == 0
415             || strcmp (result, "0x003.8p-1 33") == 0
416             || strcmp (result, "0x00007p-2 33") == 0
417             || strcmp (result, "0x0000ep-3 33") == 0);
418     ASSERT (length == strlen (result));
419     free (result);
420   }
421
422   { /* FLAG_ZERO with infinite number.  */
423     size_t length;
424     char *result =
425       my_asnprintf (NULL, &length, "%010a %d", 1.0 / 0.0, 33, 44, 55);
426     ASSERT (result != NULL);
427     /* "0000000inf 33" is not a valid result; see
428        <http://lists.gnu.org/archive/html/bug-gnulib/2007-04/msg00107.html> */
429     ASSERT (strcmp (result, "       inf 33") == 0);
430     ASSERT (length == strlen (result));
431     free (result);
432   }
433
434   { /* FLAG_ZERO with NaN.  */
435     size_t length;
436     char *result =
437       my_asnprintf (NULL, &length, "%010a %d", NaN (), 33, 44, 55);
438     ASSERT (result != NULL);
439     /* "0000000nan 33" is not a valid result; see
440        <http://lists.gnu.org/archive/html/bug-gnulib/2007-04/msg00107.html> */
441     ASSERT (strcmp (result, "       nan 33") == 0);
442     ASSERT (length == strlen (result));
443     free (result);
444   }
445
446   { /* A positive number.  */
447     size_t length;
448     char *result =
449       my_asnprintf (NULL, &length, "%La %d", 3.1416015625L, 33, 44, 55);
450     ASSERT (result != NULL);
451     ASSERT (strcmp (result, "0x1.922p+1 33") == 0
452             || strcmp (result, "0x3.244p+0 33") == 0
453             || strcmp (result, "0x6.488p-1 33") == 0
454             || strcmp (result, "0xc.91p-2 33") == 0);
455     ASSERT (length == strlen (result));
456     free (result);
457   }
458
459   { /* A negative number.  */
460     size_t length;
461     char *result =
462       my_asnprintf (NULL, &length, "%LA %d", -3.1416015625L, 33, 44, 55);
463     ASSERT (result != NULL);
464     ASSERT (strcmp (result, "-0X1.922P+1 33") == 0
465             || strcmp (result, "-0X3.244P+0 33") == 0
466             || strcmp (result, "-0X6.488P-1 33") == 0
467             || strcmp (result, "-0XC.91P-2 33") == 0);
468     ASSERT (length == strlen (result));
469     free (result);
470   }
471
472   { /* Positive zero.  */
473     size_t length;
474     char *result =
475       my_asnprintf (NULL, &length, "%La %d", 0.0L, 33, 44, 55);
476     ASSERT (result != NULL);
477     ASSERT (strcmp (result, "0x0p+0 33") == 0);
478     ASSERT (length == strlen (result));
479     free (result);
480   }
481
482   { /* Negative zero.  */
483     size_t length;
484     char *result =
485       my_asnprintf (NULL, &length, "%La %d", -0.0L, 33, 44, 55);
486     ASSERT (result != NULL);
487     ASSERT (strcmp (result, "-0x0p+0 33") == 0);
488     ASSERT (length == strlen (result));
489     free (result);
490   }
491
492   { /* Positive infinity.  */
493     size_t length;
494     char *result =
495       my_asnprintf (NULL, &length, "%La %d", 1.0L / 0.0L, 33, 44, 55);
496     ASSERT (result != NULL);
497     ASSERT (strcmp (result, "inf 33") == 0);
498     ASSERT (length == strlen (result));
499     free (result);
500   }
501
502   { /* Negative infinity.  */
503     size_t length;
504     char *result =
505       my_asnprintf (NULL, &length, "%La %d", -1.0L / 0.0L, 33, 44, 55);
506     ASSERT (result != NULL);
507     ASSERT (strcmp (result, "-inf 33") == 0);
508     ASSERT (length == strlen (result));
509     free (result);
510   }
511
512   { /* NaN.  */
513     size_t length;
514     char *result =
515       my_asnprintf (NULL, &length, "%La %d", 0.0L / 0.0L, 33, 44, 55);
516     ASSERT (result != NULL);
517     ASSERT (strcmp (result, "nan 33") == 0);
518     ASSERT (length == strlen (result));
519     free (result);
520   }
521
522   { /* Rounding near the decimal point.  */
523     size_t length;
524     char *result =
525       my_asnprintf (NULL, &length, "%.0La %d", 1.5L, 33, 44, 55);
526     ASSERT (result != NULL);
527     ASSERT (strcmp (result, "0x2p+0 33") == 0
528             || strcmp (result, "0x3p-1 33") == 0
529             || strcmp (result, "0x6p-2 33") == 0
530             || strcmp (result, "0xcp-3 33") == 0);
531     ASSERT (length == strlen (result));
532     free (result);
533   }
534
535   { /* Rounding with precision 0.  */
536     size_t length;
537     char *result =
538       my_asnprintf (NULL, &length, "%.0La %d", 1.51L, 33, 44, 55);
539     ASSERT (result != NULL);
540     ASSERT (strcmp (result, "0x2p+0 33") == 0
541             || strcmp (result, "0x3p-1 33") == 0
542             || strcmp (result, "0x6p-2 33") == 0
543             || strcmp (result, "0xcp-3 33") == 0);
544     ASSERT (length == strlen (result));
545     free (result);
546   }
547
548   { /* Rounding with precision 1.  */
549     size_t length;
550     char *result =
551       my_asnprintf (NULL, &length, "%.1La %d", 1.51L, 33, 44, 55);
552     ASSERT (result != NULL);
553     ASSERT (strcmp (result, "0x1.8p+0 33") == 0
554             || strcmp (result, "0x3.0p-1 33") == 0
555             || strcmp (result, "0x6.1p-2 33") == 0
556             || strcmp (result, "0xc.1p-3 33") == 0);
557     ASSERT (length == strlen (result));
558     free (result);
559   }
560
561   { /* Rounding with precision 2.  */
562     size_t length;
563     char *result =
564       my_asnprintf (NULL, &length, "%.2La %d", 1.51L, 33, 44, 55);
565     ASSERT (result != NULL);
566     ASSERT (strcmp (result, "0x1.83p+0 33") == 0
567             || strcmp (result, "0x3.05p-1 33") == 0
568             || strcmp (result, "0x6.0ap-2 33") == 0
569             || strcmp (result, "0xc.14p-3 33") == 0);
570     ASSERT (length == strlen (result));
571     free (result);
572   }
573
574   { /* Rounding with precision 3.  */
575     size_t length;
576     char *result =
577       my_asnprintf (NULL, &length, "%.3La %d", 1.51L, 33, 44, 55);
578     ASSERT (result != NULL);
579     ASSERT (strcmp (result, "0x1.829p+0 33") == 0
580             || strcmp (result, "0x3.052p-1 33") == 0
581             || strcmp (result, "0x6.0a4p-2 33") == 0
582             || strcmp (result, "0xc.148p-3 33") == 0);
583     ASSERT (length == strlen (result));
584     free (result);
585   }
586
587   { /* Rounding can turn a ...FFF into a ...000.  */
588     size_t length;
589     char *result =
590       my_asnprintf (NULL, &length, "%.3La %d", 1.49999L, 33, 44, 55);
591     ASSERT (result != NULL);
592     ASSERT (strcmp (result, "0x1.800p+0 33") == 0
593             || strcmp (result, "0x3.000p-1 33") == 0
594             || strcmp (result, "0x6.000p-2 33") == 0
595             || strcmp (result, "0xc.000p-3 33") == 0);
596     ASSERT (length == strlen (result));
597     free (result);
598   }
599
600   { /* Rounding can turn a ...FFF into a ...000.
601        This shows a MacOS X 10.3.9 (Darwin 7.9) bug and a
602        glibc 2.4 bug <http://sourceware.org/bugzilla/show_bug.cgi?id=2908>.  */
603     size_t length;
604     char *result =
605       my_asnprintf (NULL, &length, "%.1La %d", 1.999L, 33, 44, 55);
606     ASSERT (result != NULL);
607     ASSERT (strcmp (result, "0x1.0p+1 33") == 0
608             || strcmp (result, "0x2.0p+0 33") == 0
609             || strcmp (result, "0x4.0p-1 33") == 0
610             || strcmp (result, "0x8.0p-2 33") == 0);
611     ASSERT (length == strlen (result));
612     free (result);
613   }
614
615   { /* Width.  */
616     size_t length;
617     char *result =
618       my_asnprintf (NULL, &length, "%10La %d", 1.75L, 33, 44, 55);
619     ASSERT (result != NULL);
620     ASSERT (strcmp (result, "  0x1.cp+0 33") == 0
621             || strcmp (result, "  0x3.8p-1 33") == 0
622             || strcmp (result, "    0x7p-2 33") == 0
623             || strcmp (result, "    0xep-3 33") == 0);
624     ASSERT (length == strlen (result));
625     free (result);
626   }
627
628   { /* Small precision.  */
629     size_t length;
630     char *result =
631       my_asnprintf (NULL, &length, "%.10La %d", 1.75L, 33, 44, 55);
632     ASSERT (result != NULL);
633     ASSERT (strcmp (result, "0x1.c000000000p+0 33") == 0
634             || strcmp (result, "0x3.8000000000p-1 33") == 0
635             || strcmp (result, "0x7.0000000000p-2 33") == 0
636             || strcmp (result, "0xe.0000000000p-3 33") == 0);
637     ASSERT (length == strlen (result));
638     free (result);
639   }
640
641   { /* Large precision.  */
642     size_t length;
643     char *result =
644       my_asnprintf (NULL, &length, "%.50La %d", 1.75L, 33, 44, 55);
645     ASSERT (result != NULL);
646     ASSERT (strcmp (result, "0x1.c0000000000000000000000000000000000000000000000000p+0 33") == 0
647             || strcmp (result, "0x3.80000000000000000000000000000000000000000000000000p-1 33") == 0
648             || strcmp (result, "0x7.00000000000000000000000000000000000000000000000000p-2 33") == 0
649             || strcmp (result, "0xe.00000000000000000000000000000000000000000000000000p-3 33") == 0);
650     ASSERT (length == strlen (result));
651     free (result);
652   }
653
654   { /* FLAG_LEFT.  */
655     size_t length;
656     char *result =
657       my_asnprintf (NULL, &length, "%-10La %d", 1.75L, 33, 44, 55);
658     ASSERT (result != NULL);
659     ASSERT (strcmp (result, "0x1.cp+0   33") == 0
660             || strcmp (result, "0x3.8p-1   33") == 0
661             || strcmp (result, "0x7p-2     33") == 0
662             || strcmp (result, "0xep-3     33") == 0);
663     ASSERT (length == strlen (result));
664     free (result);
665   }
666
667   { /* FLAG_SHOWSIGN.  */
668     size_t length;
669     char *result =
670       my_asnprintf (NULL, &length, "%+La %d", 1.75L, 33, 44, 55);
671     ASSERT (result != NULL);
672     ASSERT (strcmp (result, "+0x1.cp+0 33") == 0
673             || strcmp (result, "+0x3.8p-1 33") == 0
674             || strcmp (result, "+0x7p-2 33") == 0
675             || strcmp (result, "+0xep-3 33") == 0);
676     ASSERT (length == strlen (result));
677     free (result);
678   }
679
680   { /* FLAG_SPACE.  */
681     size_t length;
682     char *result =
683       my_asnprintf (NULL, &length, "% La %d", 1.75L, 33, 44, 55);
684     ASSERT (result != NULL);
685     ASSERT (strcmp (result, " 0x1.cp+0 33") == 0
686             || strcmp (result, " 0x3.8p-1 33") == 0
687             || strcmp (result, " 0x7p-2 33") == 0
688             || strcmp (result, " 0xep-3 33") == 0);
689     ASSERT (length == strlen (result));
690     free (result);
691   }
692
693   { /* FLAG_ALT.  */
694     size_t length;
695     char *result =
696       my_asnprintf (NULL, &length, "%#La %d", 1.75L, 33, 44, 55);
697     ASSERT (result != NULL);
698     ASSERT (strcmp (result, "0x1.cp+0 33") == 0
699             || strcmp (result, "0x3.8p-1 33") == 0
700             || strcmp (result, "0x7.p-2 33") == 0
701             || strcmp (result, "0xe.p-3 33") == 0);
702     ASSERT (length == strlen (result));
703     free (result);
704   }
705
706   { /* FLAG_ALT.  */
707     size_t length;
708     char *result =
709       my_asnprintf (NULL, &length, "%#La %d", 1.0L, 33, 44, 55);
710     ASSERT (result != NULL);
711     ASSERT (strcmp (result, "0x1.p+0 33") == 0
712             || strcmp (result, "0x2.p-1 33") == 0
713             || strcmp (result, "0x4.p-2 33") == 0
714             || strcmp (result, "0x8.p-3 33") == 0);
715     ASSERT (length == strlen (result));
716     free (result);
717   }
718
719   { /* FLAG_ZERO with finite number.  */
720     size_t length;
721     char *result =
722       my_asnprintf (NULL, &length, "%010La %d", 1.75L, 33, 44, 55);
723     ASSERT (result != NULL);
724     ASSERT (strcmp (result, "0x001.cp+0 33") == 0
725             || strcmp (result, "0x003.8p-1 33") == 0
726             || strcmp (result, "0x00007p-2 33") == 0
727             || strcmp (result, "0x0000ep-3 33") == 0);
728     ASSERT (length == strlen (result));
729     free (result);
730   }
731
732   { /* FLAG_ZERO with infinite number.  */
733     size_t length;
734     char *result =
735       my_asnprintf (NULL, &length, "%010La %d", 1.0L / 0.0L, 33, 44, 55);
736     ASSERT (result != NULL);
737     /* "0000000inf 33" is not a valid result; see
738        <http://lists.gnu.org/archive/html/bug-gnulib/2007-04/msg00107.html> */
739     ASSERT (strcmp (result, "       inf 33") == 0);
740     ASSERT (length == strlen (result));
741     free (result);
742   }
743
744   { /* FLAG_ZERO with NaN.  */
745     size_t length;
746     char *result =
747       my_asnprintf (NULL, &length, "%010La %d", 0.0L / 0.0L, 33, 44, 55);
748     ASSERT (result != NULL);
749     /* "0000000nan 33" is not a valid result; see
750        <http://lists.gnu.org/archive/html/bug-gnulib/2007-04/msg00107.html> */
751     ASSERT (strcmp (result, "       nan 33") == 0);
752     ASSERT (length == strlen (result));
753     free (result);
754   }
755
756   /* Test the support of the %f format directive.  */
757
758   { /* A positive number.  */
759     size_t length;
760     char *result =
761       my_asnprintf (NULL, &length, "%f %d", 12.75, 33, 44, 55);
762     ASSERT (result != NULL);
763     ASSERT (strcmp (result, "12.750000 33") == 0);
764     ASSERT (length == strlen (result));
765     free (result);
766   }
767
768   { /* A larger positive number.  */
769     size_t length;
770     char *result =
771       my_asnprintf (NULL, &length, "%f %d", 1234567.0, 33, 44, 55);
772     ASSERT (result != NULL);
773     ASSERT (strcmp (result, "1234567.000000 33") == 0);
774     ASSERT (length == strlen (result));
775     free (result);
776   }
777
778   { /* A negative number.  */
779     size_t length;
780     char *result =
781       my_asnprintf (NULL, &length, "%f %d", -0.03125, 33, 44, 55);
782     ASSERT (result != NULL);
783     ASSERT (strcmp (result, "-0.031250 33") == 0);
784     ASSERT (length == strlen (result));
785     free (result);
786   }
787
788   { /* Positive zero.  */
789     size_t length;
790     char *result =
791       my_asnprintf (NULL, &length, "%f %d", 0.0, 33, 44, 55);
792     ASSERT (result != NULL);
793     ASSERT (strcmp (result, "0.000000 33") == 0);
794     ASSERT (length == strlen (result));
795     free (result);
796   }
797
798   { /* Negative zero.  */
799     size_t length;
800     char *result =
801       my_asnprintf (NULL, &length, "%f %d", -0.0, 33, 44, 55);
802     ASSERT (result != NULL);
803     ASSERT (strcmp (result, "-0.000000 33") == 0);
804     ASSERT (length == strlen (result));
805     free (result);
806   }
807
808   { /* Positive infinity.  */
809     size_t length;
810     char *result =
811       my_asnprintf (NULL, &length, "%f %d", 1.0 / 0.0, 33, 44, 55);
812     ASSERT (result != NULL);
813     ASSERT (strcmp (result, "inf 33") == 0
814             || strcmp (result, "infinity 33") == 0);
815     ASSERT (length == strlen (result));
816     free (result);
817   }
818
819   { /* Negative infinity.  */
820     size_t length;
821     char *result =
822       my_asnprintf (NULL, &length, "%f %d", -1.0 / 0.0, 33, 44, 55);
823     ASSERT (result != NULL);
824     ASSERT (strcmp (result, "-inf 33") == 0
825             || strcmp (result, "-infinity 33") == 0);
826     ASSERT (length == strlen (result));
827     free (result);
828   }
829
830   { /* NaN.  */
831     size_t length;
832     char *result =
833       my_asnprintf (NULL, &length, "%f %d", NaN (), 33, 44, 55);
834     ASSERT (result != NULL);
835     ASSERT (strcmp (result, "nan 33") == 0);
836     ASSERT (length == strlen (result));
837     free (result);
838   }
839
840   { /* FLAG_ZERO.  */
841     size_t length;
842     char *result =
843       my_asnprintf (NULL, &length, "%015f %d", 1234.0, 33, 44, 55);
844     ASSERT (result != NULL);
845     ASSERT (strcmp (result, "00001234.000000 33") == 0);
846     ASSERT (length == strlen (result));
847     free (result);
848   }
849
850   { /* FLAG_ZERO with infinite number.  */
851     size_t length;
852     char *result =
853       my_asnprintf (NULL, &length, "%015f %d", -1.0 / 0.0, 33, 44, 55);
854     ASSERT (result != NULL);
855     ASSERT (strcmp (result, "           -inf 33") == 0
856             || strcmp (result, "      -infinity 33") == 0);
857     ASSERT (length == strlen (result));
858     free (result);
859   }
860
861   { /* Precision.  */
862     size_t length;
863     char *result =
864       my_asnprintf (NULL, &length, "%.f %d", 1234.0, 33, 44, 55);
865     ASSERT (result != NULL);
866     ASSERT (strcmp (result, "1234 33") == 0);
867     ASSERT (length == strlen (result));
868     free (result);
869   }
870
871   { /* A positive number.  */
872     size_t length;
873     char *result =
874       my_asnprintf (NULL, &length, "%Lf %d", 12.75L, 33, 44, 55);
875     ASSERT (result != NULL);
876     ASSERT (strcmp (result, "12.750000 33") == 0);
877     ASSERT (length == strlen (result));
878     free (result);
879   }
880
881   { /* A larger positive number.  */
882     size_t length;
883     char *result =
884       my_asnprintf (NULL, &length, "%Lf %d", 1234567.0L, 33, 44, 55);
885     ASSERT (result != NULL);
886     ASSERT (strcmp (result, "1234567.000000 33") == 0);
887     ASSERT (length == strlen (result));
888     free (result);
889   }
890
891   { /* A negative number.  */
892     size_t length;
893     char *result =
894       my_asnprintf (NULL, &length, "%Lf %d", -0.03125L, 33, 44, 55);
895     ASSERT (result != NULL);
896     ASSERT (strcmp (result, "-0.031250 33") == 0);
897     ASSERT (length == strlen (result));
898     free (result);
899   }
900
901   { /* Positive zero.  */
902     size_t length;
903     char *result =
904       my_asnprintf (NULL, &length, "%Lf %d", 0.0L, 33, 44, 55);
905     ASSERT (result != NULL);
906     ASSERT (strcmp (result, "0.000000 33") == 0);
907     ASSERT (length == strlen (result));
908     free (result);
909   }
910
911   { /* Negative zero.  */
912     size_t length;
913     char *result =
914       my_asnprintf (NULL, &length, "%Lf %d", -0.0L, 33, 44, 55);
915     ASSERT (result != NULL);
916     ASSERT (strcmp (result, "-0.000000 33") == 0);
917     ASSERT (length == strlen (result));
918     free (result);
919   }
920
921   { /* Positive infinity.  */
922     size_t length;
923     char *result =
924       my_asnprintf (NULL, &length, "%Lf %d", 1.0L / 0.0L, 33, 44, 55);
925     ASSERT (result != NULL);
926     ASSERT (strcmp (result, "inf 33") == 0
927             || strcmp (result, "infinity 33") == 0);
928     ASSERT (length == strlen (result));
929     free (result);
930   }
931
932   { /* Negative infinity.  */
933     size_t length;
934     char *result =
935       my_asnprintf (NULL, &length, "%Lf %d", -1.0L / 0.0L, 33, 44, 55);
936     ASSERT (result != NULL);
937     ASSERT (strcmp (result, "-inf 33") == 0
938             || strcmp (result, "-infinity 33") == 0);
939     ASSERT (length == strlen (result));
940     free (result);
941   }
942
943   { /* NaN.  */
944     static long double zero = 0.0L;
945     size_t length;
946     char *result =
947       my_asnprintf (NULL, &length, "%Lf %d", zero / zero, 33, 44, 55);
948     ASSERT (result != NULL);
949     ASSERT (strcmp (result, "nan 33") == 0);
950     ASSERT (length == strlen (result));
951     free (result);
952   }
953
954   { /* FLAG_ZERO.  */
955     size_t length;
956     char *result =
957       my_asnprintf (NULL, &length, "%015Lf %d", 1234.0L, 33, 44, 55);
958     ASSERT (result != NULL);
959     ASSERT (strcmp (result, "00001234.000000 33") == 0);
960     ASSERT (length == strlen (result));
961     free (result);
962   }
963
964   { /* FLAG_ZERO with infinite number.  */
965     size_t length;
966     char *result =
967       my_asnprintf (NULL, &length, "%015Lf %d", -1.0L / 0.0L, 33, 44, 55);
968     ASSERT (result != NULL);
969     ASSERT (strcmp (result, "           -inf 33") == 0
970             || strcmp (result, "      -infinity 33") == 0);
971     ASSERT (length == strlen (result));
972     free (result);
973   }
974
975   { /* Precision.  */
976     size_t length;
977     char *result =
978       my_asnprintf (NULL, &length, "%.Lf %d", 1234.0L, 33, 44, 55);
979     ASSERT (result != NULL);
980     ASSERT (strcmp (result, "1234 33") == 0);
981     ASSERT (length == strlen (result));
982     free (result);
983   }
984
985   /* Test the support of the %F format directive.  */
986
987   { /* A positive number.  */
988     size_t length;
989     char *result =
990       my_asnprintf (NULL, &length, "%F %d", 12.75, 33, 44, 55);
991     ASSERT (result != NULL);
992     ASSERT (strcmp (result, "12.750000 33") == 0);
993     ASSERT (length == strlen (result));
994     free (result);
995   }
996
997   { /* A larger positive number.  */
998     size_t length;
999     char *result =
1000       my_asnprintf (NULL, &length, "%F %d", 1234567.0, 33, 44, 55);
1001     ASSERT (result != NULL);
1002     ASSERT (strcmp (result, "1234567.000000 33") == 0);
1003     ASSERT (length == strlen (result));
1004     free (result);
1005   }
1006
1007   { /* A negative number.  */
1008     size_t length;
1009     char *result =
1010       my_asnprintf (NULL, &length, "%F %d", -0.03125, 33, 44, 55);
1011     ASSERT (result != NULL);
1012     ASSERT (strcmp (result, "-0.031250 33") == 0);
1013     ASSERT (length == strlen (result));
1014     free (result);
1015   }
1016
1017   { /* Positive zero.  */
1018     size_t length;
1019     char *result =
1020       my_asnprintf (NULL, &length, "%F %d", 0.0, 33, 44, 55);
1021     ASSERT (result != NULL);
1022     ASSERT (strcmp (result, "0.000000 33") == 0);
1023     ASSERT (length == strlen (result));
1024     free (result);
1025   }
1026
1027   { /* Negative zero.  */
1028     size_t length;
1029     char *result =
1030       my_asnprintf (NULL, &length, "%F %d", -0.0, 33, 44, 55);
1031     ASSERT (result != NULL);
1032     ASSERT (strcmp (result, "-0.000000 33") == 0);
1033     ASSERT (length == strlen (result));
1034     free (result);
1035   }
1036
1037   { /* Positive infinity.  */
1038     size_t length;
1039     char *result =
1040       my_asnprintf (NULL, &length, "%F %d", 1.0 / 0.0, 33, 44, 55);
1041     ASSERT (result != NULL);
1042     ASSERT (strcmp (result, "INF 33") == 0
1043             || strcmp (result, "INFINITY 33") == 0);
1044     ASSERT (length == strlen (result));
1045     free (result);
1046   }
1047
1048   { /* Negative infinity.  */
1049     size_t length;
1050     char *result =
1051       my_asnprintf (NULL, &length, "%F %d", -1.0 / 0.0, 33, 44, 55);
1052     ASSERT (result != NULL);
1053     ASSERT (strcmp (result, "-INF 33") == 0
1054             || strcmp (result, "-INFINITY 33") == 0);
1055     ASSERT (length == strlen (result));
1056     free (result);
1057   }
1058
1059   { /* NaN.  */
1060     size_t length;
1061     char *result =
1062       my_asnprintf (NULL, &length, "%F %d", NaN (), 33, 44, 55);
1063     ASSERT (result != NULL);
1064     ASSERT (strcmp (result, "NAN 33") == 0);
1065     ASSERT (length == strlen (result));
1066     free (result);
1067   }
1068
1069   { /* FLAG_ZERO.  */
1070     size_t length;
1071     char *result =
1072       my_asnprintf (NULL, &length, "%015F %d", 1234.0, 33, 44, 55);
1073     ASSERT (result != NULL);
1074     ASSERT (strcmp (result, "00001234.000000 33") == 0);
1075     ASSERT (length == strlen (result));
1076     free (result);
1077   }
1078
1079   { /* FLAG_ZERO with infinite number.  */
1080     size_t length;
1081     char *result =
1082       my_asnprintf (NULL, &length, "%015F %d", -1.0 / 0.0, 33, 44, 55);
1083     ASSERT (result != NULL);
1084     ASSERT (strcmp (result, "           -INF 33") == 0
1085             || strcmp (result, "      -INFINITY 33") == 0);
1086     ASSERT (length == strlen (result));
1087     free (result);
1088   }
1089
1090   { /* Precision.  */
1091     size_t length;
1092     char *result =
1093       my_asnprintf (NULL, &length, "%.F %d", 1234.0, 33, 44, 55);
1094     ASSERT (result != NULL);
1095     ASSERT (strcmp (result, "1234 33") == 0);
1096     ASSERT (length == strlen (result));
1097     free (result);
1098   }
1099
1100   { /* A positive number.  */
1101     size_t length;
1102     char *result =
1103       my_asnprintf (NULL, &length, "%LF %d", 12.75L, 33, 44, 55);
1104     ASSERT (result != NULL);
1105     ASSERT (strcmp (result, "12.750000 33") == 0);
1106     ASSERT (length == strlen (result));
1107     free (result);
1108   }
1109
1110   { /* A larger positive number.  */
1111     size_t length;
1112     char *result =
1113       my_asnprintf (NULL, &length, "%LF %d", 1234567.0L, 33, 44, 55);
1114     ASSERT (result != NULL);
1115     ASSERT (strcmp (result, "1234567.000000 33") == 0);
1116     ASSERT (length == strlen (result));
1117     free (result);
1118   }
1119
1120   { /* A negative number.  */
1121     size_t length;
1122     char *result =
1123       my_asnprintf (NULL, &length, "%LF %d", -0.03125L, 33, 44, 55);
1124     ASSERT (result != NULL);
1125     ASSERT (strcmp (result, "-0.031250 33") == 0);
1126     ASSERT (length == strlen (result));
1127     free (result);
1128   }
1129
1130   { /* Positive zero.  */
1131     size_t length;
1132     char *result =
1133       my_asnprintf (NULL, &length, "%LF %d", 0.0L, 33, 44, 55);
1134     ASSERT (result != NULL);
1135     ASSERT (strcmp (result, "0.000000 33") == 0);
1136     ASSERT (length == strlen (result));
1137     free (result);
1138   }
1139
1140   { /* Negative zero.  */
1141     size_t length;
1142     char *result =
1143       my_asnprintf (NULL, &length, "%LF %d", -0.0L, 33, 44, 55);
1144     ASSERT (result != NULL);
1145     ASSERT (strcmp (result, "-0.000000 33") == 0);
1146     ASSERT (length == strlen (result));
1147     free (result);
1148   }
1149
1150   { /* Positive infinity.  */
1151     size_t length;
1152     char *result =
1153       my_asnprintf (NULL, &length, "%LF %d", 1.0L / 0.0L, 33, 44, 55);
1154     ASSERT (result != NULL);
1155     ASSERT (strcmp (result, "INF 33") == 0
1156             || strcmp (result, "INFINITY 33") == 0);
1157     ASSERT (length == strlen (result));
1158     free (result);
1159   }
1160
1161   { /* Negative infinity.  */
1162     size_t length;
1163     char *result =
1164       my_asnprintf (NULL, &length, "%LF %d", -1.0L / 0.0L, 33, 44, 55);
1165     ASSERT (result != NULL);
1166     ASSERT (strcmp (result, "-INF 33") == 0
1167             || strcmp (result, "-INFINITY 33") == 0);
1168     ASSERT (length == strlen (result));
1169     free (result);
1170   }
1171
1172   { /* NaN.  */
1173     static long double zero = 0.0L;
1174     size_t length;
1175     char *result =
1176       my_asnprintf (NULL, &length, "%LF %d", zero / zero, 33, 44, 55);
1177     ASSERT (result != NULL);
1178     ASSERT (strcmp (result, "NAN 33") == 0);
1179     ASSERT (length == strlen (result));
1180     free (result);
1181   }
1182
1183   { /* FLAG_ZERO.  */
1184     size_t length;
1185     char *result =
1186       my_asnprintf (NULL, &length, "%015LF %d", 1234.0L, 33, 44, 55);
1187     ASSERT (result != NULL);
1188     ASSERT (strcmp (result, "00001234.000000 33") == 0);
1189     ASSERT (length == strlen (result));
1190     free (result);
1191   }
1192
1193   { /* FLAG_ZERO with infinite number.  */
1194     size_t length;
1195     char *result =
1196       my_asnprintf (NULL, &length, "%015LF %d", -1.0L / 0.0L, 33, 44, 55);
1197     ASSERT (result != NULL);
1198     ASSERT (strcmp (result, "           -INF 33") == 0
1199             || strcmp (result, "      -INFINITY 33") == 0);
1200     ASSERT (length == strlen (result));
1201     free (result);
1202   }
1203
1204   { /* Precision.  */
1205     size_t length;
1206     char *result =
1207       my_asnprintf (NULL, &length, "%.LF %d", 1234.0L, 33, 44, 55);
1208     ASSERT (result != NULL);
1209     ASSERT (strcmp (result, "1234 33") == 0);
1210     ASSERT (length == strlen (result));
1211     free (result);
1212   }
1213
1214   /* Test the support of the %n format directive.  */
1215
1216   {
1217     int count = -1;
1218     size_t length;
1219     char *result =
1220       my_asnprintf (NULL, &length, "%d %n", 123, &count, 33, 44, 55);
1221     ASSERT (result != NULL);
1222     ASSERT (strcmp (result, "123 ") == 0);
1223     ASSERT (length == strlen (result));
1224     ASSERT (count == 4);
1225     free (result);
1226   }
1227
1228   /* Test the support of the POSIX/XSI format strings with positions.  */
1229
1230   {
1231     size_t length;
1232     char *result =
1233       my_asnprintf (NULL, &length, "%2$d %1$d", 33, 55);
1234     ASSERT (result != NULL);
1235     ASSERT (strcmp (result, "55 33") == 0);
1236     ASSERT (length == strlen (result));
1237     free (result);
1238   }
1239
1240   /* Test the support of the grouping flag.  */
1241
1242   {
1243     size_t length;
1244     char *result =
1245       my_asnprintf (NULL, &length, "%'d %d", 1234567, 99);
1246     ASSERT (result != NULL);
1247     ASSERT (result[strlen (result) - 1] == '9');
1248     ASSERT (length == strlen (result));
1249     free (result);
1250   }
1251 }
1252
1253 static char *
1254 my_asnprintf (char *resultbuf, size_t *lengthp, const char *format, ...)
1255 {
1256   va_list args;
1257   char *ret;
1258
1259   va_start (args, format);
1260   ret = vasnprintf (resultbuf, lengthp, format, args);
1261   va_end (args);
1262   return ret;
1263 }
1264
1265 static void
1266 test_vasnprintf ()
1267 {
1268   test_function (my_asnprintf);
1269 }
1270
1271 static void
1272 test_asnprintf ()
1273 {
1274   test_function (asnprintf);
1275 }
1276
1277 int
1278 main (int argc, char *argv[])
1279 {
1280   test_vasnprintf ();
1281   test_asnprintf ();
1282   return 0;
1283 }