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