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