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