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