Work around broken snprintf function on BeOS.
[gnulib.git] / lib / vasnprintf.c
1 /* vsprintf with automatic memory allocation.
2    Copyright (C) 1999, 2002-2007 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 #include <config.h>
26 #ifndef IN_LIBINTL
27 # include <alloca.h>
28 #endif
29
30 /* Specification.  */
31 #if WIDE_CHAR_VERSION
32 # include "vasnwprintf.h"
33 #else
34 # include "vasnprintf.h"
35 #endif
36
37 #include <locale.h>     /* localeconv() */
38 #include <stdio.h>      /* snprintf(), sprintf() */
39 #include <stdlib.h>     /* abort(), malloc(), realloc(), free() */
40 #include <string.h>     /* memcpy(), strlen() */
41 #include <errno.h>      /* errno */
42 #include <limits.h>     /* CHAR_BIT */
43 #include <float.h>      /* DBL_MAX_EXP, LDBL_MAX_EXP */
44 #if HAVE_NL_LANGINFO
45 # include <langinfo.h>
46 #endif
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 #if NEED_PRINTF_DIRECTIVE_A && !defined IN_LIBINTL
57 # include <math.h>
58 # include "isnan.h"
59 # include "printf-frexp.h"
60 # include "isnanl-nolibm.h"
61 # include "printf-frexpl.h"
62 # include "fpucw.h"
63 #endif
64
65 /* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW.  */
66 #ifndef EOVERFLOW
67 # define EOVERFLOW E2BIG
68 #endif
69
70 #if HAVE_WCHAR_T
71 # if HAVE_WCSLEN
72 #  define local_wcslen wcslen
73 # else
74    /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid
75       a dependency towards this library, here is a local substitute.
76       Define this substitute only once, even if this file is included
77       twice in the same compilation unit.  */
78 #  ifndef local_wcslen_defined
79 #   define local_wcslen_defined 1
80 static size_t
81 local_wcslen (const wchar_t *s)
82 {
83   const wchar_t *ptr;
84
85   for (ptr = s; *ptr != (wchar_t) 0; ptr++)
86     ;
87   return ptr - s;
88 }
89 #  endif
90 # endif
91 #endif
92
93 #if WIDE_CHAR_VERSION
94 # define VASNPRINTF vasnwprintf
95 # define CHAR_T wchar_t
96 # define DIRECTIVE wchar_t_directive
97 # define DIRECTIVES wchar_t_directives
98 # define PRINTF_PARSE wprintf_parse
99 # define USE_SNPRINTF 1
100 # if HAVE_DECL__SNWPRINTF
101    /* On Windows, the function swprintf() has a different signature than
102       on Unix; we use the _snwprintf() function instead.  */
103 #  define SNPRINTF _snwprintf
104 # else
105    /* Unix.  */
106 #  define SNPRINTF swprintf
107 # endif
108 #else
109 # define VASNPRINTF vasnprintf
110 # define CHAR_T char
111 # define DIRECTIVE char_directive
112 # define DIRECTIVES char_directives
113 # define PRINTF_PARSE printf_parse
114 # /* Use snprintf if it exists under the name 'snprintf' or '_snprintf'.
115      But don't use it on BeOS, since BeOS snprintf produces no output if the
116      size argument is >= 0x3000000.  */
117 # if (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF) && !defined __BEOS__
118 #  define USE_SNPRINTF 1
119 # else
120 #  define USE_SNPRINTF 0
121 # endif
122 # if HAVE_DECL__SNPRINTF
123    /* Windows.  */
124 #  define SNPRINTF _snprintf
125 # else
126    /* Unix.  */
127 #  define SNPRINTF snprintf
128    /* Here we need to call the native snprintf, not rpl_snprintf.  */
129 #  undef snprintf
130 # endif
131 #endif
132 /* Here we need to call the native sprintf, not rpl_sprintf.  */
133 #undef sprintf
134
135 #if NEED_PRINTF_DIRECTIVE_A && !defined IN_LIBINTL
136 /* Determine the decimal-point character according to the current locale.  */
137 # ifndef decimal_point_char_defined
138 #  define decimal_point_char_defined 1
139 static char
140 decimal_point_char ()
141 {
142   const char *point;
143   /* Determine it in a multithread-safe way.  We know nl_langinfo is
144      multithread-safe on glibc systems, but is not required to be multithread-
145      safe by POSIX.  sprintf(), however, is multithread-safe.  localeconv()
146      is rarely multithread-safe.  */
147 #  if HAVE_NL_LANGINFO && __GLIBC__
148   point = nl_langinfo (RADIXCHAR);
149 #  elif 1
150   char pointbuf[5];
151   sprintf (pointbuf, "%#.0f", 1.0);
152   point = &pointbuf[1];
153 #  else
154   point = localeconv () -> decimal_point;
155 #  endif
156   /* The decimal point is always a single byte: either '.' or ','.  */
157   return (point[0] != '\0' ? point[0] : '.');
158 }
159 # endif
160 #endif
161
162 CHAR_T *
163 VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list args)
164 {
165   DIRECTIVES d;
166   arguments a;
167
168   if (PRINTF_PARSE (format, &d, &a) < 0)
169     {
170       errno = EINVAL;
171       return NULL;
172     }
173
174 #define CLEANUP() \
175   free (d.dir);                                                         \
176   if (a.arg)                                                            \
177     free (a.arg);
178
179   if (printf_fetchargs (args, &a) < 0)
180     {
181       CLEANUP ();
182       errno = EINVAL;
183       return NULL;
184     }
185
186   {
187     size_t buf_neededlength;
188     CHAR_T *buf;
189     CHAR_T *buf_malloced;
190     const CHAR_T *cp;
191     size_t i;
192     DIRECTIVE *dp;
193     /* Output string accumulator.  */
194     CHAR_T *result;
195     size_t allocated;
196     size_t length;
197
198     /* Allocate a small buffer that will hold a directive passed to
199        sprintf or snprintf.  */
200     buf_neededlength =
201       xsum4 (7, d.max_width_length, d.max_precision_length, 6);
202 #if HAVE_ALLOCA
203     if (buf_neededlength < 4000 / sizeof (CHAR_T))
204       {
205         buf = (CHAR_T *) alloca (buf_neededlength * sizeof (CHAR_T));
206         buf_malloced = NULL;
207       }
208     else
209 #endif
210       {
211         size_t buf_memsize = xtimes (buf_neededlength, sizeof (CHAR_T));
212         if (size_overflow_p (buf_memsize))
213           goto out_of_memory_1;
214         buf = (CHAR_T *) malloc (buf_memsize);
215         if (buf == NULL)
216           goto out_of_memory_1;
217         buf_malloced = buf;
218       }
219
220     if (resultbuf != NULL)
221       {
222         result = resultbuf;
223         allocated = *lengthp;
224       }
225     else
226       {
227         result = NULL;
228         allocated = 0;
229       }
230     length = 0;
231     /* Invariants:
232        result is either == resultbuf or == NULL or malloc-allocated.
233        If length > 0, then result != NULL.  */
234
235     /* Ensures that allocated >= needed.  Aborts through a jump to
236        out_of_memory if needed is SIZE_MAX or otherwise too big.  */
237 #define ENSURE_ALLOCATION(needed) \
238     if ((needed) > allocated)                                                \
239       {                                                                      \
240         size_t memory_size;                                                  \
241         CHAR_T *memory;                                                      \
242                                                                              \
243         allocated = (allocated > 0 ? xtimes (allocated, 2) : 12);            \
244         if ((needed) > allocated)                                            \
245           allocated = (needed);                                              \
246         memory_size = xtimes (allocated, sizeof (CHAR_T));                   \
247         if (size_overflow_p (memory_size))                                   \
248           goto out_of_memory;                                                \
249         if (result == resultbuf || result == NULL)                           \
250           memory = (CHAR_T *) malloc (memory_size);                          \
251         else                                                                 \
252           memory = (CHAR_T *) realloc (result, memory_size);                 \
253         if (memory == NULL)                                                  \
254           goto out_of_memory;                                                \
255         if (result == resultbuf && length > 0)                               \
256           memcpy (memory, result, length * sizeof (CHAR_T));                 \
257         result = memory;                                                     \
258       }
259
260     for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++)
261       {
262         if (cp != dp->dir_start)
263           {
264             size_t n = dp->dir_start - cp;
265             size_t augmented_length = xsum (length, n);
266
267             ENSURE_ALLOCATION (augmented_length);
268             memcpy (result + length, cp, n * sizeof (CHAR_T));
269             length = augmented_length;
270           }
271         if (i == d.count)
272           break;
273
274         /* Execute a single directive.  */
275         if (dp->conversion == '%')
276           {
277             size_t augmented_length;
278
279             if (!(dp->arg_index == ARG_NONE))
280               abort ();
281             augmented_length = xsum (length, 1);
282             ENSURE_ALLOCATION (augmented_length);
283             result[length] = '%';
284             length = augmented_length;
285           }
286         else
287           {
288             if (!(dp->arg_index != ARG_NONE))
289               abort ();
290
291             if (dp->conversion == 'n')
292               {
293                 switch (a.arg[dp->arg_index].type)
294                   {
295                   case TYPE_COUNT_SCHAR_POINTER:
296                     *a.arg[dp->arg_index].a.a_count_schar_pointer = length;
297                     break;
298                   case TYPE_COUNT_SHORT_POINTER:
299                     *a.arg[dp->arg_index].a.a_count_short_pointer = length;
300                     break;
301                   case TYPE_COUNT_INT_POINTER:
302                     *a.arg[dp->arg_index].a.a_count_int_pointer = length;
303                     break;
304                   case TYPE_COUNT_LONGINT_POINTER:
305                     *a.arg[dp->arg_index].a.a_count_longint_pointer = length;
306                     break;
307 #if HAVE_LONG_LONG_INT
308                   case TYPE_COUNT_LONGLONGINT_POINTER:
309                     *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length;
310                     break;
311 #endif
312                   default:
313                     abort ();
314                   }
315               }
316 #if NEED_PRINTF_DIRECTIVE_A && !defined IN_LIBINTL
317             else if (dp->conversion == 'a' || dp->conversion == 'A')
318               {
319                 arg_type type = a.arg[dp->arg_index].type;
320                 int flags = dp->flags;
321                 int has_width;
322                 size_t width;
323                 int has_precision;
324                 size_t precision;
325                 size_t tmp_length;
326                 CHAR_T tmpbuf[700];
327                 CHAR_T *tmp;
328                 CHAR_T *pad_ptr;
329                 CHAR_T *p;
330
331                 has_width = 0;
332                 width = 0;
333                 if (dp->width_start != dp->width_end)
334                   {
335                     if (dp->width_arg_index != ARG_NONE)
336                       {
337                         int arg;
338
339                         if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
340                           abort ();
341                         arg = a.arg[dp->width_arg_index].a.a_int;
342                         if (arg < 0)
343                           {
344                             /* "A negative field width is taken as a '-' flag
345                                 followed by a positive field width."  */
346                             flags |= FLAG_LEFT;
347                             width = (unsigned int) (-arg);
348                           }
349                         else
350                           width = arg;
351                       }
352                     else
353                       {
354                         const CHAR_T *digitp = dp->width_start;
355
356                         do
357                           width = xsum (xtimes (width, 10), *digitp++ - '0');
358                         while (digitp != dp->width_end);
359                       }
360                     has_width = 1;
361                   }
362
363                 has_precision = 0;
364                 precision = 0;
365                 if (dp->precision_start != dp->precision_end)
366                   {
367                     if (dp->precision_arg_index != ARG_NONE)
368                       {
369                         int arg;
370
371                         if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
372                           abort ();
373                         arg = a.arg[dp->precision_arg_index].a.a_int;
374                         /* "A negative precision is taken as if the precision
375                             were omitted."  */
376                         if (arg >= 0)
377                           {
378                             precision = arg;
379                             has_precision = 1;
380                           }
381                       }
382                     else
383                       {
384                         const CHAR_T *digitp = dp->precision_start + 1;
385
386                         precision = 0;
387                         while (digitp != dp->precision_end)
388                           precision = xsum (xtimes (precision, 10), *digitp++ - '0');
389                         has_precision = 1;
390                       }
391                   }
392
393                 /* Allocate a temporary buffer of sufficient size.  */
394                 if (type == TYPE_LONGDOUBLE)
395                   tmp_length =
396                     (unsigned int) ((LDBL_DIG + 1)
397                                     * 0.831 /* decimal -> hexadecimal */
398                                    )
399                     + 1; /* turn floor into ceil */
400                 else
401                   tmp_length =
402                     (unsigned int) ((DBL_DIG + 1)
403                                     * 0.831 /* decimal -> hexadecimal */
404                                    )
405                     + 1; /* turn floor into ceil */
406                 if (tmp_length < precision)
407                   tmp_length = precision;
408                 /* Account for sign, decimal point etc. */
409                 tmp_length = xsum (tmp_length, 12);
410
411                 if (tmp_length < width)
412                   tmp_length = width;
413
414                 tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
415
416                 if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T))
417                   tmp = tmpbuf;
418                 else
419                   {
420                     size_t tmp_memsize = xtimes (tmp_length, sizeof (CHAR_T));
421
422                     if (size_overflow_p (tmp_memsize))
423                       /* Overflow, would lead to out of memory.  */
424                       goto out_of_memory;
425                     tmp = (CHAR_T *) malloc (tmp_memsize);
426                     if (tmp == NULL)
427                       /* Out of memory.  */
428                       goto out_of_memory;
429                   }
430
431                 pad_ptr = NULL;
432                 p = tmp;
433                 if (type == TYPE_LONGDOUBLE)
434                   {
435                     long double arg = a.arg[dp->arg_index].a.a_longdouble;
436
437                     if (isnanl (arg))
438                       {
439                         if (dp->conversion == 'A')
440                           {
441                             *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
442                           }
443                         else
444                           {
445                             *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
446                           }
447                       }
448                     else
449                       {
450                         int sign = 0;
451                         DECL_LONG_DOUBLE_ROUNDING
452
453                         BEGIN_LONG_DOUBLE_ROUNDING ();
454
455                         if (signbit (arg)) /* arg < 0.0L or negative zero */
456                           {
457                             sign = -1;
458                             arg = -arg;
459                           }
460
461                         if (sign < 0)
462                           *p++ = '-';
463                         else if (flags & FLAG_SHOWSIGN)
464                           *p++ = '+';
465                         else if (flags & FLAG_SPACE)
466                           *p++ = ' ';
467
468                         if (arg > 0.0L && arg + arg == arg)
469                           {
470                             if (dp->conversion == 'A')
471                               {
472                                 *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
473                               }
474                             else
475                               {
476                                 *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
477                               }
478                           }
479                         else
480                           {
481                             int exponent;
482                             long double mantissa;
483
484                             if (arg > 0.0L)
485                               mantissa = printf_frexpl (arg, &exponent);
486                             else
487                               {
488                                 exponent = 0;
489                                 mantissa = 0.0L;
490                               }
491
492                             if (has_precision
493                                 && precision < (unsigned int) ((LDBL_DIG + 1) * 0.831) + 1)
494                               {
495                                 /* Round the mantissa.  */
496                                 long double tail = mantissa;
497                                 size_t q;
498
499                                 for (q = precision; ; q--)
500                                   {
501                                     int digit = (int) tail;
502                                     tail -= digit;
503                                     if (q == 0)
504                                       {
505                                         if (digit & 1 ? tail >= 0.5L : tail > 0.5L)
506                                           tail = 1 - tail;
507                                         else
508                                           tail = - tail;
509                                         break;
510                                       }
511                                     tail *= 16.0L;
512                                   }
513                                 if (tail != 0.0L)
514                                   for (q = precision; q > 0; q--)
515                                     tail *= 0.0625L;
516                                 mantissa += tail;
517                               }
518
519                             *p++ = '0';
520                             *p++ = dp->conversion - 'A' + 'X';
521                             pad_ptr = p;
522                             {
523                               int digit;
524
525                               digit = (int) mantissa;
526                               mantissa -= digit;
527                               *p++ = '0' + digit;
528                               if ((flags & FLAG_ALT)
529                                   || mantissa > 0.0L || precision > 0)
530                                 {
531                                   *p++ = decimal_point_char ();
532                                   /* This loop terminates because we assume
533                                      that FLT_RADIX is a power of 2.  */
534                                   while (mantissa > 0.0L)
535                                     {
536                                       mantissa *= 16.0L;
537                                       digit = (int) mantissa;
538                                       mantissa -= digit;
539                                       *p++ = digit
540                                              + (digit < 10
541                                                 ? '0'
542                                                 : dp->conversion - 10);
543                                       if (precision > 0)
544                                         precision--;
545                                     }
546                                   while (precision > 0)
547                                     {
548                                       *p++ = '0';
549                                       precision--;
550                                     }
551                                 }
552                               }
553                               *p++ = dp->conversion - 'A' + 'P';
554 # if WIDE_CHAR_VERSION
555                               {
556                                 static const wchar_t decimal_format[] =
557                                   { '%', '+', 'd', '\0' };
558                                 SNPRINTF (p, 6 + 1, decimal_format, exponent);
559                               }
560 # else
561                               sprintf (p, "%+d", exponent);
562 # endif
563                               while (*p != '\0')
564                                 p++;
565                           }
566
567                         END_LONG_DOUBLE_ROUNDING ();
568                       }
569                   }
570                 else
571                   {
572                     double arg = a.arg[dp->arg_index].a.a_double;
573
574                     if (isnan (arg))
575                       {
576                         if (dp->conversion == 'A')
577                           {
578                             *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
579                           }
580                         else
581                           {
582                             *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
583                           }
584                       }
585                     else
586                       {
587                         int sign = 0;
588
589                         if (signbit (arg)) /* arg < 0.0 or negative zero */
590                           {
591                             sign = -1;
592                             arg = -arg;
593                           }
594
595                         if (sign < 0)
596                           *p++ = '-';
597                         else if (flags & FLAG_SHOWSIGN)
598                           *p++ = '+';
599                         else if (flags & FLAG_SPACE)
600                           *p++ = ' ';
601
602                         if (arg > 0.0 && arg + arg == arg)
603                           {
604                             if (dp->conversion == 'A')
605                               {
606                                 *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
607                               }
608                             else
609                               {
610                                 *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
611                               }
612                           }
613                         else
614                           {
615                             int exponent;
616                             double mantissa;
617
618                             if (arg > 0.0)
619                               mantissa = printf_frexp (arg, &exponent);
620                             else
621                               {
622                                 exponent = 0;
623                                 mantissa = 0.0;
624                               }
625
626                             if (has_precision
627                                 && precision < (unsigned int) ((DBL_DIG + 1) * 0.831) + 1)
628                               {
629                                 /* Round the mantissa.  */
630                                 double tail = mantissa;
631                                 size_t q;
632
633                                 for (q = precision; ; q--)
634                                   {
635                                     int digit = (int) tail;
636                                     tail -= digit;
637                                     if (q == 0)
638                                       {
639                                         if (digit & 1 ? tail >= 0.5 : tail > 0.5)
640                                           tail = 1 - tail;
641                                         else
642                                           tail = - tail;
643                                         break;
644                                       }
645                                     tail *= 16.0;
646                                   }
647                                 if (tail != 0.0)
648                                   for (q = precision; q > 0; q--)
649                                     tail *= 0.0625;
650                                 mantissa += tail;
651                               }
652
653                             *p++ = '0';
654                             *p++ = dp->conversion - 'A' + 'X';
655                             pad_ptr = p;
656                             {
657                               int digit;
658
659                               digit = (int) mantissa;
660                               mantissa -= digit;
661                               *p++ = '0' + digit;
662                               if ((flags & FLAG_ALT)
663                                   || mantissa > 0.0 || precision > 0)
664                                 {
665                                   *p++ = decimal_point_char ();
666                                   /* This loop terminates because we assume
667                                      that FLT_RADIX is a power of 2.  */
668                                   while (mantissa > 0.0)
669                                     {
670                                       mantissa *= 16.0;
671                                       digit = (int) mantissa;
672                                       mantissa -= digit;
673                                       *p++ = digit
674                                              + (digit < 10
675                                                 ? '0'
676                                                 : dp->conversion - 10);
677                                       if (precision > 0)
678                                         precision--;
679                                     }
680                                   while (precision > 0)
681                                     {
682                                       *p++ = '0';
683                                       precision--;
684                                     }
685                                 }
686                               }
687                               *p++ = dp->conversion - 'A' + 'P';
688 # if WIDE_CHAR_VERSION
689                               {
690                                 static const wchar_t decimal_format[] =
691                                   { '%', '+', 'd', '\0' };
692                                 SNPRINTF (p, 6 + 1, decimal_format, exponent);
693                               }
694 # else
695                               sprintf (p, "%+d", exponent);
696 # endif
697                               while (*p != '\0')
698                                 p++;
699                           }
700                       }
701                   }
702                 /* The generated string now extends from tmp to p, with the
703                    zero padding insertion point being at pad_ptr.  */
704                 if (has_width && p - tmp < width)
705                   {
706                     size_t pad = width - (p - tmp);
707                     CHAR_T *end = p + pad;
708
709                     if (flags & FLAG_LEFT)
710                       {
711                         /* Pad with spaces on the right.  */
712                         for (; pad > 0; pad--)
713                           *p++ = ' ';
714                       }
715                     else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
716                       {
717                         /* Pad with zeroes.  */
718                         CHAR_T *q = end;
719
720                         while (p > pad_ptr)
721                           *--q = *--p;
722                         for (; pad > 0; pad--)
723                           *p++ = '0';
724                       }
725                     else
726                       {
727                         /* Pad with spaces on the left.  */
728                         CHAR_T *q = end;
729
730                         while (p > tmp)
731                           *--q = *--p;
732                         for (; pad > 0; pad--)
733                           *p++ = ' ';
734                       }
735
736                     p = end;
737                   }
738
739                 {
740                   size_t count = p - tmp;
741
742                   if (count >= tmp_length)
743                     /* tmp_length was incorrectly calculated - fix the
744                        code above!  */
745                     abort ();
746
747                   /* Make room for the result.  */
748                   if (count >= allocated - length)
749                     {
750                       size_t n = xsum (length, count);
751
752                       ENSURE_ALLOCATION (n);
753                     }
754
755                   /* Append the result.  */
756                   memcpy (result + length, tmp, count * sizeof (CHAR_T));
757                   if (tmp != tmpbuf)
758                     free (tmp);
759                   length += count;
760                 }
761               }
762 #endif
763             else
764               {
765                 arg_type type = a.arg[dp->arg_index].type;
766                 int flags = dp->flags;
767 #if !USE_SNPRINTF || NEED_PRINTF_FLAG_ZERO
768                 int has_width;
769                 size_t width;
770 #endif
771 #if NEED_PRINTF_FLAG_ZERO
772                 int pad_ourselves;
773 #else
774 #               define pad_ourselves 0
775 #endif
776                 CHAR_T *fbp;
777                 unsigned int prefix_count;
778                 int prefixes[2];
779 #if !USE_SNPRINTF
780                 size_t tmp_length;
781                 CHAR_T tmpbuf[700];
782                 CHAR_T *tmp;
783 #endif
784
785 #if !USE_SNPRINTF || NEED_PRINTF_FLAG_ZERO
786                 has_width = 0;
787                 width = 0;
788                 if (dp->width_start != dp->width_end)
789                   {
790                     if (dp->width_arg_index != ARG_NONE)
791                       {
792                         int arg;
793
794                         if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
795                           abort ();
796                         arg = a.arg[dp->width_arg_index].a.a_int;
797                         if (arg < 0)
798                           {
799                             /* "A negative field width is taken as a '-' flag
800                                 followed by a positive field width."  */
801                             flags |= FLAG_LEFT;
802                             width = (unsigned int) (-arg);
803                           }
804                         else
805                           width = arg;
806                       }
807                     else
808                       {
809                         const CHAR_T *digitp = dp->width_start;
810
811                         do
812                           width = xsum (xtimes (width, 10), *digitp++ - '0');
813                         while (digitp != dp->width_end);
814                       }
815                     has_width = 1;
816                   }
817 #endif
818
819 #if !USE_SNPRINTF
820                 /* Allocate a temporary buffer of sufficient size for calling
821                    sprintf.  */
822                 {
823                   size_t precision;
824
825                   precision = 6;
826                   if (dp->precision_start != dp->precision_end)
827                     {
828                       if (dp->precision_arg_index != ARG_NONE)
829                         {
830                           int arg;
831
832                           if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
833                             abort ();
834                           arg = a.arg[dp->precision_arg_index].a.a_int;
835                           precision = (arg < 0 ? 0 : arg);
836                         }
837                       else
838                         {
839                           const CHAR_T *digitp = dp->precision_start + 1;
840
841                           precision = 0;
842                           while (digitp != dp->precision_end)
843                             precision = xsum (xtimes (precision, 10), *digitp++ - '0');
844                         }
845                     }
846
847                   switch (dp->conversion)
848                     {
849
850                     case 'd': case 'i': case 'u':
851 # if HAVE_LONG_LONG_INT
852                       if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
853                         tmp_length =
854                           (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
855                                           * 0.30103 /* binary -> decimal */
856                                          )
857                           + 1; /* turn floor into ceil */
858                       else
859 # endif
860                       if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
861                         tmp_length =
862                           (unsigned int) (sizeof (unsigned long) * CHAR_BIT
863                                           * 0.30103 /* binary -> decimal */
864                                          )
865                           + 1; /* turn floor into ceil */
866                       else
867                         tmp_length =
868                           (unsigned int) (sizeof (unsigned int) * CHAR_BIT
869                                           * 0.30103 /* binary -> decimal */
870                                          )
871                           + 1; /* turn floor into ceil */
872                       if (tmp_length < precision)
873                         tmp_length = precision;
874                       /* Multiply by 2, as an estimate for FLAG_GROUP.  */
875                       tmp_length = xsum (tmp_length, tmp_length);
876                       /* Add 1, to account for a leading sign.  */
877                       tmp_length = xsum (tmp_length, 1);
878                       break;
879
880                     case 'o':
881 # if HAVE_LONG_LONG_INT
882                       if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
883                         tmp_length =
884                           (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
885                                           * 0.333334 /* binary -> octal */
886                                          )
887                           + 1; /* turn floor into ceil */
888                       else
889 # endif
890                       if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
891                         tmp_length =
892                           (unsigned int) (sizeof (unsigned long) * CHAR_BIT
893                                           * 0.333334 /* binary -> octal */
894                                          )
895                           + 1; /* turn floor into ceil */
896                       else
897                         tmp_length =
898                           (unsigned int) (sizeof (unsigned int) * CHAR_BIT
899                                           * 0.333334 /* binary -> octal */
900                                          )
901                           + 1; /* turn floor into ceil */
902                       if (tmp_length < precision)
903                         tmp_length = precision;
904                       /* Add 1, to account for a leading sign.  */
905                       tmp_length = xsum (tmp_length, 1);
906                       break;
907
908                     case 'x': case 'X':
909 # if HAVE_LONG_LONG_INT
910                       if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
911                         tmp_length =
912                           (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
913                                           * 0.25 /* binary -> hexadecimal */
914                                          )
915                           + 1; /* turn floor into ceil */
916                       else
917 # endif
918                       if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
919                         tmp_length =
920                           (unsigned int) (sizeof (unsigned long) * CHAR_BIT
921                                           * 0.25 /* binary -> hexadecimal */
922                                          )
923                           + 1; /* turn floor into ceil */
924                       else
925                         tmp_length =
926                           (unsigned int) (sizeof (unsigned int) * CHAR_BIT
927                                           * 0.25 /* binary -> hexadecimal */
928                                          )
929                           + 1; /* turn floor into ceil */
930                       if (tmp_length < precision)
931                         tmp_length = precision;
932                       /* Add 2, to account for a leading sign or alternate form.  */
933                       tmp_length = xsum (tmp_length, 2);
934                       break;
935
936                     case 'f': case 'F':
937                       if (type == TYPE_LONGDOUBLE)
938                         tmp_length =
939                           (unsigned int) (LDBL_MAX_EXP
940                                           * 0.30103 /* binary -> decimal */
941                                           * 2 /* estimate for FLAG_GROUP */
942                                          )
943                           + 1 /* turn floor into ceil */
944                           + 10; /* sign, decimal point etc. */
945                       else
946                         tmp_length =
947                           (unsigned int) (DBL_MAX_EXP
948                                           * 0.30103 /* binary -> decimal */
949                                           * 2 /* estimate for FLAG_GROUP */
950                                          )
951                           + 1 /* turn floor into ceil */
952                           + 10; /* sign, decimal point etc. */
953                       tmp_length = xsum (tmp_length, precision);
954                       break;
955
956                     case 'e': case 'E': case 'g': case 'G':
957                       tmp_length =
958                         12; /* sign, decimal point, exponent etc. */
959                       tmp_length = xsum (tmp_length, precision);
960                       break;
961
962                     case 'a': case 'A':
963                       if (type == TYPE_LONGDOUBLE)
964                         tmp_length =
965                           (unsigned int) (LDBL_DIG
966                                           * 0.831 /* decimal -> hexadecimal */
967                                          )
968                           + 1; /* turn floor into ceil */
969                       else
970                         tmp_length =
971                           (unsigned int) (DBL_DIG
972                                           * 0.831 /* decimal -> hexadecimal */
973                                          )
974                           + 1; /* turn floor into ceil */
975                       if (tmp_length < precision)
976                         tmp_length = precision;
977                       /* Account for sign, decimal point etc. */
978                       tmp_length = xsum (tmp_length, 12);
979                       break;
980
981                     case 'c':
982 # if HAVE_WINT_T && !WIDE_CHAR_VERSION
983                       if (type == TYPE_WIDE_CHAR)
984                         tmp_length = MB_CUR_MAX;
985                       else
986 # endif
987                         tmp_length = 1;
988                       break;
989
990                     case 's':
991 # if HAVE_WCHAR_T
992                       if (type == TYPE_WIDE_STRING)
993                         {
994                           tmp_length =
995                             local_wcslen (a.arg[dp->arg_index].a.a_wide_string);
996
997 #  if !WIDE_CHAR_VERSION
998                           tmp_length = xtimes (tmp_length, MB_CUR_MAX);
999 #  endif
1000                         }
1001                       else
1002 # endif
1003                         tmp_length = strlen (a.arg[dp->arg_index].a.a_string);
1004                       break;
1005
1006                     case 'p':
1007                       tmp_length =
1008                         (unsigned int) (sizeof (void *) * CHAR_BIT
1009                                         * 0.25 /* binary -> hexadecimal */
1010                                        )
1011                           + 1 /* turn floor into ceil */
1012                           + 2; /* account for leading 0x */
1013                       break;
1014
1015                     default:
1016                       abort ();
1017                     }
1018
1019                   if (tmp_length < width)
1020                     tmp_length = width;
1021
1022                   tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
1023                 }
1024
1025                 if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T))
1026                   tmp = tmpbuf;
1027                 else
1028                   {
1029                     size_t tmp_memsize = xtimes (tmp_length, sizeof (CHAR_T));
1030
1031                     if (size_overflow_p (tmp_memsize))
1032                       /* Overflow, would lead to out of memory.  */
1033                       goto out_of_memory;
1034                     tmp = (CHAR_T *) malloc (tmp_memsize);
1035                     if (tmp == NULL)
1036                       /* Out of memory.  */
1037                       goto out_of_memory;
1038                   }
1039 #endif
1040
1041                 /* Decide whether to perform the padding ourselves.  */
1042 #if NEED_PRINTF_FLAG_ZERO
1043                 switch (dp->conversion)
1044                   {
1045                   case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
1046                   case 'a': case 'A':
1047                     pad_ourselves = 1;
1048                     break;
1049                   default:
1050                     pad_ourselves = 0;
1051                     break;
1052                   }
1053 #endif
1054
1055                 /* Construct the format string for calling snprintf or
1056                    sprintf.  */
1057                 fbp = buf;
1058                 *fbp++ = '%';
1059 #if NEED_PRINTF_FLAG_GROUPING
1060                 /* The underlying implementation doesn't support the ' flag.
1061                    Produce no grouping characters in this case; this is
1062                    acceptable because the grouping is locale dependent.  */
1063 #else
1064                 if (flags & FLAG_GROUP)
1065                   *fbp++ = '\'';
1066 #endif
1067                 if (flags & FLAG_LEFT)
1068                   *fbp++ = '-';
1069                 if (flags & FLAG_SHOWSIGN)
1070                   *fbp++ = '+';
1071                 if (flags & FLAG_SPACE)
1072                   *fbp++ = ' ';
1073                 if (flags & FLAG_ALT)
1074                   *fbp++ = '#';
1075                 if (!pad_ourselves)
1076                   {
1077                     if (flags & FLAG_ZERO)
1078                       *fbp++ = '0';
1079                     if (dp->width_start != dp->width_end)
1080                       {
1081                         size_t n = dp->width_end - dp->width_start;
1082                         memcpy (fbp, dp->width_start, n * sizeof (CHAR_T));
1083                         fbp += n;
1084                       }
1085                   }
1086                 if (dp->precision_start != dp->precision_end)
1087                   {
1088                     size_t n = dp->precision_end - dp->precision_start;
1089                     memcpy (fbp, dp->precision_start, n * sizeof (CHAR_T));
1090                     fbp += n;
1091                   }
1092
1093                 switch (type)
1094                   {
1095 #if HAVE_LONG_LONG_INT
1096                   case TYPE_LONGLONGINT:
1097                   case TYPE_ULONGLONGINT:
1098 # if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
1099                     *fbp++ = 'I';
1100                     *fbp++ = '6';
1101                     *fbp++ = '4';
1102                     break;
1103 # else
1104                     *fbp++ = 'l';
1105                     /*FALLTHROUGH*/
1106 # endif
1107 #endif
1108                   case TYPE_LONGINT:
1109                   case TYPE_ULONGINT:
1110 #if HAVE_WINT_T
1111                   case TYPE_WIDE_CHAR:
1112 #endif
1113 #if HAVE_WCHAR_T
1114                   case TYPE_WIDE_STRING:
1115 #endif
1116                     *fbp++ = 'l';
1117                     break;
1118                   case TYPE_LONGDOUBLE:
1119                     *fbp++ = 'L';
1120                     break;
1121                   default:
1122                     break;
1123                   }
1124 #if NEED_PRINTF_DIRECTIVE_F
1125                 if (dp->conversion == 'F')
1126                   *fbp = 'f';
1127                 else
1128 #endif
1129                   *fbp = dp->conversion;
1130 #if USE_SNPRINTF
1131                 fbp[1] = '%';
1132                 fbp[2] = 'n';
1133                 fbp[3] = '\0';
1134 #else
1135                 fbp[1] = '\0';
1136 #endif
1137
1138                 /* Construct the arguments for calling snprintf or sprintf.  */
1139                 prefix_count = 0;
1140                 if (!pad_ourselves && dp->width_arg_index != ARG_NONE)
1141                   {
1142                     if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
1143                       abort ();
1144                     prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int;
1145                   }
1146                 if (dp->precision_arg_index != ARG_NONE)
1147                   {
1148                     if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
1149                       abort ();
1150                     prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int;
1151                   }
1152
1153 #if USE_SNPRINTF
1154                 /* Prepare checking whether snprintf returns the count
1155                    via %n.  */
1156                 ENSURE_ALLOCATION (xsum (length, 1));
1157                 result[length] = '\0';
1158 #endif
1159
1160                 for (;;)
1161                   {
1162                     size_t maxlen;
1163                     int count;
1164                     int retcount;
1165
1166                     maxlen = allocated - length;
1167                     count = -1;
1168                     retcount = 0;
1169
1170 #if USE_SNPRINTF
1171                     /* SNPRINTF can fail if maxlen > INT_MAX.  */
1172                     if (maxlen > INT_MAX)
1173                       goto overflow;
1174 # define SNPRINTF_BUF(arg) \
1175                     switch (prefix_count)                                   \
1176                       {                                                     \
1177                       case 0:                                               \
1178                         retcount = SNPRINTF (result + length, maxlen, buf,  \
1179                                              arg, &count);                  \
1180                         break;                                              \
1181                       case 1:                                               \
1182                         retcount = SNPRINTF (result + length, maxlen, buf,  \
1183                                              prefixes[0], arg, &count);     \
1184                         break;                                              \
1185                       case 2:                                               \
1186                         retcount = SNPRINTF (result + length, maxlen, buf,  \
1187                                              prefixes[0], prefixes[1], arg, \
1188                                              &count);                       \
1189                         break;                                              \
1190                       default:                                              \
1191                         abort ();                                           \
1192                       }
1193 #else
1194 # define SNPRINTF_BUF(arg) \
1195                     switch (prefix_count)                                   \
1196                       {                                                     \
1197                       case 0:                                               \
1198                         count = sprintf (tmp, buf, arg);                    \
1199                         break;                                              \
1200                       case 1:                                               \
1201                         count = sprintf (tmp, buf, prefixes[0], arg);       \
1202                         break;                                              \
1203                       case 2:                                               \
1204                         count = sprintf (tmp, buf, prefixes[0], prefixes[1],\
1205                                          arg);                              \
1206                         break;                                              \
1207                       default:                                              \
1208                         abort ();                                           \
1209                       }
1210 #endif
1211
1212                     switch (type)
1213                       {
1214                       case TYPE_SCHAR:
1215                         {
1216                           int arg = a.arg[dp->arg_index].a.a_schar;
1217                           SNPRINTF_BUF (arg);
1218                         }
1219                         break;
1220                       case TYPE_UCHAR:
1221                         {
1222                           unsigned int arg = a.arg[dp->arg_index].a.a_uchar;
1223                           SNPRINTF_BUF (arg);
1224                         }
1225                         break;
1226                       case TYPE_SHORT:
1227                         {
1228                           int arg = a.arg[dp->arg_index].a.a_short;
1229                           SNPRINTF_BUF (arg);
1230                         }
1231                         break;
1232                       case TYPE_USHORT:
1233                         {
1234                           unsigned int arg = a.arg[dp->arg_index].a.a_ushort;
1235                           SNPRINTF_BUF (arg);
1236                         }
1237                         break;
1238                       case TYPE_INT:
1239                         {
1240                           int arg = a.arg[dp->arg_index].a.a_int;
1241                           SNPRINTF_BUF (arg);
1242                         }
1243                         break;
1244                       case TYPE_UINT:
1245                         {
1246                           unsigned int arg = a.arg[dp->arg_index].a.a_uint;
1247                           SNPRINTF_BUF (arg);
1248                         }
1249                         break;
1250                       case TYPE_LONGINT:
1251                         {
1252                           long int arg = a.arg[dp->arg_index].a.a_longint;
1253                           SNPRINTF_BUF (arg);
1254                         }
1255                         break;
1256                       case TYPE_ULONGINT:
1257                         {
1258                           unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint;
1259                           SNPRINTF_BUF (arg);
1260                         }
1261                         break;
1262 #if HAVE_LONG_LONG_INT
1263                       case TYPE_LONGLONGINT:
1264                         {
1265                           long long int arg = a.arg[dp->arg_index].a.a_longlongint;
1266                           SNPRINTF_BUF (arg);
1267                         }
1268                         break;
1269                       case TYPE_ULONGLONGINT:
1270                         {
1271                           unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint;
1272                           SNPRINTF_BUF (arg);
1273                         }
1274                         break;
1275 #endif
1276                       case TYPE_DOUBLE:
1277                         {
1278                           double arg = a.arg[dp->arg_index].a.a_double;
1279                           SNPRINTF_BUF (arg);
1280                         }
1281                         break;
1282                       case TYPE_LONGDOUBLE:
1283                         {
1284                           long double arg = a.arg[dp->arg_index].a.a_longdouble;
1285                           SNPRINTF_BUF (arg);
1286                         }
1287                         break;
1288                       case TYPE_CHAR:
1289                         {
1290                           int arg = a.arg[dp->arg_index].a.a_char;
1291                           SNPRINTF_BUF (arg);
1292                         }
1293                         break;
1294 #if HAVE_WINT_T
1295                       case TYPE_WIDE_CHAR:
1296                         {
1297                           wint_t arg = a.arg[dp->arg_index].a.a_wide_char;
1298                           SNPRINTF_BUF (arg);
1299                         }
1300                         break;
1301 #endif
1302                       case TYPE_STRING:
1303                         {
1304                           const char *arg = a.arg[dp->arg_index].a.a_string;
1305                           SNPRINTF_BUF (arg);
1306                         }
1307                         break;
1308 #if HAVE_WCHAR_T
1309                       case TYPE_WIDE_STRING:
1310                         {
1311                           const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
1312                           SNPRINTF_BUF (arg);
1313                         }
1314                         break;
1315 #endif
1316                       case TYPE_POINTER:
1317                         {
1318                           void *arg = a.arg[dp->arg_index].a.a_pointer;
1319                           SNPRINTF_BUF (arg);
1320                         }
1321                         break;
1322                       default:
1323                         abort ();
1324                       }
1325
1326 #if USE_SNPRINTF
1327                     /* Portability: Not all implementations of snprintf()
1328                        are ISO C 99 compliant.  Determine the number of
1329                        bytes that snprintf() has produced or would have
1330                        produced.  */
1331                     if (count >= 0)
1332                       {
1333                         /* Verify that snprintf() has NUL-terminated its
1334                            result.  */
1335                         if (count < maxlen && result[length + count] != '\0')
1336                           abort ();
1337                         /* Portability hack.  */
1338                         if (retcount > count)
1339                           count = retcount;
1340                       }
1341                     else
1342                       {
1343                         /* snprintf() doesn't understand the '%n'
1344                            directive.  */
1345                         if (fbp[1] != '\0')
1346                           {
1347                             /* Don't use the '%n' directive; instead, look
1348                                at the snprintf() return value.  */
1349                             fbp[1] = '\0';
1350                             continue;
1351                           }
1352                         else
1353                           {
1354                             /* Look at the snprintf() return value.  */
1355                             if (retcount < 0)
1356                               {
1357                                 /* HP-UX 10.20 snprintf() is doubly deficient:
1358                                    It doesn't understand the '%n' directive,
1359                                    *and* it returns -1 (rather than the length
1360                                    that would have been required) when the
1361                                    buffer is too small.  */
1362                                 size_t bigger_need =
1363                                   xsum (xtimes (allocated, 2), 12);
1364                                 ENSURE_ALLOCATION (bigger_need);
1365                                 continue;
1366                               }
1367                             else
1368                               count = retcount;
1369                           }
1370                       }
1371 #endif
1372
1373                     /* Attempt to handle failure.  */
1374                     if (count < 0)
1375                       {
1376                         if (!(result == resultbuf || result == NULL))
1377                           free (result);
1378                         if (buf_malloced != NULL)
1379                           free (buf_malloced);
1380                         CLEANUP ();
1381                         errno = EINVAL;
1382                         return NULL;
1383                       }
1384
1385                     /* Perform padding.  */
1386 #if NEED_PRINTF_FLAG_ZERO
1387                     if (pad_ourselves && has_width && count < width)
1388                       {
1389 # if USE_SNPRINTF
1390                         /* Make room for the result.  */
1391                         if (width >= maxlen)
1392                           {
1393                             /* Need at least width bytes.  But allocate
1394                                proportionally, to avoid looping eternally if
1395                                snprintf() reports a too small count.  */
1396                             size_t n =
1397                               xmax (xsum (length, width),
1398                                     xtimes (allocated, 2));
1399
1400                             length += count;
1401                             ENSURE_ALLOCATION (n);
1402                             length -= count;
1403                             maxlen = allocated - length; /* >= width */
1404                           }
1405 # endif
1406                         {
1407 # if USE_SNPRINTF
1408                           CHAR_T * const rp = result + length;
1409 # else
1410                           CHAR_T * const rp = tmp;
1411 # endif
1412                           CHAR_T *p = rp + count;
1413                           size_t pad = width - count;
1414                           CHAR_T *end = p + pad;
1415                           CHAR_T *pad_ptr = (*rp == '-' ? rp + 1 : rp);
1416                           /* No zero-padding of "inf" and "nan".  */
1417                           if ((*pad_ptr >= 'A' && *pad_ptr <= 'Z')
1418                               || (*pad_ptr >= 'a' && *pad_ptr <= 'z'))
1419                             pad_ptr = NULL;
1420                           /* The generated string now extends from rp to p,
1421                              with the zero padding insertion point being at
1422                              pad_ptr.  */
1423
1424                           if (flags & FLAG_LEFT)
1425                             {
1426                               /* Pad with spaces on the right.  */
1427                               for (; pad > 0; pad--)
1428                                 *p++ = ' ';
1429                             }
1430                           else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
1431                             {
1432                               /* Pad with zeroes.  */
1433                               CHAR_T *q = end;
1434
1435                               while (p > pad_ptr)
1436                                 *--q = *--p;
1437                               for (; pad > 0; pad--)
1438                                 *p++ = '0';
1439                             }
1440                           else
1441                             {
1442                               /* Pad with spaces on the left.  */
1443                               CHAR_T *q = end;
1444
1445                               while (p > rp)
1446                                 *--q = *--p;
1447                               for (; pad > 0; pad--)
1448                                 *p++ = ' ';
1449                             }
1450
1451                           count = width; /* = count + pad = end - rp */
1452                         }
1453                       }
1454 #endif
1455
1456 #if !USE_SNPRINTF
1457                     if (count >= tmp_length)
1458                       /* tmp_length was incorrectly calculated - fix the
1459                          code above!  */
1460                       abort ();
1461 #endif
1462
1463                     /* Make room for the result.  */
1464                     if (count >= maxlen)
1465                       {
1466                         /* Need at least count bytes.  But allocate
1467                            proportionally, to avoid looping eternally if
1468                            snprintf() reports a too small count.  */
1469                         size_t n =
1470                           xmax (xsum (length, count), xtimes (allocated, 2));
1471
1472                         ENSURE_ALLOCATION (n);
1473 #if USE_SNPRINTF
1474                         continue;
1475 #endif
1476                       }
1477
1478 #if USE_SNPRINTF
1479                     /* The snprintf() result did fit.  */
1480 #else
1481                     /* Append the sprintf() result.  */
1482                     memcpy (result + length, tmp, count * sizeof (CHAR_T));
1483                     if (tmp != tmpbuf)
1484                       free (tmp);
1485 #endif
1486
1487 #if NEED_PRINTF_DIRECTIVE_F
1488                     if (dp->conversion == 'F')
1489                       {
1490                         /* Convert the %f result to upper case for %F.  */
1491                         CHAR_T *rp = result + length;
1492                         size_t rc;
1493                         for (rc = count; rc > 0; rc--, rp++)
1494                           if (*rp >= 'a' && *rp <= 'z')
1495                             *rp = *rp - 'a' + 'A';
1496                       }
1497 #endif
1498
1499                     length += count;
1500                     break;
1501                   }
1502               }
1503           }
1504       }
1505
1506     /* Add the final NUL.  */
1507     ENSURE_ALLOCATION (xsum (length, 1));
1508     result[length] = '\0';
1509
1510     if (result != resultbuf && length + 1 < allocated)
1511       {
1512         /* Shrink the allocated memory if possible.  */
1513         CHAR_T *memory;
1514
1515         memory = (CHAR_T *) realloc (result, (length + 1) * sizeof (CHAR_T));
1516         if (memory != NULL)
1517           result = memory;
1518       }
1519
1520     if (buf_malloced != NULL)
1521       free (buf_malloced);
1522     CLEANUP ();
1523     *lengthp = length;
1524     /* Note that we can produce a big string of a length > INT_MAX.  POSIX
1525        says that snprintf() fails with errno = EOVERFLOW in this case, but
1526        that's only because snprintf() returns an 'int'.  This function does
1527        not have this limitation.  */
1528     return result;
1529
1530   overflow:
1531     if (!(result == resultbuf || result == NULL))
1532       free (result);
1533     if (buf_malloced != NULL)
1534       free (buf_malloced);
1535     CLEANUP ();
1536     errno = EOVERFLOW;
1537     return NULL;
1538
1539   out_of_memory:
1540     if (!(result == resultbuf || result == NULL))
1541       free (result);
1542     if (buf_malloced != NULL)
1543       free (buf_malloced);
1544   out_of_memory_1:
1545     CLEANUP ();
1546     errno = ENOMEM;
1547     return NULL;
1548   }
1549 }
1550
1551 #undef SNPRINTF
1552 #undef USE_SNPRINTF
1553 #undef PRINTF_PARSE
1554 #undef DIRECTIVES
1555 #undef DIRECTIVE
1556 #undef CHAR_T
1557 #undef VASNPRINTF