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