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