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