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