Add stuff from gnulib.
[gnupg.git] / gl / vasnprintf.c
1 /* vsprintf with automatic memory allocation.
2    Copyright (C) 1999, 2002-2005 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 along
15    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 /* Tell glibc's <stdio.h> to provide a prototype for snprintf().
19    This must come before <config.h> because <config.h> may include
20    <features.h>, and once <features.h> has been included, it's too late.  */
21 #ifndef _GNU_SOURCE
22 # define _GNU_SOURCE    1
23 #endif
24
25 #ifdef HAVE_CONFIG_H
26 # include <config.h>
27 #endif
28 #ifndef IN_LIBINTL
29 # include <alloca.h>
30 #endif
31
32 /* Specification.  */
33 #if WIDE_CHAR_VERSION
34 # include "vasnwprintf.h"
35 #else
36 # include "vasnprintf.h"
37 #endif
38
39 #include <stdio.h>      /* snprintf(), sprintf() */
40 #include <stdlib.h>     /* abort(), malloc(), realloc(), free() */
41 #include <string.h>     /* memcpy(), strlen() */
42 #include <errno.h>      /* errno */
43 #include <limits.h>     /* CHAR_BIT, INT_MAX */
44 #include <float.h>      /* DBL_MAX_EXP, LDBL_MAX_EXP */
45 #if WIDE_CHAR_VERSION
46 # include "wprintf-parse.h"
47 #else
48 # include "printf-parse.h"
49 #endif
50
51 /* Checked size_t computations.  */
52 #include "xsize.h"
53
54 /* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW.  */
55 #ifndef EOVERFLOW
56 # define EOVERFLOW E2BIG
57 #endif
58
59 #ifdef HAVE_WCHAR_T
60 # ifdef HAVE_WCSLEN
61 #  define local_wcslen wcslen
62 # else
63    /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid
64       a dependency towards this library, here is a local substitute.
65       Define this substitute only once, even if this file is included
66       twice in the same compilation unit.  */
67 #  ifndef local_wcslen_defined
68 #   define local_wcslen_defined 1
69 static size_t
70 local_wcslen (const wchar_t *s)
71 {
72   const wchar_t *ptr;
73
74   for (ptr = s; *ptr != (wchar_t) 0; ptr++)
75     ;
76   return ptr - s;
77 }
78 #  endif
79 # endif
80 #endif
81
82 #if WIDE_CHAR_VERSION
83 # define VASNPRINTF vasnwprintf
84 # define CHAR_T wchar_t
85 # define DIRECTIVE wchar_t_directive
86 # define DIRECTIVES wchar_t_directives
87 # define PRINTF_PARSE wprintf_parse
88 # define USE_SNPRINTF 1
89 # if HAVE_DECL__SNWPRINTF
90    /* On Windows, the function swprintf() has a different signature than
91       on Unix; we use the _snwprintf() function instead.  */
92 #  define SNPRINTF _snwprintf
93 # else
94    /* Unix.  */
95 #  define SNPRINTF swprintf
96 # endif
97 #else
98 # define VASNPRINTF vasnprintf
99 # define CHAR_T char
100 # define DIRECTIVE char_directive
101 # define DIRECTIVES char_directives
102 # define PRINTF_PARSE printf_parse
103 # define USE_SNPRINTF (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF)
104 # if HAVE_DECL__SNPRINTF
105    /* Windows.  */
106 #  define SNPRINTF _snprintf
107 # else
108    /* Unix.  */
109 #  define SNPRINTF snprintf
110 # endif
111 #endif
112
113 CHAR_T *
114 VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list args)
115 {
116   DIRECTIVES d;
117   arguments a;
118
119   if (PRINTF_PARSE (format, &d, &a) < 0)
120     {
121       errno = EINVAL;
122       return NULL;
123     }
124
125 #define CLEANUP() \
126   free (d.dir);                                                         \
127   if (a.arg)                                                            \
128     free (a.arg);
129
130   if (printf_fetchargs (args, &a) < 0)
131     {
132       CLEANUP ();
133       errno = EINVAL;
134       return NULL;
135     }
136
137   {
138     size_t buf_neededlength;
139     CHAR_T *buf;
140     CHAR_T *buf_malloced;
141     const CHAR_T *cp;
142     size_t i;
143     DIRECTIVE *dp;
144     /* Output string accumulator.  */
145     CHAR_T *result;
146     size_t allocated;
147     size_t length;
148
149     /* Allocate a small buffer that will hold a directive passed to
150        sprintf or snprintf.  */
151     buf_neededlength =
152       xsum4 (7, d.max_width_length, d.max_precision_length, 6);
153 #if HAVE_ALLOCA
154     if (buf_neededlength < 4000 / sizeof (CHAR_T))
155       {
156         buf = (CHAR_T *) alloca (buf_neededlength * sizeof (CHAR_T));
157         buf_malloced = NULL;
158       }
159     else
160 #endif
161       {
162         size_t buf_memsize = xtimes (buf_neededlength, sizeof (CHAR_T));
163         if (size_overflow_p (buf_memsize))
164           goto out_of_memory_1;
165         buf = (CHAR_T *) malloc (buf_memsize);
166         if (buf == NULL)
167           goto out_of_memory_1;
168         buf_malloced = buf;
169       }
170
171     if (resultbuf != NULL)
172       {
173         result = resultbuf;
174         allocated = *lengthp;
175       }
176     else
177       {
178         result = NULL;
179         allocated = 0;
180       }
181     length = 0;
182     /* Invariants:
183        result is either == resultbuf or == NULL or malloc-allocated.
184        If length > 0, then result != NULL.  */
185
186     /* Ensures that allocated >= needed.  Aborts through a jump to
187        out_of_memory if needed is SIZE_MAX or otherwise too big.  */
188 #define ENSURE_ALLOCATION(needed) \
189     if ((needed) > allocated)                                                \
190       {                                                                      \
191         size_t memory_size;                                                  \
192         CHAR_T *memory;                                                      \
193                                                                              \
194         allocated = (allocated > 0 ? xtimes (allocated, 2) : 12);            \
195         if ((needed) > allocated)                                            \
196           allocated = (needed);                                              \
197         memory_size = xtimes (allocated, sizeof (CHAR_T));                   \
198         if (size_overflow_p (memory_size))                                   \
199           goto out_of_memory;                                                \
200         if (result == resultbuf || result == NULL)                           \
201           memory = (CHAR_T *) malloc (memory_size);                          \
202         else                                                                 \
203           memory = (CHAR_T *) realloc (result, memory_size);                 \
204         if (memory == NULL)                                                  \
205           goto out_of_memory;                                                \
206         if (result == resultbuf && length > 0)                               \
207           memcpy (memory, result, length * sizeof (CHAR_T));                 \
208         result = memory;                                                     \
209       }
210
211     for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++)
212       {
213         if (cp != dp->dir_start)
214           {
215             size_t n = dp->dir_start - cp;
216             size_t augmented_length = xsum (length, n);
217
218             ENSURE_ALLOCATION (augmented_length);
219             memcpy (result + length, cp, n * sizeof (CHAR_T));
220             length = augmented_length;
221           }
222         if (i == d.count)
223           break;
224
225         /* Execute a single directive.  */
226         if (dp->conversion == '%')
227           {
228             size_t augmented_length;
229
230             if (!(dp->arg_index == ARG_NONE))
231               abort ();
232             augmented_length = xsum (length, 1);
233             ENSURE_ALLOCATION (augmented_length);
234             result[length] = '%';
235             length = augmented_length;
236           }
237         else
238           {
239             if (!(dp->arg_index != ARG_NONE))
240               abort ();
241
242             if (dp->conversion == 'n')
243               {
244                 switch (a.arg[dp->arg_index].type)
245                   {
246                   case TYPE_COUNT_SCHAR_POINTER:
247                     *a.arg[dp->arg_index].a.a_count_schar_pointer = length;
248                     break;
249                   case TYPE_COUNT_SHORT_POINTER:
250                     *a.arg[dp->arg_index].a.a_count_short_pointer = length;
251                     break;
252                   case TYPE_COUNT_INT_POINTER:
253                     *a.arg[dp->arg_index].a.a_count_int_pointer = length;
254                     break;
255                   case TYPE_COUNT_LONGINT_POINTER:
256                     *a.arg[dp->arg_index].a.a_count_longint_pointer = length;
257                     break;
258 #ifdef HAVE_LONG_LONG
259                   case TYPE_COUNT_LONGLONGINT_POINTER:
260                     *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length;
261                     break;
262 #endif
263                   default:
264                     abort ();
265                   }
266               }
267             else
268               {
269                 arg_type type = a.arg[dp->arg_index].type;
270                 CHAR_T *p;
271                 unsigned int prefix_count;
272                 int prefixes[2];
273 #if !USE_SNPRINTF
274                 size_t tmp_length;
275                 CHAR_T tmpbuf[700];
276                 CHAR_T *tmp;
277
278                 /* Allocate a temporary buffer of sufficient size for calling
279                    sprintf.  */
280                 {
281                   size_t width;
282                   size_t precision;
283
284                   width = 0;
285                   if (dp->width_start != dp->width_end)
286                     {
287                       if (dp->width_arg_index != ARG_NONE)
288                         {
289                           int arg;
290
291                           if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
292                             abort ();
293                           arg = a.arg[dp->width_arg_index].a.a_int;
294                           width = (arg < 0 ? (unsigned int) (-arg) : arg);
295                         }
296                       else
297                         {
298                           const CHAR_T *digitp = dp->width_start;
299
300                           do
301                             width = xsum (xtimes (width, 10), *digitp++ - '0');
302                           while (digitp != dp->width_end);
303                         }
304                     }
305
306                   precision = 6;
307                   if (dp->precision_start != dp->precision_end)
308                     {
309                       if (dp->precision_arg_index != ARG_NONE)
310                         {
311                           int arg;
312
313                           if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
314                             abort ();
315                           arg = a.arg[dp->precision_arg_index].a.a_int;
316                           precision = (arg < 0 ? 0 : arg);
317                         }
318                       else
319                         {
320                           const CHAR_T *digitp = dp->precision_start + 1;
321
322                           precision = 0;
323                           while (digitp != dp->precision_end)
324                             precision = xsum (xtimes (precision, 10), *digitp++ - '0');
325                         }
326                     }
327
328                   switch (dp->conversion)
329                     {
330
331                     case 'd': case 'i': case 'u':
332 # ifdef HAVE_LONG_LONG
333                       if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
334                         tmp_length =
335                           (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
336                                           * 0.30103 /* binary -> decimal */
337                                           * 2 /* estimate for FLAG_GROUP */
338                                          )
339                           + 1 /* turn floor into ceil */
340                           + 1; /* account for leading sign */
341                       else
342 # endif
343                       if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
344                         tmp_length =
345                           (unsigned int) (sizeof (unsigned long) * CHAR_BIT
346                                           * 0.30103 /* binary -> decimal */
347                                           * 2 /* estimate for FLAG_GROUP */
348                                          )
349                           + 1 /* turn floor into ceil */
350                           + 1; /* account for leading sign */
351                       else
352                         tmp_length =
353                           (unsigned int) (sizeof (unsigned int) * CHAR_BIT
354                                           * 0.30103 /* binary -> decimal */
355                                           * 2 /* estimate for FLAG_GROUP */
356                                          )
357                           + 1 /* turn floor into ceil */
358                           + 1; /* account for leading sign */
359                       break;
360
361                     case 'o':
362 # ifdef HAVE_LONG_LONG
363                       if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
364                         tmp_length =
365                           (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
366                                           * 0.333334 /* binary -> octal */
367                                          )
368                           + 1 /* turn floor into ceil */
369                           + 1; /* account for leading sign */
370                       else
371 # endif
372                       if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
373                         tmp_length =
374                           (unsigned int) (sizeof (unsigned long) * CHAR_BIT
375                                           * 0.333334 /* binary -> octal */
376                                          )
377                           + 1 /* turn floor into ceil */
378                           + 1; /* account for leading sign */
379                       else
380                         tmp_length =
381                           (unsigned int) (sizeof (unsigned int) * CHAR_BIT
382                                           * 0.333334 /* binary -> octal */
383                                          )
384                           + 1 /* turn floor into ceil */
385                           + 1; /* account for leading sign */
386                       break;
387
388                     case 'x': case 'X':
389 # ifdef HAVE_LONG_LONG
390                       if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
391                         tmp_length =
392                           (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
393                                           * 0.25 /* binary -> hexadecimal */
394                                          )
395                           + 1 /* turn floor into ceil */
396                           + 2; /* account for leading sign or alternate form */
397                       else
398 # endif
399                       if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
400                         tmp_length =
401                           (unsigned int) (sizeof (unsigned long) * CHAR_BIT
402                                           * 0.25 /* binary -> hexadecimal */
403                                          )
404                           + 1 /* turn floor into ceil */
405                           + 2; /* account for leading sign or alternate form */
406                       else
407                         tmp_length =
408                           (unsigned int) (sizeof (unsigned int) * CHAR_BIT
409                                           * 0.25 /* binary -> hexadecimal */
410                                          )
411                           + 1 /* turn floor into ceil */
412                           + 2; /* account for leading sign or alternate form */
413                       break;
414
415                     case 'f': case 'F':
416 # ifdef HAVE_LONG_DOUBLE
417                       if (type == TYPE_LONGDOUBLE)
418                         tmp_length =
419                           (unsigned int) (LDBL_MAX_EXP
420                                           * 0.30103 /* binary -> decimal */
421                                           * 2 /* estimate for FLAG_GROUP */
422                                          )
423                           + 1 /* turn floor into ceil */
424                           + 10; /* sign, decimal point etc. */
425                       else
426 # endif
427                         tmp_length =
428                           (unsigned int) (DBL_MAX_EXP
429                                           * 0.30103 /* binary -> decimal */
430                                           * 2 /* estimate for FLAG_GROUP */
431                                          )
432                           + 1 /* turn floor into ceil */
433                           + 10; /* sign, decimal point etc. */
434                       tmp_length = xsum (tmp_length, precision);
435                       break;
436
437                     case 'e': case 'E': case 'g': case 'G':
438                     case 'a': case 'A':
439                       tmp_length =
440                         12; /* sign, decimal point, exponent etc. */
441                       tmp_length = xsum (tmp_length, precision);
442                       break;
443
444                     case 'c':
445 # if defined HAVE_WINT_T && !WIDE_CHAR_VERSION
446                       if (type == TYPE_WIDE_CHAR)
447                         tmp_length = MB_CUR_MAX;
448                       else
449 # endif
450                         tmp_length = 1;
451                       break;
452
453                     case 's':
454 # ifdef HAVE_WCHAR_T
455                       if (type == TYPE_WIDE_STRING)
456                         {
457                           tmp_length =
458                             local_wcslen (a.arg[dp->arg_index].a.a_wide_string);
459
460 #  if !WIDE_CHAR_VERSION
461                           tmp_length = xtimes (tmp_length, MB_CUR_MAX);
462 #  endif
463                         }
464                       else
465 # endif
466                         tmp_length = strlen (a.arg[dp->arg_index].a.a_string);
467                       break;
468
469                     case 'p':
470                       tmp_length =
471                         (unsigned int) (sizeof (void *) * CHAR_BIT
472                                         * 0.25 /* binary -> hexadecimal */
473                                        )
474                           + 1 /* turn floor into ceil */
475                           + 2; /* account for leading 0x */
476                       break;
477
478                     default:
479                       abort ();
480                     }
481
482                   if (tmp_length < width)
483                     tmp_length = width;
484
485                   tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
486                 }
487
488                 if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T))
489                   tmp = tmpbuf;
490                 else
491                   {
492                     size_t tmp_memsize = xtimes (tmp_length, sizeof (CHAR_T));
493
494                     if (size_overflow_p (tmp_memsize))
495                       /* Overflow, would lead to out of memory.  */
496                       goto out_of_memory;
497                     tmp = (CHAR_T *) malloc (tmp_memsize);
498                     if (tmp == NULL)
499                       /* Out of memory.  */
500                       goto out_of_memory;
501                   }
502 #endif
503
504                 /* Construct the format string for calling snprintf or
505                    sprintf.  */
506                 p = buf;
507                 *p++ = '%';
508                 if (dp->flags & FLAG_GROUP)
509                   *p++ = '\'';
510                 if (dp->flags & FLAG_LEFT)
511                   *p++ = '-';
512                 if (dp->flags & FLAG_SHOWSIGN)
513                   *p++ = '+';
514                 if (dp->flags & FLAG_SPACE)
515                   *p++ = ' ';
516                 if (dp->flags & FLAG_ALT)
517                   *p++ = '#';
518                 if (dp->flags & FLAG_ZERO)
519                   *p++ = '0';
520                 if (dp->width_start != dp->width_end)
521                   {
522                     size_t n = dp->width_end - dp->width_start;
523                     memcpy (p, dp->width_start, n * sizeof (CHAR_T));
524                     p += n;
525                   }
526                 if (dp->precision_start != dp->precision_end)
527                   {
528                     size_t n = dp->precision_end - dp->precision_start;
529                     memcpy (p, dp->precision_start, n * sizeof (CHAR_T));
530                     p += n;
531                   }
532
533                 switch (type)
534                   {
535 #ifdef HAVE_LONG_LONG
536                   case TYPE_LONGLONGINT:
537                   case TYPE_ULONGLONGINT:
538                     *p++ = 'l';
539                     /*FALLTHROUGH*/
540 #endif
541                   case TYPE_LONGINT:
542                   case TYPE_ULONGINT:
543 #ifdef HAVE_WINT_T
544                   case TYPE_WIDE_CHAR:
545 #endif
546 #ifdef HAVE_WCHAR_T
547                   case TYPE_WIDE_STRING:
548 #endif
549                     *p++ = 'l';
550                     break;
551 #ifdef HAVE_LONG_DOUBLE
552                   case TYPE_LONGDOUBLE:
553                     *p++ = 'L';
554                     break;
555 #endif
556                   default:
557                     break;
558                   }
559                 *p = dp->conversion;
560 #if USE_SNPRINTF
561                 p[1] = '%';
562                 p[2] = 'n';
563                 p[3] = '\0';
564 #else
565                 p[1] = '\0';
566 #endif
567
568                 /* Construct the arguments for calling snprintf or sprintf.  */
569                 prefix_count = 0;
570                 if (dp->width_arg_index != ARG_NONE)
571                   {
572                     if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
573                       abort ();
574                     prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int;
575                   }
576                 if (dp->precision_arg_index != ARG_NONE)
577                   {
578                     if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
579                       abort ();
580                     prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int;
581                   }
582
583 #if USE_SNPRINTF
584                 /* Prepare checking whether snprintf returns the count
585                    via %n.  */
586                 ENSURE_ALLOCATION (xsum (length, 1));
587                 result[length] = '\0';
588 #endif
589
590                 for (;;)
591                   {
592                     size_t maxlen;
593                     int count;
594                     int retcount;
595
596                     maxlen = allocated - length;
597                     count = -1;
598                     retcount = 0;
599
600 #if USE_SNPRINTF
601 # define SNPRINTF_BUF(arg) \
602                     switch (prefix_count)                                   \
603                       {                                                     \
604                       case 0:                                               \
605                         retcount = SNPRINTF (result + length, maxlen, buf,  \
606                                              arg, &count);                  \
607                         break;                                              \
608                       case 1:                                               \
609                         retcount = SNPRINTF (result + length, maxlen, buf,  \
610                                              prefixes[0], arg, &count);     \
611                         break;                                              \
612                       case 2:                                               \
613                         retcount = SNPRINTF (result + length, maxlen, buf,  \
614                                              prefixes[0], prefixes[1], arg, \
615                                              &count);                       \
616                         break;                                              \
617                       default:                                              \
618                         abort ();                                           \
619                       }
620 #else
621 # define SNPRINTF_BUF(arg) \
622                     switch (prefix_count)                                   \
623                       {                                                     \
624                       case 0:                                               \
625                         count = sprintf (tmp, buf, arg);                    \
626                         break;                                              \
627                       case 1:                                               \
628                         count = sprintf (tmp, buf, prefixes[0], arg);       \
629                         break;                                              \
630                       case 2:                                               \
631                         count = sprintf (tmp, buf, prefixes[0], prefixes[1],\
632                                          arg);                              \
633                         break;                                              \
634                       default:                                              \
635                         abort ();                                           \
636                       }
637 #endif
638
639                     switch (type)
640                       {
641                       case TYPE_SCHAR:
642                         {
643                           int arg = a.arg[dp->arg_index].a.a_schar;
644                           SNPRINTF_BUF (arg);
645                         }
646                         break;
647                       case TYPE_UCHAR:
648                         {
649                           unsigned int arg = a.arg[dp->arg_index].a.a_uchar;
650                           SNPRINTF_BUF (arg);
651                         }
652                         break;
653                       case TYPE_SHORT:
654                         {
655                           int arg = a.arg[dp->arg_index].a.a_short;
656                           SNPRINTF_BUF (arg);
657                         }
658                         break;
659                       case TYPE_USHORT:
660                         {
661                           unsigned int arg = a.arg[dp->arg_index].a.a_ushort;
662                           SNPRINTF_BUF (arg);
663                         }
664                         break;
665                       case TYPE_INT:
666                         {
667                           int arg = a.arg[dp->arg_index].a.a_int;
668                           SNPRINTF_BUF (arg);
669                         }
670                         break;
671                       case TYPE_UINT:
672                         {
673                           unsigned int arg = a.arg[dp->arg_index].a.a_uint;
674                           SNPRINTF_BUF (arg);
675                         }
676                         break;
677                       case TYPE_LONGINT:
678                         {
679                           long int arg = a.arg[dp->arg_index].a.a_longint;
680                           SNPRINTF_BUF (arg);
681                         }
682                         break;
683                       case TYPE_ULONGINT:
684                         {
685                           unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint;
686                           SNPRINTF_BUF (arg);
687                         }
688                         break;
689 #ifdef HAVE_LONG_LONG
690                       case TYPE_LONGLONGINT:
691                         {
692                           long long int arg = a.arg[dp->arg_index].a.a_longlongint;
693                           SNPRINTF_BUF (arg);
694                         }
695                         break;
696                       case TYPE_ULONGLONGINT:
697                         {
698                           unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint;
699                           SNPRINTF_BUF (arg);
700                         }
701                         break;
702 #endif
703                       case TYPE_DOUBLE:
704                         {
705                           double arg = a.arg[dp->arg_index].a.a_double;
706                           SNPRINTF_BUF (arg);
707                         }
708                         break;
709 #ifdef HAVE_LONG_DOUBLE
710                       case TYPE_LONGDOUBLE:
711                         {
712                           long double arg = a.arg[dp->arg_index].a.a_longdouble;
713                           SNPRINTF_BUF (arg);
714                         }
715                         break;
716 #endif
717                       case TYPE_CHAR:
718                         {
719                           int arg = a.arg[dp->arg_index].a.a_char;
720                           SNPRINTF_BUF (arg);
721                         }
722                         break;
723 #ifdef HAVE_WINT_T
724                       case TYPE_WIDE_CHAR:
725                         {
726                           wint_t arg = a.arg[dp->arg_index].a.a_wide_char;
727                           SNPRINTF_BUF (arg);
728                         }
729                         break;
730 #endif
731                       case TYPE_STRING:
732                         {
733                           const char *arg = a.arg[dp->arg_index].a.a_string;
734                           SNPRINTF_BUF (arg);
735                         }
736                         break;
737 #ifdef HAVE_WCHAR_T
738                       case TYPE_WIDE_STRING:
739                         {
740                           const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
741                           SNPRINTF_BUF (arg);
742                         }
743                         break;
744 #endif
745                       case TYPE_POINTER:
746                         {
747                           void *arg = a.arg[dp->arg_index].a.a_pointer;
748                           SNPRINTF_BUF (arg);
749                         }
750                         break;
751                       default:
752                         abort ();
753                       }
754
755 #if USE_SNPRINTF
756                     /* Portability: Not all implementations of snprintf()
757                        are ISO C 99 compliant.  Determine the number of
758                        bytes that snprintf() has produced or would have
759                        produced.  */
760                     if (count >= 0)
761                       {
762                         /* Verify that snprintf() has NUL-terminated its
763                            result.  */
764                         if (count < maxlen && result[length + count] != '\0')
765                           abort ();
766                         /* Portability hack.  */
767                         if (retcount > count)
768                           count = retcount;
769                       }
770                     else
771                       {
772                         /* snprintf() doesn't understand the '%n'
773                            directive.  */
774                         if (p[1] != '\0')
775                           {
776                             /* Don't use the '%n' directive; instead, look
777                                at the snprintf() return value.  */
778                             p[1] = '\0';
779                             continue;
780                           }
781                         else
782                           {
783                             /* Look at the snprintf() return value.  */
784                             if (retcount < 0)
785                               {
786                                 /* HP-UX 10.20 snprintf() is doubly deficient:
787                                    It doesn't understand the '%n' directive,
788                                    *and* it returns -1 (rather than the length
789                                    that would have been required) when the
790                                    buffer is too small.  */
791                                 size_t bigger_need =
792                                   xsum (xtimes (allocated, 2), 12);
793                                 ENSURE_ALLOCATION (bigger_need);
794                                 continue;
795                               }
796                             else
797                               count = retcount;
798                           }
799                       }
800 #endif
801
802                     /* Attempt to handle failure.  */
803                     if (count < 0)
804                       {
805                         if (!(result == resultbuf || result == NULL))
806                           free (result);
807                         if (buf_malloced != NULL)
808                           free (buf_malloced);
809                         CLEANUP ();
810                         errno = EINVAL;
811                         return NULL;
812                       }
813
814 #if !USE_SNPRINTF
815                     if (count >= tmp_length)
816                       /* tmp_length was incorrectly calculated - fix the
817                          code above!  */
818                       abort ();
819 #endif
820
821                     /* Make room for the result.  */
822                     if (count >= maxlen)
823                       {
824                         /* Need at least count bytes.  But allocate
825                            proportionally, to avoid looping eternally if
826                            snprintf() reports a too small count.  */
827                         size_t n =
828                           xmax (xsum (length, count), xtimes (allocated, 2));
829
830                         ENSURE_ALLOCATION (n);
831 #if USE_SNPRINTF
832                         continue;
833 #endif
834                       }
835
836 #if USE_SNPRINTF
837                     /* The snprintf() result did fit.  */
838 #else
839                     /* Append the sprintf() result.  */
840                     memcpy (result + length, tmp, count * sizeof (CHAR_T));
841                     if (tmp != tmpbuf)
842                       free (tmp);
843 #endif
844
845                     length += count;
846                     break;
847                   }
848               }
849           }
850       }
851
852     /* Add the final NUL.  */
853     ENSURE_ALLOCATION (xsum (length, 1));
854     result[length] = '\0';
855
856     if (result != resultbuf && length + 1 < allocated)
857       {
858         /* Shrink the allocated memory if possible.  */
859         CHAR_T *memory;
860
861         memory = (CHAR_T *) realloc (result, (length + 1) * sizeof (CHAR_T));
862         if (memory != NULL)
863           result = memory;
864       }
865
866     if (buf_malloced != NULL)
867       free (buf_malloced);
868     CLEANUP ();
869     *lengthp = length;
870     if (length > INT_MAX)
871       goto length_overflow;
872     return result;
873
874   length_overflow:
875     /* We could produce such a big string, but its length doesn't fit into
876        an 'int'.  POSIX says that snprintf() fails with errno = EOVERFLOW in
877        this case.  */
878     if (result != resultbuf)
879       free (result);
880     errno = EOVERFLOW;
881     return NULL;
882
883   out_of_memory:
884     if (!(result == resultbuf || result == NULL))
885       free (result);
886     if (buf_malloced != NULL)
887       free (buf_malloced);
888   out_of_memory_1:
889     CLEANUP ();
890     errno = ENOMEM;
891     return NULL;
892   }
893 }
894
895 #undef SNPRINTF
896 #undef USE_SNPRINTF
897 #undef PRINTF_PARSE
898 #undef DIRECTIVES
899 #undef DIRECTIVE
900 #undef CHAR_T
901 #undef VASNPRINTF