import cvs 2:1.12.13+real-5 (see mircvs://src/gnu/usr.bin/cvs/ for VCS history)
[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                     int retcount;
600
601                     maxlen = allocated - length;
602                     count = -1;
603                     retcount = 0;
604
605 #if USE_SNPRINTF
606 # define SNPRINTF_BUF(arg) \
607                     switch (prefix_count)                                   \
608                       {                                                     \
609                       case 0:                                               \
610                         retcount = SNPRINTF (result + length, maxlen, buf,  \
611                                              arg, &count);                  \
612                         break;                                              \
613                       case 1:                                               \
614                         retcount = SNPRINTF (result + length, maxlen, buf,  \
615                                              prefixes[0], arg, &count);     \
616                         break;                                              \
617                       case 2:                                               \
618                         retcount = SNPRINTF (result + length, maxlen, buf,  \
619                                              prefixes[0], prefixes[1], arg, \
620                                              &count);                       \
621                         break;                                              \
622                       default:                                              \
623                         abort ();                                           \
624                       }
625 #else
626 # define SNPRINTF_BUF(arg) \
627                     switch (prefix_count)                                   \
628                       {                                                     \
629                       case 0:                                               \
630                         count = sprintf (tmp, buf, arg);                    \
631                         break;                                              \
632                       case 1:                                               \
633                         count = sprintf (tmp, buf, prefixes[0], arg);       \
634                         break;                                              \
635                       case 2:                                               \
636                         count = sprintf (tmp, buf, prefixes[0], prefixes[1],\
637                                          arg);                              \
638                         break;                                              \
639                       default:                                              \
640                         abort ();                                           \
641                       }
642 #endif
643
644                     switch (type)
645                       {
646                       case TYPE_SCHAR:
647                         {
648                           int arg = a.arg[dp->arg_index].a.a_schar;
649                           SNPRINTF_BUF (arg);
650                         }
651                         break;
652                       case TYPE_UCHAR:
653                         {
654                           unsigned int arg = a.arg[dp->arg_index].a.a_uchar;
655                           SNPRINTF_BUF (arg);
656                         }
657                         break;
658                       case TYPE_SHORT:
659                         {
660                           int arg = a.arg[dp->arg_index].a.a_short;
661                           SNPRINTF_BUF (arg);
662                         }
663                         break;
664                       case TYPE_USHORT:
665                         {
666                           unsigned int arg = a.arg[dp->arg_index].a.a_ushort;
667                           SNPRINTF_BUF (arg);
668                         }
669                         break;
670                       case TYPE_INT:
671                         {
672                           int arg = a.arg[dp->arg_index].a.a_int;
673                           SNPRINTF_BUF (arg);
674                         }
675                         break;
676                       case TYPE_UINT:
677                         {
678                           unsigned int arg = a.arg[dp->arg_index].a.a_uint;
679                           SNPRINTF_BUF (arg);
680                         }
681                         break;
682                       case TYPE_LONGINT:
683                         {
684                           long int arg = a.arg[dp->arg_index].a.a_longint;
685                           SNPRINTF_BUF (arg);
686                         }
687                         break;
688                       case TYPE_ULONGINT:
689                         {
690                           unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint;
691                           SNPRINTF_BUF (arg);
692                         }
693                         break;
694 #ifdef HAVE_LONG_LONG
695                       case TYPE_LONGLONGINT:
696                         {
697                           long long int arg = a.arg[dp->arg_index].a.a_longlongint;
698                           SNPRINTF_BUF (arg);
699                         }
700                         break;
701                       case TYPE_ULONGLONGINT:
702                         {
703                           unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint;
704                           SNPRINTF_BUF (arg);
705                         }
706                         break;
707 #endif
708                       case TYPE_DOUBLE:
709                         {
710                           double arg = a.arg[dp->arg_index].a.a_double;
711                           SNPRINTF_BUF (arg);
712                         }
713                         break;
714 #ifdef HAVE_LONG_DOUBLE
715                       case TYPE_LONGDOUBLE:
716                         {
717                           long double arg = a.arg[dp->arg_index].a.a_longdouble;
718                           SNPRINTF_BUF (arg);
719                         }
720                         break;
721 #endif
722                       case TYPE_CHAR:
723                         {
724                           int arg = a.arg[dp->arg_index].a.a_char;
725                           SNPRINTF_BUF (arg);
726                         }
727                         break;
728 #ifdef HAVE_WINT_T
729                       case TYPE_WIDE_CHAR:
730                         {
731                           wint_t arg = a.arg[dp->arg_index].a.a_wide_char;
732                           SNPRINTF_BUF (arg);
733                         }
734                         break;
735 #endif
736                       case TYPE_STRING:
737                         {
738                           const char *arg = a.arg[dp->arg_index].a.a_string;
739                           SNPRINTF_BUF (arg);
740                         }
741                         break;
742 #ifdef HAVE_WCHAR_T
743                       case TYPE_WIDE_STRING:
744                         {
745                           const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
746                           SNPRINTF_BUF (arg);
747                         }
748                         break;
749 #endif
750                       case TYPE_POINTER:
751                         {
752                           void *arg = a.arg[dp->arg_index].a.a_pointer;
753                           SNPRINTF_BUF (arg);
754                         }
755                         break;
756                       default:
757                         abort ();
758                       }
759
760 #if USE_SNPRINTF
761                     /* Portability: Not all implementations of snprintf()
762                        are ISO C 99 compliant.  Determine the number of
763                        bytes that snprintf() has produced or would have
764                        produced.  */
765                     if (count >= 0)
766                       {
767                         /* Verify that snprintf() has NUL-terminated its
768                            result.  */
769                         if (count < maxlen && result[length + count] != '\0')
770                           abort ();
771                         /* Portability hack.  */
772                         if (retcount > count)
773                           count = retcount;
774                       }
775                     else
776                       {
777                         /* snprintf() doesn't understand the '%n'
778                            directive.  */
779                         if (p[1] != '\0')
780                           {
781                             /* Don't use the '%n' directive; instead, look
782                                at the snprintf() return value.  */
783                             p[1] = '\0';
784                             continue;
785                           }
786                         else
787                           {
788                             /* Look at the snprintf() return value.  */
789                             if (retcount < 0)
790                               {
791                                 /* HP-UX 10.20 snprintf() is doubly deficient:
792                                    It doesn't understand the '%n' directive,
793                                    *and* it returns -1 (rather than the length
794                                    that would have been required) when the
795                                    buffer is too small.  */
796                                 size_t bigger_need =
797                                   xsum (xtimes (allocated, 2), 12);
798                                 ENSURE_ALLOCATION (bigger_need);
799                                 continue;
800                               }
801                             else
802                               count = retcount;
803                           }
804                       }
805 #endif
806
807                     /* Attempt to handle failure.  */
808                     if (count < 0)
809                       {
810                         if (!(result == resultbuf || result == NULL))
811                           free (result);
812                         if (buf_malloced != NULL)
813                           free (buf_malloced);
814                         CLEANUP ();
815                         errno = EINVAL;
816                         return NULL;
817                       }
818
819 #if !USE_SNPRINTF
820                     if (count >= tmp_length)
821                       /* tmp_length was incorrectly calculated - fix the
822                          code above!  */
823                       abort ();
824 #endif
825
826                     /* Make room for the result.  */
827                     if (count >= maxlen)
828                       {
829                         /* Need at least count bytes.  But allocate
830                            proportionally, to avoid looping eternally if
831                            snprintf() reports a too small count.  */
832                         size_t n =
833                           xmax (xsum (length, count), xtimes (allocated, 2));
834
835                         ENSURE_ALLOCATION (n);
836 #if USE_SNPRINTF
837                         continue;
838 #endif
839                       }
840
841 #if USE_SNPRINTF
842                     /* The snprintf() result did fit.  */
843 #else
844                     /* Append the sprintf() result.  */
845                     memcpy (result + length, tmp, count * sizeof (CHAR_T));
846                     if (tmp != tmpbuf)
847                       free (tmp);
848 #endif
849
850                     length += count;
851                     break;
852                   }
853               }
854           }
855       }
856
857     /* Add the final NUL.  */
858     ENSURE_ALLOCATION (xsum (length, 1));
859     result[length] = '\0';
860
861     if (result != resultbuf && length + 1 < allocated)
862       {
863         /* Shrink the allocated memory if possible.  */
864         CHAR_T *memory;
865
866         memory = (CHAR_T *) realloc (result, (length + 1) * sizeof (CHAR_T));
867         if (memory != NULL)
868           result = memory;
869       }
870
871     if (buf_malloced != NULL)
872       free (buf_malloced);
873     CLEANUP ();
874     *lengthp = length;
875     if (length > INT_MAX)
876       goto length_overflow;
877     return result;
878
879   length_overflow:
880     /* We could produce such a big string, but its length doesn't fit into
881        an 'int'.  POSIX says that snprintf() fails with errno = EOVERFLOW in
882        this case.  */
883     if (result != resultbuf)
884       free (result);
885     errno = EOVERFLOW;
886     return NULL;
887
888   out_of_memory:
889     if (!(result == resultbuf || result == NULL))
890       free (result);
891     if (buf_malloced != NULL)
892       free (buf_malloced);
893   out_of_memory_1:
894     CLEANUP ();
895     errno = ENOMEM;
896     return NULL;
897   }
898 }
899
900 #undef SNPRINTF
901 #undef USE_SNPRINTF
902 #undef PRINTF_PARSE
903 #undef DIRECTIVES
904 #undef DIRECTIVE
905 #undef CHAR_T
906 #undef VASNPRINTF