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