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