Back to index

nagios-plugins  1.4.16
vasnprintf.c
Go to the documentation of this file.
00001 /* vsprintf with automatic memory allocation.
00002    Copyright (C) 1999, 2002-2010 Free Software Foundation, Inc.
00003 
00004    This program is free software; you can redistribute it and/or modify
00005    it under the terms of the GNU General Public License as published by
00006    the Free Software Foundation; either version 3, or (at your option)
00007    any later version.
00008 
00009    This program is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012    GNU General Public License for more details.
00013 
00014    You should have received a copy of the GNU General Public License along
00015    with this program; if not, write to the Free Software Foundation,
00016    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
00017 
00018 /* This file can be parametrized with the following macros:
00019      VASNPRINTF         The name of the function being defined.
00020      FCHAR_T            The element type of the format string.
00021      DCHAR_T            The element type of the destination (result) string.
00022      FCHAR_T_ONLY_ASCII Set to 1 to enable verification that all characters
00023                         in the format string are ASCII. MUST be set if
00024                         FCHAR_T and DCHAR_T are not the same type.
00025      DIRECTIVE          Structure denoting a format directive.
00026                         Depends on FCHAR_T.
00027      DIRECTIVES         Structure denoting the set of format directives of a
00028                         format string.  Depends on FCHAR_T.
00029      PRINTF_PARSE       Function that parses a format string.
00030                         Depends on FCHAR_T.
00031      DCHAR_CPY          memcpy like function for DCHAR_T[] arrays.
00032      DCHAR_SET          memset like function for DCHAR_T[] arrays.
00033      DCHAR_MBSNLEN      mbsnlen like function for DCHAR_T[] arrays.
00034      SNPRINTF           The system's snprintf (or similar) function.
00035                         This may be either snprintf or swprintf.
00036      TCHAR_T            The element type of the argument and result string
00037                         of the said SNPRINTF function.  This may be either
00038                         char or wchar_t.  The code exploits that
00039                         sizeof (TCHAR_T) | sizeof (DCHAR_T) and
00040                         alignof (TCHAR_T) <= alignof (DCHAR_T).
00041      DCHAR_IS_TCHAR     Set to 1 if DCHAR_T and TCHAR_T are the same type.
00042      DCHAR_CONV_FROM_ENCODING A function to convert from char[] to DCHAR[].
00043      DCHAR_IS_UINT8_T   Set to 1 if DCHAR_T is uint8_t.
00044      DCHAR_IS_UINT16_T  Set to 1 if DCHAR_T is uint16_t.
00045      DCHAR_IS_UINT32_T  Set to 1 if DCHAR_T is uint32_t.  */
00046 
00047 /* Tell glibc's <stdio.h> to provide a prototype for snprintf().
00048    This must come before <config.h> because <config.h> may include
00049    <features.h>, and once <features.h> has been included, it's too late.  */
00050 #ifndef _GNU_SOURCE
00051 # define _GNU_SOURCE    1
00052 #endif
00053 
00054 #ifndef VASNPRINTF
00055 # include <config.h>
00056 #endif
00057 #ifndef IN_LIBINTL
00058 # include <alloca.h>
00059 #endif
00060 
00061 /* Specification.  */
00062 #ifndef VASNPRINTF
00063 # if WIDE_CHAR_VERSION
00064 #  include "vasnwprintf.h"
00065 # else
00066 #  include "vasnprintf.h"
00067 # endif
00068 #endif
00069 
00070 #include <locale.h>     /* localeconv() */
00071 #include <stdio.h>      /* snprintf(), sprintf() */
00072 #include <stdlib.h>     /* abort(), malloc(), realloc(), free() */
00073 #include <string.h>     /* memcpy(), strlen() */
00074 #include <errno.h>      /* errno */
00075 #include <limits.h>     /* CHAR_BIT */
00076 #include <float.h>      /* DBL_MAX_EXP, LDBL_MAX_EXP */
00077 #if HAVE_NL_LANGINFO
00078 # include <langinfo.h>
00079 #endif
00080 #ifndef VASNPRINTF
00081 # if WIDE_CHAR_VERSION
00082 #  include "wprintf-parse.h"
00083 # else
00084 #  include "printf-parse.h"
00085 # endif
00086 #endif
00087 
00088 /* Checked size_t computations.  */
00089 #include "xsize.h"
00090 
00091 #if (NEED_PRINTF_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL
00092 # include <math.h>
00093 # include "float+.h"
00094 #endif
00095 
00096 #if (NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL
00097 # include <math.h>
00098 # include "isnand-nolibm.h"
00099 #endif
00100 
00101 #if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE) && !defined IN_LIBINTL
00102 # include <math.h>
00103 # include "isnanl-nolibm.h"
00104 # include "fpucw.h"
00105 #endif
00106 
00107 #if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL
00108 # include <math.h>
00109 # include "isnand-nolibm.h"
00110 # include "printf-frexp.h"
00111 #endif
00112 
00113 #if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL
00114 # include <math.h>
00115 # include "isnanl-nolibm.h"
00116 # include "printf-frexpl.h"
00117 # include "fpucw.h"
00118 #endif
00119 
00120 /* Default parameters.  */
00121 #ifndef VASNPRINTF
00122 # if WIDE_CHAR_VERSION
00123 #  define VASNPRINTF vasnwprintf
00124 #  define FCHAR_T wchar_t
00125 #  define DCHAR_T wchar_t
00126 #  define TCHAR_T wchar_t
00127 #  define DCHAR_IS_TCHAR 1
00128 #  define DIRECTIVE wchar_t_directive
00129 #  define DIRECTIVES wchar_t_directives
00130 #  define PRINTF_PARSE wprintf_parse
00131 #  define DCHAR_CPY wmemcpy
00132 #  define DCHAR_SET wmemset
00133 # else
00134 #  define VASNPRINTF vasnprintf
00135 #  define FCHAR_T char
00136 #  define DCHAR_T char
00137 #  define TCHAR_T char
00138 #  define DCHAR_IS_TCHAR 1
00139 #  define DIRECTIVE char_directive
00140 #  define DIRECTIVES char_directives
00141 #  define PRINTF_PARSE printf_parse
00142 #  define DCHAR_CPY memcpy
00143 #  define DCHAR_SET memset
00144 # endif
00145 #endif
00146 #if WIDE_CHAR_VERSION
00147   /* TCHAR_T is wchar_t.  */
00148 # define USE_SNPRINTF 1
00149 # if HAVE_DECL__SNWPRINTF
00150    /* On Windows, the function swprintf() has a different signature than
00151       on Unix; we use the function _snwprintf() or - on mingw - snwprintf()
00152       instead.  The mingw function snwprintf() has fewer bugs than the
00153       MSVCRT function _snwprintf(), so prefer that.  */
00154 #  if defined __MINGW32__
00155 #   define SNPRINTF snwprintf
00156 #  else
00157 #   define SNPRINTF _snwprintf
00158 #  endif
00159 # else
00160    /* Unix.  */
00161 #  define SNPRINTF swprintf
00162 # endif
00163 #else
00164   /* TCHAR_T is char.  */
00165   /* Use snprintf if it exists under the name 'snprintf' or '_snprintf'.
00166      But don't use it on BeOS, since BeOS snprintf produces no output if the
00167      size argument is >= 0x3000000.
00168      Also don't use it on Linux libc5, since there snprintf with size = 1
00169      writes any output without bounds, like sprintf.  */
00170 # if (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF) && !defined __BEOS__ && !(__GNU_LIBRARY__ == 1)
00171 #  define USE_SNPRINTF 1
00172 # else
00173 #  define USE_SNPRINTF 0
00174 # endif
00175 # if HAVE_DECL__SNPRINTF
00176    /* Windows.  The mingw function snprintf() has fewer bugs than the MSVCRT
00177       function _snprintf(), so prefer that.  */
00178 #  if defined __MINGW32__
00179 #   define SNPRINTF snprintf
00180     /* Here we need to call the native snprintf, not rpl_snprintf.  */
00181 #   undef snprintf
00182 #  else
00183 #   define SNPRINTF _snprintf
00184 #  endif
00185 # else
00186    /* Unix.  */
00187 #  define SNPRINTF snprintf
00188    /* Here we need to call the native snprintf, not rpl_snprintf.  */
00189 #  undef snprintf
00190 # endif
00191 #endif
00192 /* Here we need to call the native sprintf, not rpl_sprintf.  */
00193 #undef sprintf
00194 
00195 /* GCC >= 4.0 with -Wall emits unjustified "... may be used uninitialized"
00196    warnings in this file.  Use -Dlint to suppress them.  */
00197 #ifdef lint
00198 # define IF_LINT(Code) Code
00199 #else
00200 # define IF_LINT(Code) /* empty */
00201 #endif
00202 
00203 /* Avoid some warnings from "gcc -Wshadow".
00204    This file doesn't use the exp() and remainder() functions.  */
00205 #undef exp
00206 #define exp expo
00207 #undef remainder
00208 #define remainder rem
00209 
00210 #if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && !WIDE_CHAR_VERSION
00211 # if (HAVE_STRNLEN && !defined _AIX)
00212 #  define local_strnlen strnlen
00213 # else
00214 #  ifndef local_strnlen_defined
00215 #   define local_strnlen_defined 1
00216 static size_t
00217 local_strnlen (const char *string, size_t maxlen)
00218 {
00219   const char *end = memchr (string, '\0', maxlen);
00220   return end ? (size_t) (end - string) : maxlen;
00221 }
00222 #  endif
00223 # endif
00224 #endif
00225 
00226 #if (((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && WIDE_CHAR_VERSION) || ((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && !WIDE_CHAR_VERSION && DCHAR_IS_TCHAR)) && HAVE_WCHAR_T
00227 # if HAVE_WCSLEN
00228 #  define local_wcslen wcslen
00229 # else
00230    /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid
00231       a dependency towards this library, here is a local substitute.
00232       Define this substitute only once, even if this file is included
00233       twice in the same compilation unit.  */
00234 #  ifndef local_wcslen_defined
00235 #   define local_wcslen_defined 1
00236 static size_t
00237 local_wcslen (const wchar_t *s)
00238 {
00239   const wchar_t *ptr;
00240 
00241   for (ptr = s; *ptr != (wchar_t) 0; ptr++)
00242     ;
00243   return ptr - s;
00244 }
00245 #  endif
00246 # endif
00247 #endif
00248 
00249 #if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && HAVE_WCHAR_T && WIDE_CHAR_VERSION
00250 # if HAVE_WCSNLEN
00251 #  define local_wcsnlen wcsnlen
00252 # else
00253 #  ifndef local_wcsnlen_defined
00254 #   define local_wcsnlen_defined 1
00255 static size_t
00256 local_wcsnlen (const wchar_t *s, size_t maxlen)
00257 {
00258   const wchar_t *ptr;
00259 
00260   for (ptr = s; maxlen > 0 && *ptr != (wchar_t) 0; ptr++, maxlen--)
00261     ;
00262   return ptr - s;
00263 }
00264 #  endif
00265 # endif
00266 #endif
00267 
00268 #if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL
00269 /* Determine the decimal-point character according to the current locale.  */
00270 # ifndef decimal_point_char_defined
00271 #  define decimal_point_char_defined 1
00272 static char
00273 decimal_point_char (void)
00274 {
00275   const char *point;
00276   /* Determine it in a multithread-safe way.  We know nl_langinfo is
00277      multithread-safe on glibc systems and MacOS X systems, but is not required
00278      to be multithread-safe by POSIX.  sprintf(), however, is multithread-safe.
00279      localeconv() is rarely multithread-safe.  */
00280 #  if HAVE_NL_LANGINFO && (__GLIBC__ || (defined __APPLE__ && defined __MACH__))
00281   point = nl_langinfo (RADIXCHAR);
00282 #  elif 1
00283   char pointbuf[5];
00284   sprintf (pointbuf, "%#.0f", 1.0);
00285   point = &pointbuf[1];
00286 #  else
00287   point = localeconv () -> decimal_point;
00288 #  endif
00289   /* The decimal point is always a single byte: either '.' or ','.  */
00290   return (point[0] != '\0' ? point[0] : '.');
00291 }
00292 # endif
00293 #endif
00294 
00295 #if NEED_PRINTF_INFINITE_DOUBLE && !NEED_PRINTF_DOUBLE && !defined IN_LIBINTL
00296 
00297 /* Equivalent to !isfinite(x) || x == 0, but does not require libm.  */
00298 static int
00299 is_infinite_or_zero (double x)
00300 {
00301   return isnand (x) || x + x == x;
00302 }
00303 
00304 #endif
00305 
00306 #if NEED_PRINTF_INFINITE_LONG_DOUBLE && !NEED_PRINTF_LONG_DOUBLE && !defined IN_LIBINTL
00307 
00308 /* Equivalent to !isfinite(x) || x == 0, but does not require libm.  */
00309 static int
00310 is_infinite_or_zerol (long double x)
00311 {
00312   return isnanl (x) || x + x == x;
00313 }
00314 
00315 #endif
00316 
00317 #if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL
00318 
00319 /* Converting 'long double' to decimal without rare rounding bugs requires
00320    real bignums.  We use the naming conventions of GNU gmp, but vastly simpler
00321    (and slower) algorithms.  */
00322 
00323 typedef unsigned int mp_limb_t;
00324 # define GMP_LIMB_BITS 32
00325 typedef int mp_limb_verify[2 * (sizeof (mp_limb_t) * CHAR_BIT == GMP_LIMB_BITS) - 1];
00326 
00327 typedef unsigned long long mp_twolimb_t;
00328 # define GMP_TWOLIMB_BITS 64
00329 typedef int mp_twolimb_verify[2 * (sizeof (mp_twolimb_t) * CHAR_BIT == GMP_TWOLIMB_BITS) - 1];
00330 
00331 /* Representation of a bignum >= 0.  */
00332 typedef struct
00333 {
00334   size_t nlimbs;
00335   mp_limb_t *limbs; /* Bits in little-endian order, allocated with malloc().  */
00336 } mpn_t;
00337 
00338 /* Compute the product of two bignums >= 0.
00339    Return the allocated memory in case of success, NULL in case of memory
00340    allocation failure.  */
00341 static void *
00342 multiply (mpn_t src1, mpn_t src2, mpn_t *dest)
00343 {
00344   const mp_limb_t *p1;
00345   const mp_limb_t *p2;
00346   size_t len1;
00347   size_t len2;
00348 
00349   if (src1.nlimbs <= src2.nlimbs)
00350     {
00351       len1 = src1.nlimbs;
00352       p1 = src1.limbs;
00353       len2 = src2.nlimbs;
00354       p2 = src2.limbs;
00355     }
00356   else
00357     {
00358       len1 = src2.nlimbs;
00359       p1 = src2.limbs;
00360       len2 = src1.nlimbs;
00361       p2 = src1.limbs;
00362     }
00363   /* Now 0 <= len1 <= len2.  */
00364   if (len1 == 0)
00365     {
00366       /* src1 or src2 is zero.  */
00367       dest->nlimbs = 0;
00368       dest->limbs = (mp_limb_t *) malloc (1);
00369     }
00370   else
00371     {
00372       /* Here 1 <= len1 <= len2.  */
00373       size_t dlen;
00374       mp_limb_t *dp;
00375       size_t k, i, j;
00376 
00377       dlen = len1 + len2;
00378       dp = (mp_limb_t *) malloc (dlen * sizeof (mp_limb_t));
00379       if (dp == NULL)
00380         return NULL;
00381       for (k = len2; k > 0; )
00382         dp[--k] = 0;
00383       for (i = 0; i < len1; i++)
00384         {
00385           mp_limb_t digit1 = p1[i];
00386           mp_twolimb_t carry = 0;
00387           for (j = 0; j < len2; j++)
00388             {
00389               mp_limb_t digit2 = p2[j];
00390               carry += (mp_twolimb_t) digit1 * (mp_twolimb_t) digit2;
00391               carry += dp[i + j];
00392               dp[i + j] = (mp_limb_t) carry;
00393               carry = carry >> GMP_LIMB_BITS;
00394             }
00395           dp[i + len2] = (mp_limb_t) carry;
00396         }
00397       /* Normalise.  */
00398       while (dlen > 0 && dp[dlen - 1] == 0)
00399         dlen--;
00400       dest->nlimbs = dlen;
00401       dest->limbs = dp;
00402     }
00403   return dest->limbs;
00404 }
00405 
00406 /* Compute the quotient of a bignum a >= 0 and a bignum b > 0.
00407    a is written as  a = q * b + r  with 0 <= r < b.  q is the quotient, r
00408    the remainder.
00409    Finally, round-to-even is performed: If r > b/2 or if r = b/2 and q is odd,
00410    q is incremented.
00411    Return the allocated memory in case of success, NULL in case of memory
00412    allocation failure.  */
00413 static void *
00414 divide (mpn_t a, mpn_t b, mpn_t *q)
00415 {
00416   /* Algorithm:
00417      First normalise a and b: a=[a[m-1],...,a[0]], b=[b[n-1],...,b[0]]
00418      with m>=0 and n>0 (in base beta = 2^GMP_LIMB_BITS).
00419      If m<n, then q:=0 and r:=a.
00420      If m>=n=1, perform a single-precision division:
00421        r:=0, j:=m,
00422        while j>0 do
00423          {Here (q[m-1]*beta^(m-1)+...+q[j]*beta^j) * b[0] + r*beta^j =
00424                = a[m-1]*beta^(m-1)+...+a[j]*beta^j und 0<=r<b[0]<beta}
00425          j:=j-1, r:=r*beta+a[j], q[j]:=floor(r/b[0]), r:=r-b[0]*q[j].
00426        Normalise [q[m-1],...,q[0]], yields q.
00427      If m>=n>1, perform a multiple-precision division:
00428        We have a/b < beta^(m-n+1).
00429        s:=intDsize-1-(highest bit in b[n-1]), 0<=s<intDsize.
00430        Shift a and b left by s bits, copying them. r:=a.
00431        r=[r[m],...,r[0]], b=[b[n-1],...,b[0]] with b[n-1]>=beta/2.
00432        For j=m-n,...,0: {Here 0 <= r < b*beta^(j+1).}
00433          Compute q* :
00434            q* := floor((r[j+n]*beta+r[j+n-1])/b[n-1]).
00435            In case of overflow (q* >= beta) set q* := beta-1.
00436            Compute c2 := ((r[j+n]*beta+r[j+n-1]) - q* * b[n-1])*beta + r[j+n-2]
00437            and c3 := b[n-2] * q*.
00438            {We have 0 <= c2 < 2*beta^2, even 0 <= c2 < beta^2 if no overflow
00439             occurred.  Furthermore 0 <= c3 < beta^2.
00440             If there was overflow and
00441             r[j+n]*beta+r[j+n-1] - q* * b[n-1] >= beta, i.e. c2 >= beta^2,
00442             the next test can be skipped.}
00443            While c3 > c2, {Here 0 <= c2 < c3 < beta^2}
00444              Put q* := q* - 1, c2 := c2 + b[n-1]*beta, c3 := c3 - b[n-2].
00445            If q* > 0:
00446              Put r := r - b * q* * beta^j. In detail:
00447                [r[n+j],...,r[j]] := [r[n+j],...,r[j]] - q* * [b[n-1],...,b[0]].
00448                hence: u:=0, for i:=0 to n-1 do
00449                               u := u + q* * b[i],
00450                               r[j+i]:=r[j+i]-(u mod beta) (+ beta, if carry),
00451                               u:=u div beta (+ 1, if carry in subtraction)
00452                       r[n+j]:=r[n+j]-u.
00453                {Since always u = (q* * [b[i-1],...,b[0]] div beta^i) + 1
00454                                < q* + 1 <= beta,
00455                 the carry u does not overflow.}
00456              If a negative carry occurs, put q* := q* - 1
00457                and [r[n+j],...,r[j]] := [r[n+j],...,r[j]] + [0,b[n-1],...,b[0]].
00458          Set q[j] := q*.
00459        Normalise [q[m-n],..,q[0]]; this yields the quotient q.
00460        Shift [r[n-1],...,r[0]] right by s bits and normalise; this yields the
00461        rest r.
00462        The room for q[j] can be allocated at the memory location of r[n+j].
00463      Finally, round-to-even:
00464        Shift r left by 1 bit.
00465        If r > b or if r = b and q[0] is odd, q := q+1.
00466    */
00467   const mp_limb_t *a_ptr = a.limbs;
00468   size_t a_len = a.nlimbs;
00469   const mp_limb_t *b_ptr = b.limbs;
00470   size_t b_len = b.nlimbs;
00471   mp_limb_t *roomptr;
00472   mp_limb_t *tmp_roomptr = NULL;
00473   mp_limb_t *q_ptr;
00474   size_t q_len;
00475   mp_limb_t *r_ptr;
00476   size_t r_len;
00477 
00478   /* Allocate room for a_len+2 digits.
00479      (Need a_len+1 digits for the real division and 1 more digit for the
00480      final rounding of q.)  */
00481   roomptr = (mp_limb_t *) malloc ((a_len + 2) * sizeof (mp_limb_t));
00482   if (roomptr == NULL)
00483     return NULL;
00484 
00485   /* Normalise a.  */
00486   while (a_len > 0 && a_ptr[a_len - 1] == 0)
00487     a_len--;
00488 
00489   /* Normalise b.  */
00490   for (;;)
00491     {
00492       if (b_len == 0)
00493         /* Division by zero.  */
00494         abort ();
00495       if (b_ptr[b_len - 1] == 0)
00496         b_len--;
00497       else
00498         break;
00499     }
00500 
00501   /* Here m = a_len >= 0 and n = b_len > 0.  */
00502 
00503   if (a_len < b_len)
00504     {
00505       /* m<n: trivial case.  q=0, r := copy of a.  */
00506       r_ptr = roomptr;
00507       r_len = a_len;
00508       memcpy (r_ptr, a_ptr, a_len * sizeof (mp_limb_t));
00509       q_ptr = roomptr + a_len;
00510       q_len = 0;
00511     }
00512   else if (b_len == 1)
00513     {
00514       /* n=1: single precision division.
00515          beta^(m-1) <= a < beta^m  ==>  beta^(m-2) <= a/b < beta^m  */
00516       r_ptr = roomptr;
00517       q_ptr = roomptr + 1;
00518       {
00519         mp_limb_t den = b_ptr[0];
00520         mp_limb_t remainder = 0;
00521         const mp_limb_t *sourceptr = a_ptr + a_len;
00522         mp_limb_t *destptr = q_ptr + a_len;
00523         size_t count;
00524         for (count = a_len; count > 0; count--)
00525           {
00526             mp_twolimb_t num =
00527               ((mp_twolimb_t) remainder << GMP_LIMB_BITS) | *--sourceptr;
00528             *--destptr = num / den;
00529             remainder = num % den;
00530           }
00531         /* Normalise and store r.  */
00532         if (remainder > 0)
00533           {
00534             r_ptr[0] = remainder;
00535             r_len = 1;
00536           }
00537         else
00538           r_len = 0;
00539         /* Normalise q.  */
00540         q_len = a_len;
00541         if (q_ptr[q_len - 1] == 0)
00542           q_len--;
00543       }
00544     }
00545   else
00546     {
00547       /* n>1: multiple precision division.
00548          beta^(m-1) <= a < beta^m, beta^(n-1) <= b < beta^n  ==>
00549          beta^(m-n-1) <= a/b < beta^(m-n+1).  */
00550       /* Determine s.  */
00551       size_t s;
00552       {
00553         mp_limb_t msd = b_ptr[b_len - 1]; /* = b[n-1], > 0 */
00554         s = 31;
00555         if (msd >= 0x10000)
00556           {
00557             msd = msd >> 16;
00558             s -= 16;
00559           }
00560         if (msd >= 0x100)
00561           {
00562             msd = msd >> 8;
00563             s -= 8;
00564           }
00565         if (msd >= 0x10)
00566           {
00567             msd = msd >> 4;
00568             s -= 4;
00569           }
00570         if (msd >= 0x4)
00571           {
00572             msd = msd >> 2;
00573             s -= 2;
00574           }
00575         if (msd >= 0x2)
00576           {
00577             msd = msd >> 1;
00578             s -= 1;
00579           }
00580       }
00581       /* 0 <= s < GMP_LIMB_BITS.
00582          Copy b, shifting it left by s bits.  */
00583       if (s > 0)
00584         {
00585           tmp_roomptr = (mp_limb_t *) malloc (b_len * sizeof (mp_limb_t));
00586           if (tmp_roomptr == NULL)
00587             {
00588               free (roomptr);
00589               return NULL;
00590             }
00591           {
00592             const mp_limb_t *sourceptr = b_ptr;
00593             mp_limb_t *destptr = tmp_roomptr;
00594             mp_twolimb_t accu = 0;
00595             size_t count;
00596             for (count = b_len; count > 0; count--)
00597               {
00598                 accu += (mp_twolimb_t) *sourceptr++ << s;
00599                 *destptr++ = (mp_limb_t) accu;
00600                 accu = accu >> GMP_LIMB_BITS;
00601               }
00602             /* accu must be zero, since that was how s was determined.  */
00603             if (accu != 0)
00604               abort ();
00605           }
00606           b_ptr = tmp_roomptr;
00607         }
00608       /* Copy a, shifting it left by s bits, yields r.
00609          Memory layout:
00610          At the beginning: r = roomptr[0..a_len],
00611          at the end: r = roomptr[0..b_len-1], q = roomptr[b_len..a_len]  */
00612       r_ptr = roomptr;
00613       if (s == 0)
00614         {
00615           memcpy (r_ptr, a_ptr, a_len * sizeof (mp_limb_t));
00616           r_ptr[a_len] = 0;
00617         }
00618       else
00619         {
00620           const mp_limb_t *sourceptr = a_ptr;
00621           mp_limb_t *destptr = r_ptr;
00622           mp_twolimb_t accu = 0;
00623           size_t count;
00624           for (count = a_len; count > 0; count--)
00625             {
00626               accu += (mp_twolimb_t) *sourceptr++ << s;
00627               *destptr++ = (mp_limb_t) accu;
00628               accu = accu >> GMP_LIMB_BITS;
00629             }
00630           *destptr++ = (mp_limb_t) accu;
00631         }
00632       q_ptr = roomptr + b_len;
00633       q_len = a_len - b_len + 1; /* q will have m-n+1 limbs */
00634       {
00635         size_t j = a_len - b_len; /* m-n */
00636         mp_limb_t b_msd = b_ptr[b_len - 1]; /* b[n-1] */
00637         mp_limb_t b_2msd = b_ptr[b_len - 2]; /* b[n-2] */
00638         mp_twolimb_t b_msdd = /* b[n-1]*beta+b[n-2] */
00639           ((mp_twolimb_t) b_msd << GMP_LIMB_BITS) | b_2msd;
00640         /* Division loop, traversed m-n+1 times.
00641            j counts down, b is unchanged, beta/2 <= b[n-1] < beta.  */
00642         for (;;)
00643           {
00644             mp_limb_t q_star;
00645             mp_limb_t c1;
00646             if (r_ptr[j + b_len] < b_msd) /* r[j+n] < b[n-1] ? */
00647               {
00648                 /* Divide r[j+n]*beta+r[j+n-1] by b[n-1], no overflow.  */
00649                 mp_twolimb_t num =
00650                   ((mp_twolimb_t) r_ptr[j + b_len] << GMP_LIMB_BITS)
00651                   | r_ptr[j + b_len - 1];
00652                 q_star = num / b_msd;
00653                 c1 = num % b_msd;
00654               }
00655             else
00656               {
00657                 /* Overflow, hence r[j+n]*beta+r[j+n-1] >= beta*b[n-1].  */
00658                 q_star = (mp_limb_t)~(mp_limb_t)0; /* q* = beta-1 */
00659                 /* Test whether r[j+n]*beta+r[j+n-1] - (beta-1)*b[n-1] >= beta
00660                    <==> r[j+n]*beta+r[j+n-1] + b[n-1] >= beta*b[n-1]+beta
00661                    <==> b[n-1] < floor((r[j+n]*beta+r[j+n-1]+b[n-1])/beta)
00662                         {<= beta !}.
00663                    If yes, jump directly to the subtraction loop.
00664                    (Otherwise, r[j+n]*beta+r[j+n-1] - (beta-1)*b[n-1] < beta
00665                     <==> floor((r[j+n]*beta+r[j+n-1]+b[n-1])/beta) = b[n-1] ) */
00666                 if (r_ptr[j + b_len] > b_msd
00667                     || (c1 = r_ptr[j + b_len - 1] + b_msd) < b_msd)
00668                   /* r[j+n] >= b[n-1]+1 or
00669                      r[j+n] = b[n-1] and the addition r[j+n-1]+b[n-1] gives a
00670                      carry.  */
00671                   goto subtract;
00672               }
00673             /* q_star = q*,
00674                c1 = (r[j+n]*beta+r[j+n-1]) - q* * b[n-1] (>=0, <beta).  */
00675             {
00676               mp_twolimb_t c2 = /* c1*beta+r[j+n-2] */
00677                 ((mp_twolimb_t) c1 << GMP_LIMB_BITS) | r_ptr[j + b_len - 2];
00678               mp_twolimb_t c3 = /* b[n-2] * q* */
00679                 (mp_twolimb_t) b_2msd * (mp_twolimb_t) q_star;
00680               /* While c2 < c3, increase c2 and decrease c3.
00681                  Consider c3-c2.  While it is > 0, decrease it by
00682                  b[n-1]*beta+b[n-2].  Because of b[n-1]*beta+b[n-2] >= beta^2/2
00683                  this can happen only twice.  */
00684               if (c3 > c2)
00685                 {
00686                   q_star = q_star - 1; /* q* := q* - 1 */
00687                   if (c3 - c2 > b_msdd)
00688                     q_star = q_star - 1; /* q* := q* - 1 */
00689                 }
00690             }
00691             if (q_star > 0)
00692               subtract:
00693               {
00694                 /* Subtract r := r - b * q* * beta^j.  */
00695                 mp_limb_t cr;
00696                 {
00697                   const mp_limb_t *sourceptr = b_ptr;
00698                   mp_limb_t *destptr = r_ptr + j;
00699                   mp_twolimb_t carry = 0;
00700                   size_t count;
00701                   for (count = b_len; count > 0; count--)
00702                     {
00703                       /* Here 0 <= carry <= q*.  */
00704                       carry =
00705                         carry
00706                         + (mp_twolimb_t) q_star * (mp_twolimb_t) *sourceptr++
00707                         + (mp_limb_t) ~(*destptr);
00708                       /* Here 0 <= carry <= beta*q* + beta-1.  */
00709                       *destptr++ = ~(mp_limb_t) carry;
00710                       carry = carry >> GMP_LIMB_BITS; /* <= q* */
00711                     }
00712                   cr = (mp_limb_t) carry;
00713                 }
00714                 /* Subtract cr from r_ptr[j + b_len], then forget about
00715                    r_ptr[j + b_len].  */
00716                 if (cr > r_ptr[j + b_len])
00717                   {
00718                     /* Subtraction gave a carry.  */
00719                     q_star = q_star - 1; /* q* := q* - 1 */
00720                     /* Add b back.  */
00721                     {
00722                       const mp_limb_t *sourceptr = b_ptr;
00723                       mp_limb_t *destptr = r_ptr + j;
00724                       mp_limb_t carry = 0;
00725                       size_t count;
00726                       for (count = b_len; count > 0; count--)
00727                         {
00728                           mp_limb_t source1 = *sourceptr++;
00729                           mp_limb_t source2 = *destptr;
00730                           *destptr++ = source1 + source2 + carry;
00731                           carry =
00732                             (carry
00733                              ? source1 >= (mp_limb_t) ~source2
00734                              : source1 > (mp_limb_t) ~source2);
00735                         }
00736                     }
00737                     /* Forget about the carry and about r[j+n].  */
00738                   }
00739               }
00740             /* q* is determined.  Store it as q[j].  */
00741             q_ptr[j] = q_star;
00742             if (j == 0)
00743               break;
00744             j--;
00745           }
00746       }
00747       r_len = b_len;
00748       /* Normalise q.  */
00749       if (q_ptr[q_len - 1] == 0)
00750         q_len--;
00751 # if 0 /* Not needed here, since we need r only to compare it with b/2, and
00752           b is shifted left by s bits.  */
00753       /* Shift r right by s bits.  */
00754       if (s > 0)
00755         {
00756           mp_limb_t ptr = r_ptr + r_len;
00757           mp_twolimb_t accu = 0;
00758           size_t count;
00759           for (count = r_len; count > 0; count--)
00760             {
00761               accu = (mp_twolimb_t) (mp_limb_t) accu << GMP_LIMB_BITS;
00762               accu += (mp_twolimb_t) *--ptr << (GMP_LIMB_BITS - s);
00763               *ptr = (mp_limb_t) (accu >> GMP_LIMB_BITS);
00764             }
00765         }
00766 # endif
00767       /* Normalise r.  */
00768       while (r_len > 0 && r_ptr[r_len - 1] == 0)
00769         r_len--;
00770     }
00771   /* Compare r << 1 with b.  */
00772   if (r_len > b_len)
00773     goto increment_q;
00774   {
00775     size_t i;
00776     for (i = b_len;;)
00777       {
00778         mp_limb_t r_i =
00779           (i <= r_len && i > 0 ? r_ptr[i - 1] >> (GMP_LIMB_BITS - 1) : 0)
00780           | (i < r_len ? r_ptr[i] << 1 : 0);
00781         mp_limb_t b_i = (i < b_len ? b_ptr[i] : 0);
00782         if (r_i > b_i)
00783           goto increment_q;
00784         if (r_i < b_i)
00785           goto keep_q;
00786         if (i == 0)
00787           break;
00788         i--;
00789       }
00790   }
00791   if (q_len > 0 && ((q_ptr[0] & 1) != 0))
00792     /* q is odd.  */
00793     increment_q:
00794     {
00795       size_t i;
00796       for (i = 0; i < q_len; i++)
00797         if (++(q_ptr[i]) != 0)
00798           goto keep_q;
00799       q_ptr[q_len++] = 1;
00800     }
00801   keep_q:
00802   if (tmp_roomptr != NULL)
00803     free (tmp_roomptr);
00804   q->limbs = q_ptr;
00805   q->nlimbs = q_len;
00806   return roomptr;
00807 }
00808 
00809 /* Convert a bignum a >= 0, multiplied with 10^extra_zeroes, to decimal
00810    representation.
00811    Destroys the contents of a.
00812    Return the allocated memory - containing the decimal digits in low-to-high
00813    order, terminated with a NUL character - in case of success, NULL in case
00814    of memory allocation failure.  */
00815 static char *
00816 convert_to_decimal (mpn_t a, size_t extra_zeroes)
00817 {
00818   mp_limb_t *a_ptr = a.limbs;
00819   size_t a_len = a.nlimbs;
00820   /* 0.03345 is slightly larger than log(2)/(9*log(10)).  */
00821   size_t c_len = 9 * ((size_t)(a_len * (GMP_LIMB_BITS * 0.03345f)) + 1);
00822   char *c_ptr = (char *) malloc (xsum (c_len, extra_zeroes));
00823   if (c_ptr != NULL)
00824     {
00825       char *d_ptr = c_ptr;
00826       for (; extra_zeroes > 0; extra_zeroes--)
00827         *d_ptr++ = '0';
00828       while (a_len > 0)
00829         {
00830           /* Divide a by 10^9, in-place.  */
00831           mp_limb_t remainder = 0;
00832           mp_limb_t *ptr = a_ptr + a_len;
00833           size_t count;
00834           for (count = a_len; count > 0; count--)
00835             {
00836               mp_twolimb_t num =
00837                 ((mp_twolimb_t) remainder << GMP_LIMB_BITS) | *--ptr;
00838               *ptr = num / 1000000000;
00839               remainder = num % 1000000000;
00840             }
00841           /* Store the remainder as 9 decimal digits.  */
00842           for (count = 9; count > 0; count--)
00843             {
00844               *d_ptr++ = '0' + (remainder % 10);
00845               remainder = remainder / 10;
00846             }
00847           /* Normalize a.  */
00848           if (a_ptr[a_len - 1] == 0)
00849             a_len--;
00850         }
00851       /* Remove leading zeroes.  */
00852       while (d_ptr > c_ptr && d_ptr[-1] == '0')
00853         d_ptr--;
00854       /* But keep at least one zero.  */
00855       if (d_ptr == c_ptr)
00856         *d_ptr++ = '0';
00857       /* Terminate the string.  */
00858       *d_ptr = '\0';
00859     }
00860   return c_ptr;
00861 }
00862 
00863 # if NEED_PRINTF_LONG_DOUBLE
00864 
00865 /* Assuming x is finite and >= 0:
00866    write x as x = 2^e * m, where m is a bignum.
00867    Return the allocated memory in case of success, NULL in case of memory
00868    allocation failure.  */
00869 static void *
00870 decode_long_double (long double x, int *ep, mpn_t *mp)
00871 {
00872   mpn_t m;
00873   int exp;
00874   long double y;
00875   size_t i;
00876 
00877   /* Allocate memory for result.  */
00878   m.nlimbs = (LDBL_MANT_BIT + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS;
00879   m.limbs = (mp_limb_t *) malloc (m.nlimbs * sizeof (mp_limb_t));
00880   if (m.limbs == NULL)
00881     return NULL;
00882   /* Split into exponential part and mantissa.  */
00883   y = frexpl (x, &exp);
00884   if (!(y >= 0.0L && y < 1.0L))
00885     abort ();
00886   /* x = 2^exp * y = 2^(exp - LDBL_MANT_BIT) * (y * LDBL_MANT_BIT), and the
00887      latter is an integer.  */
00888   /* Convert the mantissa (y * LDBL_MANT_BIT) to a sequence of limbs.
00889      I'm not sure whether it's safe to cast a 'long double' value between
00890      2^31 and 2^32 to 'unsigned int', therefore play safe and cast only
00891      'long double' values between 0 and 2^16 (to 'unsigned int' or 'int',
00892      doesn't matter).  */
00893 #  if (LDBL_MANT_BIT % GMP_LIMB_BITS) != 0
00894 #   if (LDBL_MANT_BIT % GMP_LIMB_BITS) > GMP_LIMB_BITS / 2
00895     {
00896       mp_limb_t hi, lo;
00897       y *= (mp_limb_t) 1 << (LDBL_MANT_BIT % (GMP_LIMB_BITS / 2));
00898       hi = (int) y;
00899       y -= hi;
00900       if (!(y >= 0.0L && y < 1.0L))
00901         abort ();
00902       y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
00903       lo = (int) y;
00904       y -= lo;
00905       if (!(y >= 0.0L && y < 1.0L))
00906         abort ();
00907       m.limbs[LDBL_MANT_BIT / GMP_LIMB_BITS] = (hi << (GMP_LIMB_BITS / 2)) | lo;
00908     }
00909 #   else
00910     {
00911       mp_limb_t d;
00912       y *= (mp_limb_t) 1 << (LDBL_MANT_BIT % GMP_LIMB_BITS);
00913       d = (int) y;
00914       y -= d;
00915       if (!(y >= 0.0L && y < 1.0L))
00916         abort ();
00917       m.limbs[LDBL_MANT_BIT / GMP_LIMB_BITS] = d;
00918     }
00919 #   endif
00920 #  endif
00921   for (i = LDBL_MANT_BIT / GMP_LIMB_BITS; i > 0; )
00922     {
00923       mp_limb_t hi, lo;
00924       y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
00925       hi = (int) y;
00926       y -= hi;
00927       if (!(y >= 0.0L && y < 1.0L))
00928         abort ();
00929       y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
00930       lo = (int) y;
00931       y -= lo;
00932       if (!(y >= 0.0L && y < 1.0L))
00933         abort ();
00934       m.limbs[--i] = (hi << (GMP_LIMB_BITS / 2)) | lo;
00935     }
00936 #if 0 /* On FreeBSD 6.1/x86, 'long double' numbers sometimes have excess
00937          precision.  */
00938   if (!(y == 0.0L))
00939     abort ();
00940 #endif
00941   /* Normalise.  */
00942   while (m.nlimbs > 0 && m.limbs[m.nlimbs - 1] == 0)
00943     m.nlimbs--;
00944   *mp = m;
00945   *ep = exp - LDBL_MANT_BIT;
00946   return m.limbs;
00947 }
00948 
00949 # endif
00950 
00951 # if NEED_PRINTF_DOUBLE
00952 
00953 /* Assuming x is finite and >= 0:
00954    write x as x = 2^e * m, where m is a bignum.
00955    Return the allocated memory in case of success, NULL in case of memory
00956    allocation failure.  */
00957 static void *
00958 decode_double (double x, int *ep, mpn_t *mp)
00959 {
00960   mpn_t m;
00961   int exp;
00962   double y;
00963   size_t i;
00964 
00965   /* Allocate memory for result.  */
00966   m.nlimbs = (DBL_MANT_BIT + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS;
00967   m.limbs = (mp_limb_t *) malloc (m.nlimbs * sizeof (mp_limb_t));
00968   if (m.limbs == NULL)
00969     return NULL;
00970   /* Split into exponential part and mantissa.  */
00971   y = frexp (x, &exp);
00972   if (!(y >= 0.0 && y < 1.0))
00973     abort ();
00974   /* x = 2^exp * y = 2^(exp - DBL_MANT_BIT) * (y * DBL_MANT_BIT), and the
00975      latter is an integer.  */
00976   /* Convert the mantissa (y * DBL_MANT_BIT) to a sequence of limbs.
00977      I'm not sure whether it's safe to cast a 'double' value between
00978      2^31 and 2^32 to 'unsigned int', therefore play safe and cast only
00979      'double' values between 0 and 2^16 (to 'unsigned int' or 'int',
00980      doesn't matter).  */
00981 #  if (DBL_MANT_BIT % GMP_LIMB_BITS) != 0
00982 #   if (DBL_MANT_BIT % GMP_LIMB_BITS) > GMP_LIMB_BITS / 2
00983     {
00984       mp_limb_t hi, lo;
00985       y *= (mp_limb_t) 1 << (DBL_MANT_BIT % (GMP_LIMB_BITS / 2));
00986       hi = (int) y;
00987       y -= hi;
00988       if (!(y >= 0.0 && y < 1.0))
00989         abort ();
00990       y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
00991       lo = (int) y;
00992       y -= lo;
00993       if (!(y >= 0.0 && y < 1.0))
00994         abort ();
00995       m.limbs[DBL_MANT_BIT / GMP_LIMB_BITS] = (hi << (GMP_LIMB_BITS / 2)) | lo;
00996     }
00997 #   else
00998     {
00999       mp_limb_t d;
01000       y *= (mp_limb_t) 1 << (DBL_MANT_BIT % GMP_LIMB_BITS);
01001       d = (int) y;
01002       y -= d;
01003       if (!(y >= 0.0 && y < 1.0))
01004         abort ();
01005       m.limbs[DBL_MANT_BIT / GMP_LIMB_BITS] = d;
01006     }
01007 #   endif
01008 #  endif
01009   for (i = DBL_MANT_BIT / GMP_LIMB_BITS; i > 0; )
01010     {
01011       mp_limb_t hi, lo;
01012       y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
01013       hi = (int) y;
01014       y -= hi;
01015       if (!(y >= 0.0 && y < 1.0))
01016         abort ();
01017       y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
01018       lo = (int) y;
01019       y -= lo;
01020       if (!(y >= 0.0 && y < 1.0))
01021         abort ();
01022       m.limbs[--i] = (hi << (GMP_LIMB_BITS / 2)) | lo;
01023     }
01024   if (!(y == 0.0))
01025     abort ();
01026   /* Normalise.  */
01027   while (m.nlimbs > 0 && m.limbs[m.nlimbs - 1] == 0)
01028     m.nlimbs--;
01029   *mp = m;
01030   *ep = exp - DBL_MANT_BIT;
01031   return m.limbs;
01032 }
01033 
01034 # endif
01035 
01036 /* Assuming x = 2^e * m is finite and >= 0, and n is an integer:
01037    Returns the decimal representation of round (x * 10^n).
01038    Return the allocated memory - containing the decimal digits in low-to-high
01039    order, terminated with a NUL character - in case of success, NULL in case
01040    of memory allocation failure.  */
01041 static char *
01042 scale10_round_decimal_decoded (int e, mpn_t m, void *memory, int n)
01043 {
01044   int s;
01045   size_t extra_zeroes;
01046   unsigned int abs_n;
01047   unsigned int abs_s;
01048   mp_limb_t *pow5_ptr;
01049   size_t pow5_len;
01050   unsigned int s_limbs;
01051   unsigned int s_bits;
01052   mpn_t pow5;
01053   mpn_t z;
01054   void *z_memory;
01055   char *digits;
01056 
01057   if (memory == NULL)
01058     return NULL;
01059   /* x = 2^e * m, hence
01060      y = round (2^e * 10^n * m) = round (2^(e+n) * 5^n * m)
01061        = round (2^s * 5^n * m).  */
01062   s = e + n;
01063   extra_zeroes = 0;
01064   /* Factor out a common power of 10 if possible.  */
01065   if (s > 0 && n > 0)
01066     {
01067       extra_zeroes = (s < n ? s : n);
01068       s -= extra_zeroes;
01069       n -= extra_zeroes;
01070     }
01071   /* Here y = round (2^s * 5^n * m) * 10^extra_zeroes.
01072      Before converting to decimal, we need to compute
01073      z = round (2^s * 5^n * m).  */
01074   /* Compute 5^|n|, possibly shifted by |s| bits if n and s have the same
01075      sign.  2.322 is slightly larger than log(5)/log(2).  */
01076   abs_n = (n >= 0 ? n : -n);
01077   abs_s = (s >= 0 ? s : -s);
01078   pow5_ptr = (mp_limb_t *) malloc (((int)(abs_n * (2.322f / GMP_LIMB_BITS)) + 1
01079                                     + abs_s / GMP_LIMB_BITS + 1)
01080                                    * sizeof (mp_limb_t));
01081   if (pow5_ptr == NULL)
01082     {
01083       free (memory);
01084       return NULL;
01085     }
01086   /* Initialize with 1.  */
01087   pow5_ptr[0] = 1;
01088   pow5_len = 1;
01089   /* Multiply with 5^|n|.  */
01090   if (abs_n > 0)
01091     {
01092       static mp_limb_t const small_pow5[13 + 1] =
01093         {
01094           1, 5, 25, 125, 625, 3125, 15625, 78125, 390625, 1953125, 9765625,
01095           48828125, 244140625, 1220703125
01096         };
01097       unsigned int n13;
01098       for (n13 = 0; n13 <= abs_n; n13 += 13)
01099         {
01100           mp_limb_t digit1 = small_pow5[n13 + 13 <= abs_n ? 13 : abs_n - n13];
01101           size_t j;
01102           mp_twolimb_t carry = 0;
01103           for (j = 0; j < pow5_len; j++)
01104             {
01105               mp_limb_t digit2 = pow5_ptr[j];
01106               carry += (mp_twolimb_t) digit1 * (mp_twolimb_t) digit2;
01107               pow5_ptr[j] = (mp_limb_t) carry;
01108               carry = carry >> GMP_LIMB_BITS;
01109             }
01110           if (carry > 0)
01111             pow5_ptr[pow5_len++] = (mp_limb_t) carry;
01112         }
01113     }
01114   s_limbs = abs_s / GMP_LIMB_BITS;
01115   s_bits = abs_s % GMP_LIMB_BITS;
01116   if (n >= 0 ? s >= 0 : s <= 0)
01117     {
01118       /* Multiply with 2^|s|.  */
01119       if (s_bits > 0)
01120         {
01121           mp_limb_t *ptr = pow5_ptr;
01122           mp_twolimb_t accu = 0;
01123           size_t count;
01124           for (count = pow5_len; count > 0; count--)
01125             {
01126               accu += (mp_twolimb_t) *ptr << s_bits;
01127               *ptr++ = (mp_limb_t) accu;
01128               accu = accu >> GMP_LIMB_BITS;
01129             }
01130           if (accu > 0)
01131             {
01132               *ptr = (mp_limb_t) accu;
01133               pow5_len++;
01134             }
01135         }
01136       if (s_limbs > 0)
01137         {
01138           size_t count;
01139           for (count = pow5_len; count > 0;)
01140             {
01141               count--;
01142               pow5_ptr[s_limbs + count] = pow5_ptr[count];
01143             }
01144           for (count = s_limbs; count > 0;)
01145             {
01146               count--;
01147               pow5_ptr[count] = 0;
01148             }
01149           pow5_len += s_limbs;
01150         }
01151       pow5.limbs = pow5_ptr;
01152       pow5.nlimbs = pow5_len;
01153       if (n >= 0)
01154         {
01155           /* Multiply m with pow5.  No division needed.  */
01156           z_memory = multiply (m, pow5, &z);
01157         }
01158       else
01159         {
01160           /* Divide m by pow5 and round.  */
01161           z_memory = divide (m, pow5, &z);
01162         }
01163     }
01164   else
01165     {
01166       pow5.limbs = pow5_ptr;
01167       pow5.nlimbs = pow5_len;
01168       if (n >= 0)
01169         {
01170           /* n >= 0, s < 0.
01171              Multiply m with pow5, then divide by 2^|s|.  */
01172           mpn_t numerator;
01173           mpn_t denominator;
01174           void *tmp_memory;
01175           tmp_memory = multiply (m, pow5, &numerator);
01176           if (tmp_memory == NULL)
01177             {
01178               free (pow5_ptr);
01179               free (memory);
01180               return NULL;
01181             }
01182           /* Construct 2^|s|.  */
01183           {
01184             mp_limb_t *ptr = pow5_ptr + pow5_len;
01185             size_t i;
01186             for (i = 0; i < s_limbs; i++)
01187               ptr[i] = 0;
01188             ptr[s_limbs] = (mp_limb_t) 1 << s_bits;
01189             denominator.limbs = ptr;
01190             denominator.nlimbs = s_limbs + 1;
01191           }
01192           z_memory = divide (numerator, denominator, &z);
01193           free (tmp_memory);
01194         }
01195       else
01196         {
01197           /* n < 0, s > 0.
01198              Multiply m with 2^s, then divide by pow5.  */
01199           mpn_t numerator;
01200           mp_limb_t *num_ptr;
01201           num_ptr = (mp_limb_t *) malloc ((m.nlimbs + s_limbs + 1)
01202                                           * sizeof (mp_limb_t));
01203           if (num_ptr == NULL)
01204             {
01205               free (pow5_ptr);
01206               free (memory);
01207               return NULL;
01208             }
01209           {
01210             mp_limb_t *destptr = num_ptr;
01211             {
01212               size_t i;
01213               for (i = 0; i < s_limbs; i++)
01214                 *destptr++ = 0;
01215             }
01216             if (s_bits > 0)
01217               {
01218                 const mp_limb_t *sourceptr = m.limbs;
01219                 mp_twolimb_t accu = 0;
01220                 size_t count;
01221                 for (count = m.nlimbs; count > 0; count--)
01222                   {
01223                     accu += (mp_twolimb_t) *sourceptr++ << s_bits;
01224                     *destptr++ = (mp_limb_t) accu;
01225                     accu = accu >> GMP_LIMB_BITS;
01226                   }
01227                 if (accu > 0)
01228                   *destptr++ = (mp_limb_t) accu;
01229               }
01230             else
01231               {
01232                 const mp_limb_t *sourceptr = m.limbs;
01233                 size_t count;
01234                 for (count = m.nlimbs; count > 0; count--)
01235                   *destptr++ = *sourceptr++;
01236               }
01237             numerator.limbs = num_ptr;
01238             numerator.nlimbs = destptr - num_ptr;
01239           }
01240           z_memory = divide (numerator, pow5, &z);
01241           free (num_ptr);
01242         }
01243     }
01244   free (pow5_ptr);
01245   free (memory);
01246 
01247   /* Here y = round (x * 10^n) = z * 10^extra_zeroes.  */
01248 
01249   if (z_memory == NULL)
01250     return NULL;
01251   digits = convert_to_decimal (z, extra_zeroes);
01252   free (z_memory);
01253   return digits;
01254 }
01255 
01256 # if NEED_PRINTF_LONG_DOUBLE
01257 
01258 /* Assuming x is finite and >= 0, and n is an integer:
01259    Returns the decimal representation of round (x * 10^n).
01260    Return the allocated memory - containing the decimal digits in low-to-high
01261    order, terminated with a NUL character - in case of success, NULL in case
01262    of memory allocation failure.  */
01263 static char *
01264 scale10_round_decimal_long_double (long double x, int n)
01265 {
01266   int e IF_LINT(= 0);
01267   mpn_t m;
01268   void *memory = decode_long_double (x, &e, &m);
01269   return scale10_round_decimal_decoded (e, m, memory, n);
01270 }
01271 
01272 # endif
01273 
01274 # if NEED_PRINTF_DOUBLE
01275 
01276 /* Assuming x is finite and >= 0, and n is an integer:
01277    Returns the decimal representation of round (x * 10^n).
01278    Return the allocated memory - containing the decimal digits in low-to-high
01279    order, terminated with a NUL character - in case of success, NULL in case
01280    of memory allocation failure.  */
01281 static char *
01282 scale10_round_decimal_double (double x, int n)
01283 {
01284   int e IF_LINT(= 0);
01285   mpn_t m;
01286   void *memory = decode_double (x, &e, &m);
01287   return scale10_round_decimal_decoded (e, m, memory, n);
01288 }
01289 
01290 # endif
01291 
01292 # if NEED_PRINTF_LONG_DOUBLE
01293 
01294 /* Assuming x is finite and > 0:
01295    Return an approximation for n with 10^n <= x < 10^(n+1).
01296    The approximation is usually the right n, but may be off by 1 sometimes.  */
01297 static int
01298 floorlog10l (long double x)
01299 {
01300   int exp;
01301   long double y;
01302   double z;
01303   double l;
01304 
01305   /* Split into exponential part and mantissa.  */
01306   y = frexpl (x, &exp);
01307   if (!(y >= 0.0L && y < 1.0L))
01308     abort ();
01309   if (y == 0.0L)
01310     return INT_MIN;
01311   if (y < 0.5L)
01312     {
01313       while (y < (1.0L / (1 << (GMP_LIMB_BITS / 2)) / (1 << (GMP_LIMB_BITS / 2))))
01314         {
01315           y *= 1.0L * (1 << (GMP_LIMB_BITS / 2)) * (1 << (GMP_LIMB_BITS / 2));
01316           exp -= GMP_LIMB_BITS;
01317         }
01318       if (y < (1.0L / (1 << 16)))
01319         {
01320           y *= 1.0L * (1 << 16);
01321           exp -= 16;
01322         }
01323       if (y < (1.0L / (1 << 8)))
01324         {
01325           y *= 1.0L * (1 << 8);
01326           exp -= 8;
01327         }
01328       if (y < (1.0L / (1 << 4)))
01329         {
01330           y *= 1.0L * (1 << 4);
01331           exp -= 4;
01332         }
01333       if (y < (1.0L / (1 << 2)))
01334         {
01335           y *= 1.0L * (1 << 2);
01336           exp -= 2;
01337         }
01338       if (y < (1.0L / (1 << 1)))
01339         {
01340           y *= 1.0L * (1 << 1);
01341           exp -= 1;
01342         }
01343     }
01344   if (!(y >= 0.5L && y < 1.0L))
01345     abort ();
01346   /* Compute an approximation for l = log2(x) = exp + log2(y).  */
01347   l = exp;
01348   z = y;
01349   if (z < 0.70710678118654752444)
01350     {
01351       z *= 1.4142135623730950488;
01352       l -= 0.5;
01353     }
01354   if (z < 0.8408964152537145431)
01355     {
01356       z *= 1.1892071150027210667;
01357       l -= 0.25;
01358     }
01359   if (z < 0.91700404320467123175)
01360     {
01361       z *= 1.0905077326652576592;
01362       l -= 0.125;
01363     }
01364   if (z < 0.9576032806985736469)
01365     {
01366       z *= 1.0442737824274138403;
01367       l -= 0.0625;
01368     }
01369   /* Now 0.95 <= z <= 1.01.  */
01370   z = 1 - z;
01371   /* log2(1-z) = 1/log(2) * (- z - z^2/2 - z^3/3 - z^4/4 - ...)
01372      Four terms are enough to get an approximation with error < 10^-7.  */
01373   l -= 1.4426950408889634074 * z * (1.0 + z * (0.5 + z * ((1.0 / 3) + z * 0.25)));
01374   /* Finally multiply with log(2)/log(10), yields an approximation for
01375      log10(x).  */
01376   l *= 0.30102999566398119523;
01377   /* Round down to the next integer.  */
01378   return (int) l + (l < 0 ? -1 : 0);
01379 }
01380 
01381 # endif
01382 
01383 # if NEED_PRINTF_DOUBLE
01384 
01385 /* Assuming x is finite and > 0:
01386    Return an approximation for n with 10^n <= x < 10^(n+1).
01387    The approximation is usually the right n, but may be off by 1 sometimes.  */
01388 static int
01389 floorlog10 (double x)
01390 {
01391   int exp;
01392   double y;
01393   double z;
01394   double l;
01395 
01396   /* Split into exponential part and mantissa.  */
01397   y = frexp (x, &exp);
01398   if (!(y >= 0.0 && y < 1.0))
01399     abort ();
01400   if (y == 0.0)
01401     return INT_MIN;
01402   if (y < 0.5)
01403     {
01404       while (y < (1.0 / (1 << (GMP_LIMB_BITS / 2)) / (1 << (GMP_LIMB_BITS / 2))))
01405         {
01406           y *= 1.0 * (1 << (GMP_LIMB_BITS / 2)) * (1 << (GMP_LIMB_BITS / 2));
01407           exp -= GMP_LIMB_BITS;
01408         }
01409       if (y < (1.0 / (1 << 16)))
01410         {
01411           y *= 1.0 * (1 << 16);
01412           exp -= 16;
01413         }
01414       if (y < (1.0 / (1 << 8)))
01415         {
01416           y *= 1.0 * (1 << 8);
01417           exp -= 8;
01418         }
01419       if (y < (1.0 / (1 << 4)))
01420         {
01421           y *= 1.0 * (1 << 4);
01422           exp -= 4;
01423         }
01424       if (y < (1.0 / (1 << 2)))
01425         {
01426           y *= 1.0 * (1 << 2);
01427           exp -= 2;
01428         }
01429       if (y < (1.0 / (1 << 1)))
01430         {
01431           y *= 1.0 * (1 << 1);
01432           exp -= 1;
01433         }
01434     }
01435   if (!(y >= 0.5 && y < 1.0))
01436     abort ();
01437   /* Compute an approximation for l = log2(x) = exp + log2(y).  */
01438   l = exp;
01439   z = y;
01440   if (z < 0.70710678118654752444)
01441     {
01442       z *= 1.4142135623730950488;
01443       l -= 0.5;
01444     }
01445   if (z < 0.8408964152537145431)
01446     {
01447       z *= 1.1892071150027210667;
01448       l -= 0.25;
01449     }
01450   if (z < 0.91700404320467123175)
01451     {
01452       z *= 1.0905077326652576592;
01453       l -= 0.125;
01454     }
01455   if (z < 0.9576032806985736469)
01456     {
01457       z *= 1.0442737824274138403;
01458       l -= 0.0625;
01459     }
01460   /* Now 0.95 <= z <= 1.01.  */
01461   z = 1 - z;
01462   /* log2(1-z) = 1/log(2) * (- z - z^2/2 - z^3/3 - z^4/4 - ...)
01463      Four terms are enough to get an approximation with error < 10^-7.  */
01464   l -= 1.4426950408889634074 * z * (1.0 + z * (0.5 + z * ((1.0 / 3) + z * 0.25)));
01465   /* Finally multiply with log(2)/log(10), yields an approximation for
01466      log10(x).  */
01467   l *= 0.30102999566398119523;
01468   /* Round down to the next integer.  */
01469   return (int) l + (l < 0 ? -1 : 0);
01470 }
01471 
01472 # endif
01473 
01474 /* Tests whether a string of digits consists of exactly PRECISION zeroes and
01475    a single '1' digit.  */
01476 static int
01477 is_borderline (const char *digits, size_t precision)
01478 {
01479   for (; precision > 0; precision--, digits++)
01480     if (*digits != '0')
01481       return 0;
01482   if (*digits != '1')
01483     return 0;
01484   digits++;
01485   return *digits == '\0';
01486 }
01487 
01488 #endif
01489 
01490 #if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99
01491 
01492 /* Use a different function name, to make it possible that the 'wchar_t'
01493    parametrization and the 'char' parametrization get compiled in the same
01494    translation unit.  */
01495 # if WIDE_CHAR_VERSION
01496 #  define MAX_ROOM_NEEDED wmax_room_needed
01497 # else
01498 #  define MAX_ROOM_NEEDED max_room_needed
01499 # endif
01500 
01501 /* Returns the number of TCHAR_T units needed as temporary space for the result
01502    of sprintf or SNPRINTF of a single conversion directive.  */
01503 static inline size_t
01504 MAX_ROOM_NEEDED (const arguments *ap, size_t arg_index, FCHAR_T conversion,
01505                  arg_type type, int flags, size_t width, int has_precision,
01506                  size_t precision, int pad_ourselves)
01507 {
01508   size_t tmp_length;
01509 
01510   switch (conversion)
01511     {
01512     case 'd': case 'i': case 'u':
01513 # if HAVE_LONG_LONG_INT
01514       if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
01515         tmp_length =
01516           (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
01517                           * 0.30103 /* binary -> decimal */
01518                          )
01519           + 1; /* turn floor into ceil */
01520       else
01521 # endif
01522       if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
01523         tmp_length =
01524           (unsigned int) (sizeof (unsigned long) * CHAR_BIT
01525                           * 0.30103 /* binary -> decimal */
01526                          )
01527           + 1; /* turn floor into ceil */
01528       else
01529         tmp_length =
01530           (unsigned int) (sizeof (unsigned int) * CHAR_BIT
01531                           * 0.30103 /* binary -> decimal */
01532                          )
01533           + 1; /* turn floor into ceil */
01534       if (tmp_length < precision)
01535         tmp_length = precision;
01536       /* Multiply by 2, as an estimate for FLAG_GROUP.  */
01537       tmp_length = xsum (tmp_length, tmp_length);
01538       /* Add 1, to account for a leading sign.  */
01539       tmp_length = xsum (tmp_length, 1);
01540       break;
01541 
01542     case 'o':
01543 # if HAVE_LONG_LONG_INT
01544       if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
01545         tmp_length =
01546           (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
01547                           * 0.333334 /* binary -> octal */
01548                          )
01549           + 1; /* turn floor into ceil */
01550       else
01551 # endif
01552       if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
01553         tmp_length =
01554           (unsigned int) (sizeof (unsigned long) * CHAR_BIT
01555                           * 0.333334 /* binary -> octal */
01556                          )
01557           + 1; /* turn floor into ceil */
01558       else
01559         tmp_length =
01560           (unsigned int) (sizeof (unsigned int) * CHAR_BIT
01561                           * 0.333334 /* binary -> octal */
01562                          )
01563           + 1; /* turn floor into ceil */
01564       if (tmp_length < precision)
01565         tmp_length = precision;
01566       /* Add 1, to account for a leading sign.  */
01567       tmp_length = xsum (tmp_length, 1);
01568       break;
01569 
01570     case 'x': case 'X':
01571 # if HAVE_LONG_LONG_INT
01572       if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
01573         tmp_length =
01574           (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
01575                           * 0.25 /* binary -> hexadecimal */
01576                          )
01577           + 1; /* turn floor into ceil */
01578       else
01579 # endif
01580       if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
01581         tmp_length =
01582           (unsigned int) (sizeof (unsigned long) * CHAR_BIT
01583                           * 0.25 /* binary -> hexadecimal */
01584                          )
01585           + 1; /* turn floor into ceil */
01586       else
01587         tmp_length =
01588           (unsigned int) (sizeof (unsigned int) * CHAR_BIT
01589                           * 0.25 /* binary -> hexadecimal */
01590                          )
01591           + 1; /* turn floor into ceil */
01592       if (tmp_length < precision)
01593         tmp_length = precision;
01594       /* Add 2, to account for a leading sign or alternate form.  */
01595       tmp_length = xsum (tmp_length, 2);
01596       break;
01597 
01598     case 'f': case 'F':
01599       if (type == TYPE_LONGDOUBLE)
01600         tmp_length =
01601           (unsigned int) (LDBL_MAX_EXP
01602                           * 0.30103 /* binary -> decimal */
01603                           * 2 /* estimate for FLAG_GROUP */
01604                          )
01605           + 1 /* turn floor into ceil */
01606           + 10; /* sign, decimal point etc. */
01607       else
01608         tmp_length =
01609           (unsigned int) (DBL_MAX_EXP
01610                           * 0.30103 /* binary -> decimal */
01611                           * 2 /* estimate for FLAG_GROUP */
01612                          )
01613           + 1 /* turn floor into ceil */
01614           + 10; /* sign, decimal point etc. */
01615       tmp_length = xsum (tmp_length, precision);
01616       break;
01617 
01618     case 'e': case 'E': case 'g': case 'G':
01619       tmp_length =
01620         12; /* sign, decimal point, exponent etc. */
01621       tmp_length = xsum (tmp_length, precision);
01622       break;
01623 
01624     case 'a': case 'A':
01625       if (type == TYPE_LONGDOUBLE)
01626         tmp_length =
01627           (unsigned int) (LDBL_DIG
01628                           * 0.831 /* decimal -> hexadecimal */
01629                          )
01630           + 1; /* turn floor into ceil */
01631       else
01632         tmp_length =
01633           (unsigned int) (DBL_DIG
01634                           * 0.831 /* decimal -> hexadecimal */
01635                          )
01636           + 1; /* turn floor into ceil */
01637       if (tmp_length < precision)
01638         tmp_length = precision;
01639       /* Account for sign, decimal point etc. */
01640       tmp_length = xsum (tmp_length, 12);
01641       break;
01642 
01643     case 'c':
01644 # if HAVE_WINT_T && !WIDE_CHAR_VERSION
01645       if (type == TYPE_WIDE_CHAR)
01646         tmp_length = MB_CUR_MAX;
01647       else
01648 # endif
01649         tmp_length = 1;
01650       break;
01651 
01652     case 's':
01653 # if HAVE_WCHAR_T
01654       if (type == TYPE_WIDE_STRING)
01655         {
01656 #  if WIDE_CHAR_VERSION
01657           /* ISO C says about %ls in fwprintf:
01658                "If the precision is not specified or is greater than the size
01659                 of the array, the array shall contain a null wide character."
01660              So if there is a precision, we must not use wcslen.  */
01661           const wchar_t *arg = ap->arg[arg_index].a.a_wide_string;
01662 
01663           if (has_precision)
01664             tmp_length = local_wcsnlen (arg, precision);
01665           else
01666             tmp_length = local_wcslen (arg);
01667 #  else
01668           /* ISO C says about %ls in fprintf:
01669                "If a precision is specified, no more than that many bytes are
01670                 written (including shift sequences, if any), and the array
01671                 shall contain a null wide character if, to equal the multibyte
01672                 character sequence length given by the precision, the function
01673                 would need to access a wide character one past the end of the
01674                 array."
01675              So if there is a precision, we must not use wcslen.  */
01676           /* This case has already been handled separately in VASNPRINTF.  */
01677           abort ();
01678 #  endif
01679         }
01680       else
01681 # endif
01682         {
01683 # if WIDE_CHAR_VERSION
01684           /* ISO C says about %s in fwprintf:
01685                "If the precision is not specified or is greater than the size
01686                 of the converted array, the converted array shall contain a
01687                 null wide character."
01688              So if there is a precision, we must not use strlen.  */
01689           /* This case has already been handled separately in VASNPRINTF.  */
01690           abort ();
01691 # else
01692           /* ISO C says about %s in fprintf:
01693                "If the precision is not specified or greater than the size of
01694                 the array, the array shall contain a null character."
01695              So if there is a precision, we must not use strlen.  */
01696           const char *arg = ap->arg[arg_index].a.a_string;
01697 
01698           if (has_precision)
01699             tmp_length = local_strnlen (arg, precision);
01700           else
01701             tmp_length = strlen (arg);
01702 # endif
01703         }
01704       break;
01705 
01706     case 'p':
01707       tmp_length =
01708         (unsigned int) (sizeof (void *) * CHAR_BIT
01709                         * 0.25 /* binary -> hexadecimal */
01710                        )
01711           + 1 /* turn floor into ceil */
01712           + 2; /* account for leading 0x */
01713       break;
01714 
01715     default:
01716       abort ();
01717     }
01718 
01719   if (!pad_ourselves)
01720     {
01721 # if ENABLE_UNISTDIO
01722       /* Padding considers the number of characters, therefore the number of
01723          elements after padding may be
01724            > max (tmp_length, width)
01725          but is certainly
01726            <= tmp_length + width.  */
01727       tmp_length = xsum (tmp_length, width);
01728 # else
01729       /* Padding considers the number of elements, says POSIX.  */
01730       if (tmp_length < width)
01731         tmp_length = width;
01732 # endif
01733     }
01734 
01735   tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
01736 
01737   return tmp_length;
01738 }
01739 
01740 #endif
01741 
01742 DCHAR_T *
01743 VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
01744             const FCHAR_T *format, va_list args)
01745 {
01746   DIRECTIVES d;
01747   arguments a;
01748 
01749   if (PRINTF_PARSE (format, &d, &a) < 0)
01750     /* errno is already set.  */
01751     return NULL;
01752 
01753 #define CLEANUP() \
01754   free (d.dir);                                                         \
01755   if (a.arg)                                                            \
01756     free (a.arg);
01757 
01758   if (PRINTF_FETCHARGS (args, &a) < 0)
01759     {
01760       CLEANUP ();
01761       errno = EINVAL;
01762       return NULL;
01763     }
01764 
01765   {
01766     size_t buf_neededlength;
01767     TCHAR_T *buf;
01768     TCHAR_T *buf_malloced;
01769     const FCHAR_T *cp;
01770     size_t i;
01771     DIRECTIVE *dp;
01772     /* Output string accumulator.  */
01773     DCHAR_T *result;
01774     size_t allocated;
01775     size_t length;
01776 
01777     /* Allocate a small buffer that will hold a directive passed to
01778        sprintf or snprintf.  */
01779     buf_neededlength =
01780       xsum4 (7, d.max_width_length, d.max_precision_length, 6);
01781 #if HAVE_ALLOCA
01782     if (buf_neededlength < 4000 / sizeof (TCHAR_T))
01783       {
01784         buf = (TCHAR_T *) alloca (buf_neededlength * sizeof (TCHAR_T));
01785         buf_malloced = NULL;
01786       }
01787     else
01788 #endif
01789       {
01790         size_t buf_memsize = xtimes (buf_neededlength, sizeof (TCHAR_T));
01791         if (size_overflow_p (buf_memsize))
01792           goto out_of_memory_1;
01793         buf = (TCHAR_T *) malloc (buf_memsize);
01794         if (buf == NULL)
01795           goto out_of_memory_1;
01796         buf_malloced = buf;
01797       }
01798 
01799     if (resultbuf != NULL)
01800       {
01801         result = resultbuf;
01802         allocated = *lengthp;
01803       }
01804     else
01805       {
01806         result = NULL;
01807         allocated = 0;
01808       }
01809     length = 0;
01810     /* Invariants:
01811        result is either == resultbuf or == NULL or malloc-allocated.
01812        If length > 0, then result != NULL.  */
01813 
01814     /* Ensures that allocated >= needed.  Aborts through a jump to
01815        out_of_memory if needed is SIZE_MAX or otherwise too big.  */
01816 #define ENSURE_ALLOCATION(needed) \
01817     if ((needed) > allocated)                                                \
01818       {                                                                      \
01819         size_t memory_size;                                                  \
01820         DCHAR_T *memory;                                                     \
01821                                                                              \
01822         allocated = (allocated > 0 ? xtimes (allocated, 2) : 12);            \
01823         if ((needed) > allocated)                                            \
01824           allocated = (needed);                                              \
01825         memory_size = xtimes (allocated, sizeof (DCHAR_T));                  \
01826         if (size_overflow_p (memory_size))                                   \
01827           goto out_of_memory;                                                \
01828         if (result == resultbuf || result == NULL)                           \
01829           memory = (DCHAR_T *) malloc (memory_size);                         \
01830         else                                                                 \
01831           memory = (DCHAR_T *) realloc (result, memory_size);                \
01832         if (memory == NULL)                                                  \
01833           goto out_of_memory;                                                \
01834         if (result == resultbuf && length > 0)                               \
01835           DCHAR_CPY (memory, result, length);                                \
01836         result = memory;                                                     \
01837       }
01838 
01839     for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++)
01840       {
01841         if (cp != dp->dir_start)
01842           {
01843             size_t n = dp->dir_start - cp;
01844             size_t augmented_length = xsum (length, n);
01845 
01846             ENSURE_ALLOCATION (augmented_length);
01847             /* This copies a piece of FCHAR_T[] into a DCHAR_T[].  Here we
01848                need that the format string contains only ASCII characters
01849                if FCHAR_T and DCHAR_T are not the same type.  */
01850             if (sizeof (FCHAR_T) == sizeof (DCHAR_T))
01851               {
01852                 DCHAR_CPY (result + length, (const DCHAR_T *) cp, n);
01853                 length = augmented_length;
01854               }
01855             else
01856               {
01857                 do
01858                   result[length++] = (unsigned char) *cp++;
01859                 while (--n > 0);
01860               }
01861           }
01862         if (i == d.count)
01863           break;
01864 
01865         /* Execute a single directive.  */
01866         if (dp->conversion == '%')
01867           {
01868             size_t augmented_length;
01869 
01870             if (!(dp->arg_index == ARG_NONE))
01871               abort ();
01872             augmented_length = xsum (length, 1);
01873             ENSURE_ALLOCATION (augmented_length);
01874             result[length] = '%';
01875             length = augmented_length;
01876           }
01877         else
01878           {
01879             if (!(dp->arg_index != ARG_NONE))
01880               abort ();
01881 
01882             if (dp->conversion == 'n')
01883               {
01884                 switch (a.arg[dp->arg_index].type)
01885                   {
01886                   case TYPE_COUNT_SCHAR_POINTER:
01887                     *a.arg[dp->arg_index].a.a_count_schar_pointer = length;
01888                     break;
01889                   case TYPE_COUNT_SHORT_POINTER:
01890                     *a.arg[dp->arg_index].a.a_count_short_pointer = length;
01891                     break;
01892                   case TYPE_COUNT_INT_POINTER:
01893                     *a.arg[dp->arg_index].a.a_count_int_pointer = length;
01894                     break;
01895                   case TYPE_COUNT_LONGINT_POINTER:
01896                     *a.arg[dp->arg_index].a.a_count_longint_pointer = length;
01897                     break;
01898 #if HAVE_LONG_LONG_INT
01899                   case TYPE_COUNT_LONGLONGINT_POINTER:
01900                     *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length;
01901                     break;
01902 #endif
01903                   default:
01904                     abort ();
01905                   }
01906               }
01907 #if ENABLE_UNISTDIO
01908             /* The unistdio extensions.  */
01909             else if (dp->conversion == 'U')
01910               {
01911                 arg_type type = a.arg[dp->arg_index].type;
01912                 int flags = dp->flags;
01913                 int has_width;
01914                 size_t width;
01915                 int has_precision;
01916                 size_t precision;
01917 
01918                 has_width = 0;
01919                 width = 0;
01920                 if (dp->width_start != dp->width_end)
01921                   {
01922                     if (dp->width_arg_index != ARG_NONE)
01923                       {
01924                         int arg;
01925 
01926                         if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
01927                           abort ();
01928                         arg = a.arg[dp->width_arg_index].a.a_int;
01929                         if (arg < 0)
01930                           {
01931                             /* "A negative field width is taken as a '-' flag
01932                                 followed by a positive field width."  */
01933                             flags |= FLAG_LEFT;
01934                             width = (unsigned int) (-arg);
01935                           }
01936                         else
01937                           width = arg;
01938                       }
01939                     else
01940                       {
01941                         const FCHAR_T *digitp = dp->width_start;
01942 
01943                         do
01944                           width = xsum (xtimes (width, 10), *digitp++ - '0');
01945                         while (digitp != dp->width_end);
01946                       }
01947                     has_width = 1;
01948                   }
01949 
01950                 has_precision = 0;
01951                 precision = 0;
01952                 if (dp->precision_start != dp->precision_end)
01953                   {
01954                     if (dp->precision_arg_index != ARG_NONE)
01955                       {
01956                         int arg;
01957 
01958                         if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
01959                           abort ();
01960                         arg = a.arg[dp->precision_arg_index].a.a_int;
01961                         /* "A negative precision is taken as if the precision
01962                             were omitted."  */
01963                         if (arg >= 0)
01964                           {
01965                             precision = arg;
01966                             has_precision = 1;
01967                           }
01968                       }
01969                     else
01970                       {
01971                         const FCHAR_T *digitp = dp->precision_start + 1;
01972 
01973                         precision = 0;
01974                         while (digitp != dp->precision_end)
01975                           precision = xsum (xtimes (precision, 10), *digitp++ - '0');
01976                         has_precision = 1;
01977                       }
01978                   }
01979 
01980                 switch (type)
01981                   {
01982                   case TYPE_U8_STRING:
01983                     {
01984                       const uint8_t *arg = a.arg[dp->arg_index].a.a_u8_string;
01985                       const uint8_t *arg_end;
01986                       size_t characters;
01987 
01988                       if (has_precision)
01989                         {
01990                           /* Use only PRECISION characters, from the left.  */
01991                           arg_end = arg;
01992                           characters = 0;
01993                           for (; precision > 0; precision--)
01994                             {
01995                               int count = u8_strmblen (arg_end);
01996                               if (count == 0)
01997                                 break;
01998                               if (count < 0)
01999                                 {
02000                                   if (!(result == resultbuf || result == NULL))
02001                                     free (result);
02002                                   if (buf_malloced != NULL)
02003                                     free (buf_malloced);
02004                                   CLEANUP ();
02005                                   errno = EILSEQ;
02006                                   return NULL;
02007                                 }
02008                               arg_end += count;
02009                               characters++;
02010                             }
02011                         }
02012                       else if (has_width)
02013                         {
02014                           /* Use the entire string, and count the number of
02015                              characters.  */
02016                           arg_end = arg;
02017                           characters = 0;
02018                           for (;;)
02019                             {
02020                               int count = u8_strmblen (arg_end);
02021                               if (count == 0)
02022                                 break;
02023                               if (count < 0)
02024                                 {
02025                                   if (!(result == resultbuf || result == NULL))
02026                                     free (result);
02027                                   if (buf_malloced != NULL)
02028                                     free (buf_malloced);
02029                                   CLEANUP ();
02030                                   errno = EILSEQ;
02031                                   return NULL;
02032                                 }
02033                               arg_end += count;
02034                               characters++;
02035                             }
02036                         }
02037                       else
02038                         {
02039                           /* Use the entire string.  */
02040                           arg_end = arg + u8_strlen (arg);
02041                           /* The number of characters doesn't matter.  */
02042                           characters = 0;
02043                         }
02044 
02045                       if (has_width && width > characters
02046                           && !(dp->flags & FLAG_LEFT))
02047                         {
02048                           size_t n = width - characters;
02049                           ENSURE_ALLOCATION (xsum (length, n));
02050                           DCHAR_SET (result + length, ' ', n);
02051                           length += n;
02052                         }
02053 
02054 # if DCHAR_IS_UINT8_T
02055                       {
02056                         size_t n = arg_end - arg;
02057                         ENSURE_ALLOCATION (xsum (length, n));
02058                         DCHAR_CPY (result + length, arg, n);
02059                         length += n;
02060                       }
02061 # else
02062                       { /* Convert.  */
02063                         DCHAR_T *converted = result + length;
02064                         size_t converted_len = allocated - length;
02065 #  if DCHAR_IS_TCHAR
02066                         /* Convert from UTF-8 to locale encoding.  */
02067                         converted =
02068                           u8_conv_to_encoding (locale_charset (),
02069                                                iconveh_question_mark,
02070                                                arg, arg_end - arg, NULL,
02071                                                converted, &converted_len);
02072 #  else
02073                         /* Convert from UTF-8 to UTF-16/UTF-32.  */
02074                         converted =
02075                           U8_TO_DCHAR (arg, arg_end - arg,
02076                                        converted, &converted_len);
02077 #  endif
02078                         if (converted == NULL)
02079                           {
02080                             int saved_errno = errno;
02081                             if (!(result == resultbuf || result == NULL))
02082                               free (result);
02083                             if (buf_malloced != NULL)
02084                               free (buf_malloced);
02085                             CLEANUP ();
02086                             errno = saved_errno;
02087                             return NULL;
02088                           }
02089                         if (converted != result + length)
02090                           {
02091                             ENSURE_ALLOCATION (xsum (length, converted_len));
02092                             DCHAR_CPY (result + length, converted, converted_len);
02093                             free (converted);
02094                           }
02095                         length += converted_len;
02096                       }
02097 # endif
02098 
02099                       if (has_width && width > characters
02100                           && (dp->flags & FLAG_LEFT))
02101                         {
02102                           size_t n = width - characters;
02103                           ENSURE_ALLOCATION (xsum (length, n));
02104                           DCHAR_SET (result + length, ' ', n);
02105                           length += n;
02106                         }
02107                     }
02108                     break;
02109 
02110                   case TYPE_U16_STRING:
02111                     {
02112                       const uint16_t *arg = a.arg[dp->arg_index].a.a_u16_string;
02113                       const uint16_t *arg_end;
02114                       size_t characters;
02115 
02116                       if (has_precision)
02117                         {
02118                           /* Use only PRECISION characters, from the left.  */
02119                           arg_end = arg;
02120                           characters = 0;
02121                           for (; precision > 0; precision--)
02122                             {
02123                               int count = u16_strmblen (arg_end);
02124                               if (count == 0)
02125                                 break;
02126                               if (count < 0)
02127                                 {
02128                                   if (!(result == resultbuf || result == NULL))
02129                                     free (result);
02130                                   if (buf_malloced != NULL)
02131                                     free (buf_malloced);
02132                                   CLEANUP ();
02133                                   errno = EILSEQ;
02134                                   return NULL;
02135                                 }
02136                               arg_end += count;
02137                               characters++;
02138                             }
02139                         }
02140                       else if (has_width)
02141                         {
02142                           /* Use the entire string, and count the number of
02143                              characters.  */
02144                           arg_end = arg;
02145                           characters = 0;
02146                           for (;;)
02147                             {
02148                               int count = u16_strmblen (arg_end);
02149                               if (count == 0)
02150                                 break;
02151                               if (count < 0)
02152                                 {
02153                                   if (!(result == resultbuf || result == NULL))
02154                                     free (result);
02155                                   if (buf_malloced != NULL)
02156                                     free (buf_malloced);
02157                                   CLEANUP ();
02158                                   errno = EILSEQ;
02159                                   return NULL;
02160                                 }
02161                               arg_end += count;
02162                               characters++;
02163                             }
02164                         }
02165                       else
02166                         {
02167                           /* Use the entire string.  */
02168                           arg_end = arg + u16_strlen (arg);
02169                           /* The number of characters doesn't matter.  */
02170                           characters = 0;
02171                         }
02172 
02173                       if (has_width && width > characters
02174                           && !(dp->flags & FLAG_LEFT))
02175                         {
02176                           size_t n = width - characters;
02177                           ENSURE_ALLOCATION (xsum (length, n));
02178                           DCHAR_SET (result + length, ' ', n);
02179                           length += n;
02180                         }
02181 
02182 # if DCHAR_IS_UINT16_T
02183                       {
02184                         size_t n = arg_end - arg;
02185                         ENSURE_ALLOCATION (xsum (length, n));
02186                         DCHAR_CPY (result + length, arg, n);
02187                         length += n;
02188                       }
02189 # else
02190                       { /* Convert.  */
02191                         DCHAR_T *converted = result + length;
02192                         size_t converted_len = allocated - length;
02193 #  if DCHAR_IS_TCHAR
02194                         /* Convert from UTF-16 to locale encoding.  */
02195                         converted =
02196                           u16_conv_to_encoding (locale_charset (),
02197                                                 iconveh_question_mark,
02198                                                 arg, arg_end - arg, NULL,
02199                                                 converted, &converted_len);
02200 #  else
02201                         /* Convert from UTF-16 to UTF-8/UTF-32.  */
02202                         converted =
02203                           U16_TO_DCHAR (arg, arg_end - arg,
02204                                         converted, &converted_len);
02205 #  endif
02206                         if (converted == NULL)
02207                           {
02208                             int saved_errno = errno;
02209                             if (!(result == resultbuf || result == NULL))
02210                               free (result);
02211                             if (buf_malloced != NULL)
02212                               free (buf_malloced);
02213                             CLEANUP ();
02214                             errno = saved_errno;
02215                             return NULL;
02216                           }
02217                         if (converted != result + length)
02218                           {
02219                             ENSURE_ALLOCATION (xsum (length, converted_len));
02220                             DCHAR_CPY (result + length, converted, converted_len);
02221                             free (converted);
02222                           }
02223                         length += converted_len;
02224                       }
02225 # endif
02226 
02227                       if (has_width && width > characters
02228                           && (dp->flags & FLAG_LEFT))
02229                         {
02230                           size_t n = width - characters;
02231                           ENSURE_ALLOCATION (xsum (length, n));
02232                           DCHAR_SET (result + length, ' ', n);
02233                           length += n;
02234                         }
02235                     }
02236                     break;
02237 
02238                   case TYPE_U32_STRING:
02239                     {
02240                       const uint32_t *arg = a.arg[dp->arg_index].a.a_u32_string;
02241                       const uint32_t *arg_end;
02242                       size_t characters;
02243 
02244                       if (has_precision)
02245                         {
02246                           /* Use only PRECISION characters, from the left.  */
02247                           arg_end = arg;
02248                           characters = 0;
02249                           for (; precision > 0; precision--)
02250                             {
02251                               int count = u32_strmblen (arg_end);
02252                               if (count == 0)
02253                                 break;
02254                               if (count < 0)
02255                                 {
02256                                   if (!(result == resultbuf || result == NULL))
02257                                     free (result);
02258                                   if (buf_malloced != NULL)
02259                                     free (buf_malloced);
02260                                   CLEANUP ();
02261                                   errno = EILSEQ;
02262                                   return NULL;
02263                                 }
02264                               arg_end += count;
02265                               characters++;
02266                             }
02267                         }
02268                       else if (has_width)
02269                         {
02270                           /* Use the entire string, and count the number of
02271                              characters.  */
02272                           arg_end = arg;
02273                           characters = 0;
02274                           for (;;)
02275                             {
02276                               int count = u32_strmblen (arg_end);
02277                               if (count == 0)
02278                                 break;
02279                               if (count < 0)
02280                                 {
02281                                   if (!(result == resultbuf || result == NULL))
02282                                     free (result);
02283                                   if (buf_malloced != NULL)
02284                                     free (buf_malloced);
02285                                   CLEANUP ();
02286                                   errno = EILSEQ;
02287                                   return NULL;
02288                                 }
02289                               arg_end += count;
02290                               characters++;
02291                             }
02292                         }
02293                       else
02294                         {
02295                           /* Use the entire string.  */
02296                           arg_end = arg + u32_strlen (arg);
02297                           /* The number of characters doesn't matter.  */
02298                           characters = 0;
02299                         }
02300 
02301                       if (has_width && width > characters
02302                           && !(dp->flags & FLAG_LEFT))
02303                         {
02304                           size_t n = width - characters;
02305                           ENSURE_ALLOCATION (xsum (length, n));
02306                           DCHAR_SET (result + length, ' ', n);
02307                           length += n;
02308                         }
02309 
02310 # if DCHAR_IS_UINT32_T
02311                       {
02312                         size_t n = arg_end - arg;
02313                         ENSURE_ALLOCATION (xsum (length, n));
02314                         DCHAR_CPY (result + length, arg, n);
02315                         length += n;
02316                       }
02317 # else
02318                       { /* Convert.  */
02319                         DCHAR_T *converted = result + length;
02320                         size_t converted_len = allocated - length;
02321 #  if DCHAR_IS_TCHAR
02322                         /* Convert from UTF-32 to locale encoding.  */
02323                         converted =
02324                           u32_conv_to_encoding (locale_charset (),
02325                                                 iconveh_question_mark,
02326                                                 arg, arg_end - arg, NULL,
02327                                                 converted, &converted_len);
02328 #  else
02329                         /* Convert from UTF-32 to UTF-8/UTF-16.  */
02330                         converted =
02331                           U32_TO_DCHAR (arg, arg_end - arg,
02332                                         converted, &converted_len);
02333 #  endif
02334                         if (converted == NULL)
02335                           {
02336                             int saved_errno = errno;
02337                             if (!(result == resultbuf || result == NULL))
02338                               free (result);
02339                             if (buf_malloced != NULL)
02340                               free (buf_malloced);
02341                             CLEANUP ();
02342                             errno = saved_errno;
02343                             return NULL;
02344                           }
02345                         if (converted != result + length)
02346                           {
02347                             ENSURE_ALLOCATION (xsum (length, converted_len));
02348                             DCHAR_CPY (result + length, converted, converted_len);
02349                             free (converted);
02350                           }
02351                         length += converted_len;
02352                       }
02353 # endif
02354 
02355                       if (has_width && width > characters
02356                           && (dp->flags & FLAG_LEFT))
02357                         {
02358                           size_t n = width - characters;
02359                           ENSURE_ALLOCATION (xsum (length, n));
02360                           DCHAR_SET (result + length, ' ', n);
02361                           length += n;
02362                         }
02363                     }
02364                     break;
02365 
02366                   default:
02367                     abort ();
02368                   }
02369               }
02370 #endif
02371 #if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && HAVE_WCHAR_T
02372             else if (dp->conversion == 's'
02373 # if WIDE_CHAR_VERSION
02374                      && a.arg[dp->arg_index].type != TYPE_WIDE_STRING
02375 # else
02376                      && a.arg[dp->arg_index].type == TYPE_WIDE_STRING
02377 # endif
02378                     )
02379               {
02380                 /* The normal handling of the 's' directive below requires
02381                    allocating a temporary buffer.  The determination of its
02382                    length (tmp_length), in the case when a precision is
02383                    specified, below requires a conversion between a char[]
02384                    string and a wchar_t[] wide string.  It could be done, but
02385                    we have no guarantee that the implementation of sprintf will
02386                    use the exactly same algorithm.  Without this guarantee, it
02387                    is possible to have buffer overrun bugs.  In order to avoid
02388                    such bugs, we implement the entire processing of the 's'
02389                    directive ourselves.  */
02390                 int flags = dp->flags;
02391                 int has_width;
02392                 size_t width;
02393                 int has_precision;
02394                 size_t precision;
02395 
02396                 has_width = 0;
02397                 width = 0;
02398                 if (dp->width_start != dp->width_end)
02399                   {
02400                     if (dp->width_arg_index != ARG_NONE)
02401                       {
02402                         int arg;
02403 
02404                         if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
02405                           abort ();
02406                         arg = a.arg[dp->width_arg_index].a.a_int;
02407                         if (arg < 0)
02408                           {
02409                             /* "A negative field width is taken as a '-' flag
02410                                 followed by a positive field width."  */
02411                             flags |= FLAG_LEFT;
02412                             width = (unsigned int) (-arg);
02413                           }
02414                         else
02415                           width = arg;
02416                       }
02417                     else
02418                       {
02419                         const FCHAR_T *digitp = dp->width_start;
02420 
02421                         do
02422                           width = xsum (xtimes (width, 10), *digitp++ - '0');
02423                         while (digitp != dp->width_end);
02424                       }
02425                     has_width = 1;
02426                   }
02427 
02428                 has_precision = 0;
02429                 precision = 6;
02430                 if (dp->precision_start != dp->precision_end)
02431                   {
02432                     if (dp->precision_arg_index != ARG_NONE)
02433                       {
02434                         int arg;
02435 
02436                         if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
02437                           abort ();
02438                         arg = a.arg[dp->precision_arg_index].a.a_int;
02439                         /* "A negative precision is taken as if the precision
02440                             were omitted."  */
02441                         if (arg >= 0)
02442                           {
02443                             precision = arg;
02444                             has_precision = 1;
02445                           }
02446                       }
02447                     else
02448                       {
02449                         const FCHAR_T *digitp = dp->precision_start + 1;
02450 
02451                         precision = 0;
02452                         while (digitp != dp->precision_end)
02453                           precision = xsum (xtimes (precision, 10), *digitp++ - '0');
02454                         has_precision = 1;
02455                       }
02456                   }
02457 
02458 # if WIDE_CHAR_VERSION
02459                 /* %s in vasnwprintf.  See the specification of fwprintf.  */
02460                 {
02461                   const char *arg = a.arg[dp->arg_index].a.a_string;
02462                   const char *arg_end;
02463                   size_t characters;
02464 
02465                   if (has_precision)
02466                     {
02467                       /* Use only as many bytes as needed to produce PRECISION
02468                          wide characters, from the left.  */
02469 #  if HAVE_MBRTOWC
02470                       mbstate_t state;
02471                       memset (&state, '\0', sizeof (mbstate_t));
02472 #  endif
02473                       arg_end = arg;
02474                       characters = 0;
02475                       for (; precision > 0; precision--)
02476                         {
02477                           int count;
02478 #  if HAVE_MBRTOWC
02479                           count = mbrlen (arg_end, MB_CUR_MAX, &state);
02480 #  else
02481                           count = mblen (arg_end, MB_CUR_MAX);
02482 #  endif
02483                           if (count == 0)
02484                             /* Found the terminating NUL.  */
02485                             break;
02486                           if (count < 0)
02487                             {
02488                               /* Invalid or incomplete multibyte character.  */
02489                               if (!(result == resultbuf || result == NULL))
02490                                 free (result);
02491                               if (buf_malloced != NULL)
02492                                 free (buf_malloced);
02493                               CLEANUP ();
02494                               errno = EILSEQ;
02495                               return NULL;
02496                             }
02497                           arg_end += count;
02498                           characters++;
02499                         }
02500                     }
02501                   else if (has_width)
02502                     {
02503                       /* Use the entire string, and count the number of wide
02504                          characters.  */
02505 #  if HAVE_MBRTOWC
02506                       mbstate_t state;
02507                       memset (&state, '\0', sizeof (mbstate_t));
02508 #  endif
02509                       arg_end = arg;
02510                       characters = 0;
02511                       for (;;)
02512                         {
02513                           int count;
02514 #  if HAVE_MBRTOWC
02515                           count = mbrlen (arg_end, MB_CUR_MAX, &state);
02516 #  else
02517                           count = mblen (arg_end, MB_CUR_MAX);
02518 #  endif
02519                           if (count == 0)
02520                             /* Found the terminating NUL.  */
02521                             break;
02522                           if (count < 0)
02523                             {
02524                               /* Invalid or incomplete multibyte character.  */
02525                               if (!(result == resultbuf || result == NULL))
02526                                 free (result);
02527                               if (buf_malloced != NULL)
02528                                 free (buf_malloced);
02529                               CLEANUP ();
02530                               errno = EILSEQ;
02531                               return NULL;
02532                             }
02533                           arg_end += count;
02534                           characters++;
02535                         }
02536                     }
02537                   else
02538                     {
02539                       /* Use the entire string.  */
02540                       arg_end = arg + strlen (arg);
02541                       /* The number of characters doesn't matter.  */
02542                       characters = 0;
02543                     }
02544 
02545                   if (has_width && width > characters
02546                       && !(dp->flags & FLAG_LEFT))
02547                     {
02548                       size_t n = width - characters;
02549                       ENSURE_ALLOCATION (xsum (length, n));
02550                       DCHAR_SET (result + length, ' ', n);
02551                       length += n;
02552                     }
02553 
02554                   if (has_precision || has_width)
02555                     {
02556                       /* We know the number of wide characters in advance.  */
02557                       size_t remaining;
02558 #  if HAVE_MBRTOWC
02559                       mbstate_t state;
02560                       memset (&state, '\0', sizeof (mbstate_t));
02561 #  endif
02562                       ENSURE_ALLOCATION (xsum (length, characters));
02563                       for (remaining = characters; remaining > 0; remaining--)
02564                         {
02565                           wchar_t wc;
02566                           int count;
02567 #  if HAVE_MBRTOWC
02568                           count = mbrtowc (&wc, arg, arg_end - arg, &state);
02569 #  else
02570                           count = mbtowc (&wc, arg, arg_end - arg);
02571 #  endif
02572                           if (count <= 0)
02573                             /* mbrtowc not consistent with mbrlen, or mbtowc
02574                                not consistent with mblen.  */
02575                             abort ();
02576                           result[length++] = wc;
02577                           arg += count;
02578                         }
02579                       if (!(arg == arg_end))
02580                         abort ();
02581                     }
02582                   else
02583                     {
02584 #  if HAVE_MBRTOWC
02585                       mbstate_t state;
02586                       memset (&state, '\0', sizeof (mbstate_t));
02587 #  endif
02588                       while (arg < arg_end)
02589                         {
02590                           wchar_t wc;
02591                           int count;
02592 #  if HAVE_MBRTOWC
02593                           count = mbrtowc (&wc, arg, arg_end - arg, &state);
02594 #  else
02595                           count = mbtowc (&wc, arg, arg_end - arg);
02596 #  endif
02597                           if (count <= 0)
02598                             /* mbrtowc not consistent with mbrlen, or mbtowc
02599                                not consistent with mblen.  */
02600                             abort ();
02601                           ENSURE_ALLOCATION (xsum (length, 1));
02602                           result[length++] = wc;
02603                           arg += count;
02604                         }
02605                     }
02606 
02607                   if (has_width && width > characters
02608                       && (dp->flags & FLAG_LEFT))
02609                     {
02610                       size_t n = width - characters;
02611                       ENSURE_ALLOCATION (xsum (length, n));
02612                       DCHAR_SET (result + length, ' ', n);
02613                       length += n;
02614                     }
02615                 }
02616 # else
02617                 /* %ls in vasnprintf.  See the specification of fprintf.  */
02618                 {
02619                   const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
02620                   const wchar_t *arg_end;
02621                   size_t characters;
02622 #  if !DCHAR_IS_TCHAR
02623                   /* This code assumes that TCHAR_T is 'char'.  */
02624                   typedef int TCHAR_T_verify[2 * (sizeof (TCHAR_T) == 1) - 1];
02625                   TCHAR_T *tmpsrc;
02626                   DCHAR_T *tmpdst;
02627                   size_t tmpdst_len;
02628 #  endif
02629                   size_t w;
02630 
02631                   if (has_precision)
02632                     {
02633                       /* Use only as many wide characters as needed to produce
02634                          at most PRECISION bytes, from the left.  */
02635 #  if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
02636                       mbstate_t state;
02637                       memset (&state, '\0', sizeof (mbstate_t));
02638 #  endif
02639                       arg_end = arg;
02640                       characters = 0;
02641                       while (precision > 0)
02642                         {
02643                           char cbuf[64]; /* Assume MB_CUR_MAX <= 64.  */
02644                           int count;
02645 
02646                           if (*arg_end == 0)
02647                             /* Found the terminating null wide character.  */
02648                             break;
02649 #  if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
02650                           count = wcrtomb (cbuf, *arg_end, &state);
02651 #  else
02652                           count = wctomb (cbuf, *arg_end);
02653 #  endif
02654                           if (count < 0)
02655                             {
02656                               /* Cannot convert.  */
02657                               if (!(result == resultbuf || result == NULL))
02658                                 free (result);
02659                               if (buf_malloced != NULL)
02660                                 free (buf_malloced);
02661                               CLEANUP ();
02662                               errno = EILSEQ;
02663                               return NULL;
02664                             }
02665                           if (precision < count)
02666                             break;
02667                           arg_end++;
02668                           characters += count;
02669                           precision -= count;
02670                         }
02671                     }
02672 #  if DCHAR_IS_TCHAR
02673                   else if (has_width)
02674 #  else
02675                   else
02676 #  endif
02677                     {
02678                       /* Use the entire string, and count the number of
02679                          bytes.  */
02680 #  if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
02681                       mbstate_t state;
02682                       memset (&state, '\0', sizeof (mbstate_t));
02683 #  endif
02684                       arg_end = arg;
02685                       characters = 0;
02686                       for (;;)
02687                         {
02688                           char cbuf[64]; /* Assume MB_CUR_MAX <= 64.  */
02689                           int count;
02690 
02691                           if (*arg_end == 0)
02692                             /* Found the terminating null wide character.  */
02693                             break;
02694 #  if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
02695                           count = wcrtomb (cbuf, *arg_end, &state);
02696 #  else
02697                           count = wctomb (cbuf, *arg_end);
02698 #  endif
02699                           if (count < 0)
02700                             {
02701                               /* Cannot convert.  */
02702                               if (!(result == resultbuf || result == NULL))
02703                                 free (result);
02704                               if (buf_malloced != NULL)
02705                                 free (buf_malloced);
02706                               CLEANUP ();
02707                               errno = EILSEQ;
02708                               return NULL;
02709                             }
02710                           arg_end++;
02711                           characters += count;
02712                         }
02713                     }
02714 #  if DCHAR_IS_TCHAR
02715                   else
02716                     {
02717                       /* Use the entire string.  */
02718                       arg_end = arg + local_wcslen (arg);
02719                       /* The number of bytes doesn't matter.  */
02720                       characters = 0;
02721                     }
02722 #  endif
02723 
02724 #  if !DCHAR_IS_TCHAR
02725                   /* Convert the string into a piece of temporary memory.  */
02726                   tmpsrc = (TCHAR_T *) malloc (characters * sizeof (TCHAR_T));
02727                   if (tmpsrc == NULL)
02728                     goto out_of_memory;
02729                   {
02730                     TCHAR_T *tmpptr = tmpsrc;
02731                     size_t remaining;
02732 #   if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
02733                     mbstate_t state;
02734                     memset (&state, '\0', sizeof (mbstate_t));
02735 #   endif
02736                     for (remaining = characters; remaining > 0; )
02737                       {
02738                         char cbuf[64]; /* Assume MB_CUR_MAX <= 64.  */
02739                         int count;
02740 
02741                         if (*arg == 0)
02742                           abort ();
02743 #   if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
02744                         count = wcrtomb (cbuf, *arg, &state);
02745 #   else
02746                         count = wctomb (cbuf, *arg);
02747 #   endif
02748                         if (count <= 0)
02749                           /* Inconsistency.  */
02750                           abort ();
02751                         memcpy (tmpptr, cbuf, count);
02752                         tmpptr += count;
02753                         arg++;
02754                         remaining -= count;
02755                       }
02756                     if (!(arg == arg_end))
02757                       abort ();
02758                   }
02759 
02760                   /* Convert from TCHAR_T[] to DCHAR_T[].  */
02761                   tmpdst =
02762                     DCHAR_CONV_FROM_ENCODING (locale_charset (),
02763                                               iconveh_question_mark,
02764                                               tmpsrc, characters,
02765                                               NULL,
02766                                               NULL, &tmpdst_len);
02767                   if (tmpdst == NULL)
02768                     {
02769                       int saved_errno = errno;
02770                       free (tmpsrc);
02771                       if (!(result == resultbuf || result == NULL))
02772                         free (result);
02773                       if (buf_malloced != NULL)
02774                         free (buf_malloced);
02775                       CLEANUP ();
02776                       errno = saved_errno;
02777                       return NULL;
02778                     }
02779                   free (tmpsrc);
02780 #  endif
02781 
02782                   if (has_width)
02783                     {
02784 #  if ENABLE_UNISTDIO
02785                       /* Outside POSIX, it's preferrable to compare the width
02786                          against the number of _characters_ of the converted
02787                          value.  */
02788                       w = DCHAR_MBSNLEN (result + length, characters);
02789 #  else
02790                       /* The width is compared against the number of _bytes_
02791                          of the converted value, says POSIX.  */
02792                       w = characters;
02793 #  endif
02794                     }
02795                   else
02796                     /* w doesn't matter.  */
02797                     w = 0;
02798 
02799                   if (has_width && width > w
02800                       && !(dp->flags & FLAG_LEFT))
02801                     {
02802                       size_t n = width - w;
02803                       ENSURE_ALLOCATION (xsum (length, n));
02804                       DCHAR_SET (result + length, ' ', n);
02805                       length += n;
02806                     }
02807 
02808 #  if DCHAR_IS_TCHAR
02809                   if (has_precision || has_width)
02810                     {
02811                       /* We know the number of bytes in advance.  */
02812                       size_t remaining;
02813 #   if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
02814                       mbstate_t state;
02815                       memset (&state, '\0', sizeof (mbstate_t));
02816 #   endif
02817                       ENSURE_ALLOCATION (xsum (length, characters));
02818                       for (remaining = characters; remaining > 0; )
02819                         {
02820                           char cbuf[64]; /* Assume MB_CUR_MAX <= 64.  */
02821                           int count;
02822 
02823                           if (*arg == 0)
02824                             abort ();
02825 #   if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
02826                           count = wcrtomb (cbuf, *arg, &state);
02827 #   else
02828                           count = wctomb (cbuf, *arg);
02829 #   endif
02830                           if (count <= 0)
02831                             /* Inconsistency.  */
02832                             abort ();
02833                           memcpy (result + length, cbuf, count);
02834                           length += count;
02835                           arg++;
02836                           remaining -= count;
02837                         }
02838                       if (!(arg == arg_end))
02839                         abort ();
02840                     }
02841                   else
02842                     {
02843 #   if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
02844                       mbstate_t state;
02845                       memset (&state, '\0', sizeof (mbstate_t));
02846 #   endif
02847                       while (arg < arg_end)
02848                         {
02849                           char cbuf[64]; /* Assume MB_CUR_MAX <= 64.  */
02850                           int count;
02851 
02852                           if (*arg == 0)
02853                             abort ();
02854 #   if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
02855                           count = wcrtomb (cbuf, *arg, &state);
02856 #   else
02857                           count = wctomb (cbuf, *arg);
02858 #   endif
02859                           if (count <= 0)
02860                             {
02861                               /* Cannot convert.  */
02862                               if (!(result == resultbuf || result == NULL))
02863                                 free (result);
02864                               if (buf_malloced != NULL)
02865                                 free (buf_malloced);
02866                               CLEANUP ();
02867                               errno = EILSEQ;
02868                               return NULL;
02869                             }
02870                           ENSURE_ALLOCATION (xsum (length, count));
02871                           memcpy (result + length, cbuf, count);
02872                           length += count;
02873                           arg++;
02874                         }
02875                     }
02876 #  else
02877                   ENSURE_ALLOCATION (xsum (length, tmpdst_len));
02878                   DCHAR_CPY (result + length, tmpdst, tmpdst_len);
02879                   free (tmpdst);
02880                   length += tmpdst_len;
02881 #  endif
02882 
02883                   if (has_width && width > w
02884                       && (dp->flags & FLAG_LEFT))
02885                     {
02886                       size_t n = width - w;
02887                       ENSURE_ALLOCATION (xsum (length, n));
02888                       DCHAR_SET (result + length, ' ', n);
02889                       length += n;
02890                     }
02891                 }
02892 # endif
02893               }
02894 #endif
02895 #if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL
02896             else if ((dp->conversion == 'a' || dp->conversion == 'A')
02897 # if !(NEED_PRINTF_DIRECTIVE_A || (NEED_PRINTF_LONG_DOUBLE && NEED_PRINTF_DOUBLE))
02898                      && (0
02899 #  if NEED_PRINTF_DOUBLE
02900                          || a.arg[dp->arg_index].type == TYPE_DOUBLE
02901 #  endif
02902 #  if NEED_PRINTF_LONG_DOUBLE
02903                          || a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
02904 #  endif
02905                         )
02906 # endif
02907                     )
02908               {
02909                 arg_type type = a.arg[dp->arg_index].type;
02910                 int flags = dp->flags;
02911                 int has_width;
02912                 size_t width;
02913                 int has_precision;
02914                 size_t precision;
02915                 size_t tmp_length;
02916                 DCHAR_T tmpbuf[700];
02917                 DCHAR_T *tmp;
02918                 DCHAR_T *pad_ptr;
02919                 DCHAR_T *p;
02920 
02921                 has_width = 0;
02922                 width = 0;
02923                 if (dp->width_start != dp->width_end)
02924                   {
02925                     if (dp->width_arg_index != ARG_NONE)
02926                       {
02927                         int arg;
02928 
02929                         if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
02930                           abort ();
02931                         arg = a.arg[dp->width_arg_index].a.a_int;
02932                         if (arg < 0)
02933                           {
02934                             /* "A negative field width is taken as a '-' flag
02935                                 followed by a positive field width."  */
02936                             flags |= FLAG_LEFT;
02937                             width = (unsigned int) (-arg);
02938                           }
02939                         else
02940                           width = arg;
02941                       }
02942                     else
02943                       {
02944                         const FCHAR_T *digitp = dp->width_start;
02945 
02946                         do
02947                           width = xsum (xtimes (width, 10), *digitp++ - '0');
02948                         while (digitp != dp->width_end);
02949                       }
02950                     has_width = 1;
02951                   }
02952 
02953                 has_precision = 0;
02954                 precision = 0;
02955                 if (dp->precision_start != dp->precision_end)
02956                   {
02957                     if (dp->precision_arg_index != ARG_NONE)
02958                       {
02959                         int arg;
02960 
02961                         if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
02962                           abort ();
02963                         arg = a.arg[dp->precision_arg_index].a.a_int;
02964                         /* "A negative precision is taken as if the precision
02965                             were omitted."  */
02966                         if (arg >= 0)
02967                           {
02968                             precision = arg;
02969                             has_precision = 1;
02970                           }
02971                       }
02972                     else
02973                       {
02974                         const FCHAR_T *digitp = dp->precision_start + 1;
02975 
02976                         precision = 0;
02977                         while (digitp != dp->precision_end)
02978                           precision = xsum (xtimes (precision, 10), *digitp++ - '0');
02979                         has_precision = 1;
02980                       }
02981                   }
02982 
02983                 /* Allocate a temporary buffer of sufficient size.  */
02984                 if (type == TYPE_LONGDOUBLE)
02985                   tmp_length =
02986                     (unsigned int) ((LDBL_DIG + 1)
02987                                     * 0.831 /* decimal -> hexadecimal */
02988                                    )
02989                     + 1; /* turn floor into ceil */
02990                 else
02991                   tmp_length =
02992                     (unsigned int) ((DBL_DIG + 1)
02993                                     * 0.831 /* decimal -> hexadecimal */
02994                                    )
02995                     + 1; /* turn floor into ceil */
02996                 if (tmp_length < precision)
02997                   tmp_length = precision;
02998                 /* Account for sign, decimal point etc. */
02999                 tmp_length = xsum (tmp_length, 12);
03000 
03001                 if (tmp_length < width)
03002                   tmp_length = width;
03003 
03004                 tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
03005 
03006                 if (tmp_length <= sizeof (tmpbuf) / sizeof (DCHAR_T))
03007                   tmp = tmpbuf;
03008                 else
03009                   {
03010                     size_t tmp_memsize = xtimes (tmp_length, sizeof (DCHAR_T));
03011 
03012                     if (size_overflow_p (tmp_memsize))
03013                       /* Overflow, would lead to out of memory.  */
03014                       goto out_of_memory;
03015                     tmp = (DCHAR_T *) malloc (tmp_memsize);
03016                     if (tmp == NULL)
03017                       /* Out of memory.  */
03018                       goto out_of_memory;
03019                   }
03020 
03021                 pad_ptr = NULL;
03022                 p = tmp;
03023                 if (type == TYPE_LONGDOUBLE)
03024                   {
03025 # if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE
03026                     long double arg = a.arg[dp->arg_index].a.a_longdouble;
03027 
03028                     if (isnanl (arg))
03029                       {
03030                         if (dp->conversion == 'A')
03031                           {
03032                             *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
03033                           }
03034                         else
03035                           {
03036                             *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
03037                           }
03038                       }
03039                     else
03040                       {
03041                         int sign = 0;
03042                         DECL_LONG_DOUBLE_ROUNDING
03043 
03044                         BEGIN_LONG_DOUBLE_ROUNDING ();
03045 
03046                         if (signbit (arg)) /* arg < 0.0L or negative zero */
03047                           {
03048                             sign = -1;
03049                             arg = -arg;
03050                           }
03051 
03052                         if (sign < 0)
03053                           *p++ = '-';
03054                         else if (flags & FLAG_SHOWSIGN)
03055                           *p++ = '+';
03056                         else if (flags & FLAG_SPACE)
03057                           *p++ = ' ';
03058 
03059                         if (arg > 0.0L && arg + arg == arg)
03060                           {
03061                             if (dp->conversion == 'A')
03062                               {
03063                                 *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
03064                               }
03065                             else
03066                               {
03067                                 *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
03068                               }
03069                           }
03070                         else
03071                           {
03072                             int exponent;
03073                             long double mantissa;
03074 
03075                             if (arg > 0.0L)
03076                               mantissa = printf_frexpl (arg, &exponent);
03077                             else
03078                               {
03079                                 exponent = 0;
03080                                 mantissa = 0.0L;
03081                               }
03082 
03083                             if (has_precision
03084                                 && precision < (unsigned int) ((LDBL_DIG + 1) * 0.831) + 1)
03085                               {
03086                                 /* Round the mantissa.  */
03087                                 long double tail = mantissa;
03088                                 size_t q;
03089 
03090                                 for (q = precision; ; q--)
03091                                   {
03092                                     int digit = (int) tail;
03093                                     tail -= digit;
03094                                     if (q == 0)
03095                                       {
03096                                         if (digit & 1 ? tail >= 0.5L : tail > 0.5L)
03097                                           tail = 1 - tail;
03098                                         else
03099                                           tail = - tail;
03100                                         break;
03101                                       }
03102                                     tail *= 16.0L;
03103                                   }
03104                                 if (tail != 0.0L)
03105                                   for (q = precision; q > 0; q--)
03106                                     tail *= 0.0625L;
03107                                 mantissa += tail;
03108                               }
03109 
03110                             *p++ = '0';
03111                             *p++ = dp->conversion - 'A' + 'X';
03112                             pad_ptr = p;
03113                             {
03114                               int digit;
03115 
03116                               digit = (int) mantissa;
03117                               mantissa -= digit;
03118                               *p++ = '0' + digit;
03119                               if ((flags & FLAG_ALT)
03120                                   || mantissa > 0.0L || precision > 0)
03121                                 {
03122                                   *p++ = decimal_point_char ();
03123                                   /* This loop terminates because we assume
03124                                      that FLT_RADIX is a power of 2.  */
03125                                   while (mantissa > 0.0L)
03126                                     {
03127                                       mantissa *= 16.0L;
03128                                       digit = (int) mantissa;
03129                                       mantissa -= digit;
03130                                       *p++ = digit
03131                                              + (digit < 10
03132                                                 ? '0'
03133                                                 : dp->conversion - 10);
03134                                       if (precision > 0)
03135                                         precision--;
03136                                     }
03137                                   while (precision > 0)
03138                                     {
03139                                       *p++ = '0';
03140                                       precision--;
03141                                     }
03142                                 }
03143                               }
03144                               *p++ = dp->conversion - 'A' + 'P';
03145 #  if WIDE_CHAR_VERSION
03146                               {
03147                                 static const wchar_t decimal_format[] =
03148                                   { '%', '+', 'd', '\0' };
03149                                 SNPRINTF (p, 6 + 1, decimal_format, exponent);
03150                               }
03151                               while (*p != '\0')
03152                                 p++;
03153 #  else
03154                               if (sizeof (DCHAR_T) == 1)
03155                                 {
03156                                   sprintf ((char *) p, "%+d", exponent);
03157                                   while (*p != '\0')
03158                                     p++;
03159                                 }
03160                               else
03161                                 {
03162                                   char expbuf[6 + 1];
03163                                   const char *ep;
03164                                   sprintf (expbuf, "%+d", exponent);
03165                                   for (ep = expbuf; (*p = *ep) != '\0'; ep++)
03166                                     p++;
03167                                 }
03168 #  endif
03169                           }
03170 
03171                         END_LONG_DOUBLE_ROUNDING ();
03172                       }
03173 # else
03174                     abort ();
03175 # endif
03176                   }
03177                 else
03178                   {
03179 # if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE
03180                     double arg = a.arg[dp->arg_index].a.a_double;
03181 
03182                     if (isnand (arg))
03183                       {
03184                         if (dp->conversion == 'A')
03185                           {
03186                             *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
03187                           }
03188                         else
03189                           {
03190                             *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
03191                           }
03192                       }
03193                     else
03194                       {
03195                         int sign = 0;
03196 
03197                         if (signbit (arg)) /* arg < 0.0 or negative zero */
03198                           {
03199                             sign = -1;
03200                             arg = -arg;
03201                           }
03202 
03203                         if (sign < 0)
03204                           *p++ = '-';
03205                         else if (flags & FLAG_SHOWSIGN)
03206                           *p++ = '+';
03207                         else if (flags & FLAG_SPACE)
03208                           *p++ = ' ';
03209 
03210                         if (arg > 0.0 && arg + arg == arg)
03211                           {
03212                             if (dp->conversion == 'A')
03213                               {
03214                                 *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
03215                               }
03216                             else
03217                               {
03218                                 *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
03219                               }
03220                           }
03221                         else
03222                           {
03223                             int exponent;
03224                             double mantissa;
03225 
03226                             if (arg > 0.0)
03227                               mantissa = printf_frexp (arg, &exponent);
03228                             else
03229                               {
03230                                 exponent = 0;
03231                                 mantissa = 0.0;
03232                               }
03233 
03234                             if (has_precision
03235                                 && precision < (unsigned int) ((DBL_DIG + 1) * 0.831) + 1)
03236                               {
03237                                 /* Round the mantissa.  */
03238                                 double tail = mantissa;
03239                                 size_t q;
03240 
03241                                 for (q = precision; ; q--)
03242                                   {
03243                                     int digit = (int) tail;
03244                                     tail -= digit;
03245                                     if (q == 0)
03246                                       {
03247                                         if (digit & 1 ? tail >= 0.5 : tail > 0.5)
03248                                           tail = 1 - tail;
03249                                         else
03250                                           tail = - tail;
03251                                         break;
03252                                       }
03253                                     tail *= 16.0;
03254                                   }
03255                                 if (tail != 0.0)
03256                                   for (q = precision; q > 0; q--)
03257                                     tail *= 0.0625;
03258                                 mantissa += tail;
03259                               }
03260 
03261                             *p++ = '0';
03262                             *p++ = dp->conversion - 'A' + 'X';
03263                             pad_ptr = p;
03264                             {
03265                               int digit;
03266 
03267                               digit = (int) mantissa;
03268                               mantissa -= digit;
03269                               *p++ = '0' + digit;
03270                               if ((flags & FLAG_ALT)
03271                                   || mantissa > 0.0 || precision > 0)
03272                                 {
03273                                   *p++ = decimal_point_char ();
03274                                   /* This loop terminates because we assume
03275                                      that FLT_RADIX is a power of 2.  */
03276                                   while (mantissa > 0.0)
03277                                     {
03278                                       mantissa *= 16.0;
03279                                       digit = (int) mantissa;
03280                                       mantissa -= digit;
03281                                       *p++ = digit
03282                                              + (digit < 10
03283                                                 ? '0'
03284                                                 : dp->conversion - 10);
03285                                       if (precision > 0)
03286                                         precision--;
03287                                     }
03288                                   while (precision > 0)
03289                                     {
03290                                       *p++ = '0';
03291                                       precision--;
03292                                     }
03293                                 }
03294                               }
03295                               *p++ = dp->conversion - 'A' + 'P';
03296 #  if WIDE_CHAR_VERSION
03297                               {
03298                                 static const wchar_t decimal_format[] =
03299                                   { '%', '+', 'd', '\0' };
03300                                 SNPRINTF (p, 6 + 1, decimal_format, exponent);
03301                               }
03302                               while (*p != '\0')
03303                                 p++;
03304 #  else
03305                               if (sizeof (DCHAR_T) == 1)
03306                                 {
03307                                   sprintf ((char *) p, "%+d", exponent);
03308                                   while (*p != '\0')
03309                                     p++;
03310                                 }
03311                               else
03312                                 {
03313                                   char expbuf[6 + 1];
03314                                   const char *ep;
03315                                   sprintf (expbuf, "%+d", exponent);
03316                                   for (ep = expbuf; (*p = *ep) != '\0'; ep++)
03317                                     p++;
03318                                 }
03319 #  endif
03320                           }
03321                       }
03322 # else
03323                     abort ();
03324 # endif
03325                   }
03326                 /* The generated string now extends from tmp to p, with the
03327                    zero padding insertion point being at pad_ptr.  */
03328                 if (has_width && p - tmp < width)
03329                   {
03330                     size_t pad = width - (p - tmp);
03331                     DCHAR_T *end = p + pad;
03332 
03333                     if (flags & FLAG_LEFT)
03334                       {
03335                         /* Pad with spaces on the right.  */
03336                         for (; pad > 0; pad--)
03337                           *p++ = ' ';
03338                       }
03339                     else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
03340                       {
03341                         /* Pad with zeroes.  */
03342                         DCHAR_T *q = end;
03343 
03344                         while (p > pad_ptr)
03345                           *--q = *--p;
03346                         for (; pad > 0; pad--)
03347                           *p++ = '0';
03348                       }
03349                     else
03350                       {
03351                         /* Pad with spaces on the left.  */
03352                         DCHAR_T *q = end;
03353 
03354                         while (p > tmp)
03355                           *--q = *--p;
03356                         for (; pad > 0; pad--)
03357                           *p++ = ' ';
03358                       }
03359 
03360                     p = end;
03361                   }
03362 
03363                 {
03364                   size_t count = p - tmp;
03365 
03366                   if (count >= tmp_length)
03367                     /* tmp_length was incorrectly calculated - fix the
03368                        code above!  */
03369                     abort ();
03370 
03371                   /* Make room for the result.  */
03372                   if (count >= allocated - length)
03373                     {
03374                       size_t n = xsum (length, count);
03375 
03376                       ENSURE_ALLOCATION (n);
03377                     }
03378 
03379                   /* Append the result.  */
03380                   memcpy (result + length, tmp, count * sizeof (DCHAR_T));
03381                   if (tmp != tmpbuf)
03382                     free (tmp);
03383                   length += count;
03384                 }
03385               }
03386 #endif
03387 #if (NEED_PRINTF_INFINITE_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL
03388             else if ((dp->conversion == 'f' || dp->conversion == 'F'
03389                       || dp->conversion == 'e' || dp->conversion == 'E'
03390                       || dp->conversion == 'g' || dp->conversion == 'G'
03391                       || dp->conversion == 'a' || dp->conversion == 'A')
03392                      && (0
03393 # if NEED_PRINTF_DOUBLE
03394                          || a.arg[dp->arg_index].type == TYPE_DOUBLE
03395 # elif NEED_PRINTF_INFINITE_DOUBLE
03396                          || (a.arg[dp->arg_index].type == TYPE_DOUBLE
03397                              /* The systems (mingw) which produce wrong output
03398                                 for Inf, -Inf, and NaN also do so for -0.0.
03399                                 Therefore we treat this case here as well.  */
03400                              && is_infinite_or_zero (a.arg[dp->arg_index].a.a_double))
03401 # endif
03402 # if NEED_PRINTF_LONG_DOUBLE
03403                          || a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
03404 # elif NEED_PRINTF_INFINITE_LONG_DOUBLE
03405                          || (a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
03406                              /* Some systems produce wrong output for Inf,
03407                                 -Inf, and NaN.  Some systems in this category
03408                                 (IRIX 5.3) also do so for -0.0.  Therefore we
03409                                 treat this case here as well.  */
03410                              && is_infinite_or_zerol (a.arg[dp->arg_index].a.a_longdouble))
03411 # endif
03412                         ))
03413               {
03414 # if (NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE)
03415                 arg_type type = a.arg[dp->arg_index].type;
03416 # endif
03417                 int flags = dp->flags;
03418                 int has_width;
03419                 size_t width;
03420                 int has_precision;
03421                 size_t precision;
03422                 size_t tmp_length;
03423                 DCHAR_T tmpbuf[700];
03424                 DCHAR_T *tmp;
03425                 DCHAR_T *pad_ptr;
03426                 DCHAR_T *p;
03427 
03428                 has_width = 0;
03429                 width = 0;
03430                 if (dp->width_start != dp->width_end)
03431                   {
03432                     if (dp->width_arg_index != ARG_NONE)
03433                       {
03434                         int arg;
03435 
03436                         if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
03437                           abort ();
03438                         arg = a.arg[dp->width_arg_index].a.a_int;
03439                         if (arg < 0)
03440                           {
03441                             /* "A negative field width is taken as a '-' flag
03442                                 followed by a positive field width."  */
03443                             flags |= FLAG_LEFT;
03444                             width = (unsigned int) (-arg);
03445                           }
03446                         else
03447                           width = arg;
03448                       }
03449                     else
03450                       {
03451                         const FCHAR_T *digitp = dp->width_start;
03452 
03453                         do
03454                           width = xsum (xtimes (width, 10), *digitp++ - '0');
03455                         while (digitp != dp->width_end);
03456                       }
03457                     has_width = 1;
03458                   }
03459 
03460                 has_precision = 0;
03461                 precision = 0;
03462                 if (dp->precision_start != dp->precision_end)
03463                   {
03464                     if (dp->precision_arg_index != ARG_NONE)
03465                       {
03466                         int arg;
03467 
03468                         if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
03469                           abort ();
03470                         arg = a.arg[dp->precision_arg_index].a.a_int;
03471                         /* "A negative precision is taken as if the precision
03472                             were omitted."  */
03473                         if (arg >= 0)
03474                           {
03475                             precision = arg;
03476                             has_precision = 1;
03477                           }
03478                       }
03479                     else
03480                       {
03481                         const FCHAR_T *digitp = dp->precision_start + 1;
03482 
03483                         precision = 0;
03484                         while (digitp != dp->precision_end)
03485                           precision = xsum (xtimes (precision, 10), *digitp++ - '0');
03486                         has_precision = 1;
03487                       }
03488                   }
03489 
03490                 /* POSIX specifies the default precision to be 6 for %f, %F,
03491                    %e, %E, but not for %g, %G.  Implementations appear to use
03492                    the same default precision also for %g, %G.  But for %a, %A,
03493                    the default precision is 0.  */
03494                 if (!has_precision)
03495                   if (!(dp->conversion == 'a' || dp->conversion == 'A'))
03496                     precision = 6;
03497 
03498                 /* Allocate a temporary buffer of sufficient size.  */
03499 # if NEED_PRINTF_DOUBLE && NEED_PRINTF_LONG_DOUBLE
03500                 tmp_length = (type == TYPE_LONGDOUBLE ? LDBL_DIG + 1 : DBL_DIG + 1);
03501 # elif NEED_PRINTF_INFINITE_DOUBLE && NEED_PRINTF_LONG_DOUBLE
03502                 tmp_length = (type == TYPE_LONGDOUBLE ? LDBL_DIG + 1 : 0);
03503 # elif NEED_PRINTF_LONG_DOUBLE
03504                 tmp_length = LDBL_DIG + 1;
03505 # elif NEED_PRINTF_DOUBLE
03506                 tmp_length = DBL_DIG + 1;
03507 # else
03508                 tmp_length = 0;
03509 # endif
03510                 if (tmp_length < precision)
03511                   tmp_length = precision;
03512 # if NEED_PRINTF_LONG_DOUBLE
03513 #  if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
03514                 if (type == TYPE_LONGDOUBLE)
03515 #  endif
03516                   if (dp->conversion == 'f' || dp->conversion == 'F')
03517                     {
03518                       long double arg = a.arg[dp->arg_index].a.a_longdouble;
03519                       if (!(isnanl (arg) || arg + arg == arg))
03520                         {
03521                           /* arg is finite and nonzero.  */
03522                           int exponent = floorlog10l (arg < 0 ? -arg : arg);
03523                           if (exponent >= 0 && tmp_length < exponent + precision)
03524                             tmp_length = exponent + precision;
03525                         }
03526                     }
03527 # endif
03528 # if NEED_PRINTF_DOUBLE
03529 #  if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE
03530                 if (type == TYPE_DOUBLE)
03531 #  endif
03532                   if (dp->conversion == 'f' || dp->conversion == 'F')
03533                     {
03534                       double arg = a.arg[dp->arg_index].a.a_double;
03535                       if (!(isnand (arg) || arg + arg == arg))
03536                         {
03537                           /* arg is finite and nonzero.  */
03538                           int exponent = floorlog10 (arg < 0 ? -arg : arg);
03539                           if (exponent >= 0 && tmp_length < exponent + precision)
03540                             tmp_length = exponent + precision;
03541                         }
03542                     }
03543 # endif
03544                 /* Account for sign, decimal point etc. */
03545                 tmp_length = xsum (tmp_length, 12);
03546 
03547                 if (tmp_length < width)
03548                   tmp_length = width;
03549 
03550                 tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
03551 
03552                 if (tmp_length <= sizeof (tmpbuf) / sizeof (DCHAR_T))
03553                   tmp = tmpbuf;
03554                 else
03555                   {
03556                     size_t tmp_memsize = xtimes (tmp_length, sizeof (DCHAR_T));
03557 
03558                     if (size_overflow_p (tmp_memsize))
03559                       /* Overflow, would lead to out of memory.  */
03560                       goto out_of_memory;
03561                     tmp = (DCHAR_T *) malloc (tmp_memsize);
03562                     if (tmp == NULL)
03563                       /* Out of memory.  */
03564                       goto out_of_memory;
03565                   }
03566 
03567                 pad_ptr = NULL;
03568                 p = tmp;
03569 
03570 # if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE
03571 #  if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
03572                 if (type == TYPE_LONGDOUBLE)
03573 #  endif
03574                   {
03575                     long double arg = a.arg[dp->arg_index].a.a_longdouble;
03576 
03577                     if (isnanl (arg))
03578                       {
03579                         if (dp->conversion >= 'A' && dp->conversion <= 'Z')
03580                           {
03581                             *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
03582                           }
03583                         else
03584                           {
03585                             *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
03586                           }
03587                       }
03588                     else
03589                       {
03590                         int sign = 0;
03591                         DECL_LONG_DOUBLE_ROUNDING
03592 
03593                         BEGIN_LONG_DOUBLE_ROUNDING ();
03594 
03595                         if (signbit (arg)) /* arg < 0.0L or negative zero */
03596                           {
03597                             sign = -1;
03598                             arg = -arg;
03599                           }
03600 
03601                         if (sign < 0)
03602                           *p++ = '-';
03603                         else if (flags & FLAG_SHOWSIGN)
03604                           *p++ = '+';
03605                         else if (flags & FLAG_SPACE)
03606                           *p++ = ' ';
03607 
03608                         if (arg > 0.0L && arg + arg == arg)
03609                           {
03610                             if (dp->conversion >= 'A' && dp->conversion <= 'Z')
03611                               {
03612                                 *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
03613                               }
03614                             else
03615                               {
03616                                 *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
03617                               }
03618                           }
03619                         else
03620                           {
03621 #  if NEED_PRINTF_LONG_DOUBLE
03622                             pad_ptr = p;
03623 
03624                             if (dp->conversion == 'f' || dp->conversion == 'F')
03625                               {
03626                                 char *digits;
03627                                 size_t ndigits;
03628 
03629                                 digits =
03630                                   scale10_round_decimal_long_double (arg, precision);
03631                                 if (digits == NULL)
03632                                   {
03633                                     END_LONG_DOUBLE_ROUNDING ();
03634                                     goto out_of_memory;
03635                                   }
03636                                 ndigits = strlen (digits);
03637 
03638                                 if (ndigits > precision)
03639                                   do
03640                                     {
03641                                       --ndigits;
03642                                       *p++ = digits[ndigits];
03643                                     }
03644                                   while (ndigits > precision);
03645                                 else
03646                                   *p++ = '0';
03647                                 /* Here ndigits <= precision.  */
03648                                 if ((flags & FLAG_ALT) || precision > 0)
03649                                   {
03650                                     *p++ = decimal_point_char ();
03651                                     for (; precision > ndigits; precision--)
03652                                       *p++ = '0';
03653                                     while (ndigits > 0)
03654                                       {
03655                                         --ndigits;
03656                                         *p++ = digits[ndigits];
03657                                       }
03658                                   }
03659 
03660                                 free (digits);
03661                               }
03662                             else if (dp->conversion == 'e' || dp->conversion == 'E')
03663                               {
03664                                 int exponent;
03665 
03666                                 if (arg == 0.0L)
03667                                   {
03668                                     exponent = 0;
03669                                     *p++ = '0';
03670                                     if ((flags & FLAG_ALT) || precision > 0)
03671                                       {
03672                                         *p++ = decimal_point_char ();
03673                                         for (; precision > 0; precision--)
03674                                           *p++ = '0';
03675                                       }
03676                                   }
03677                                 else
03678                                   {
03679                                     /* arg > 0.0L.  */
03680                                     int adjusted;
03681                                     char *digits;
03682                                     size_t ndigits;
03683 
03684                                     exponent = floorlog10l (arg);
03685                                     adjusted = 0;
03686                                     for (;;)
03687                                       {
03688                                         digits =
03689                                           scale10_round_decimal_long_double (arg,
03690                                                                              (int)precision - exponent);
03691                                         if (digits == NULL)
03692                                           {
03693                                             END_LONG_DOUBLE_ROUNDING ();
03694                                             goto out_of_memory;
03695                                           }
03696                                         ndigits = strlen (digits);
03697 
03698                                         if (ndigits == precision + 1)
03699                                           break;
03700                                         if (ndigits < precision
03701                                             || ndigits > precision + 2)
03702                                           /* The exponent was not guessed
03703                                              precisely enough.  */
03704                                           abort ();
03705                                         if (adjusted)
03706                                           /* None of two values of exponent is
03707                                              the right one.  Prevent an endless
03708                                              loop.  */
03709                                           abort ();
03710                                         free (digits);
03711                                         if (ndigits == precision)
03712                                           exponent -= 1;
03713                                         else
03714                                           exponent += 1;
03715                                         adjusted = 1;
03716                                       }
03717                                     /* Here ndigits = precision+1.  */
03718                                     if (is_borderline (digits, precision))
03719                                       {
03720                                         /* Maybe the exponent guess was too high
03721                                            and a smaller exponent can be reached
03722                                            by turning a 10...0 into 9...9x.  */
03723                                         char *digits2 =
03724                                           scale10_round_decimal_long_double (arg,
03725                                                                              (int)precision - exponent + 1);
03726                                         if (digits2 == NULL)
03727                                           {
03728                                             free (digits);
03729                                             END_LONG_DOUBLE_ROUNDING ();
03730                                             goto out_of_memory;
03731                                           }
03732                                         if (strlen (digits2) == precision + 1)
03733                                           {
03734                                             free (digits);
03735                                             digits = digits2;
03736                                             exponent -= 1;
03737                                           }
03738                                         else
03739                                           free (digits2);
03740                                       }
03741                                     /* Here ndigits = precision+1.  */
03742 
03743                                     *p++ = digits[--ndigits];
03744                                     if ((flags & FLAG_ALT) || precision > 0)
03745                                       {
03746                                         *p++ = decimal_point_char ();
03747                                         while (ndigits > 0)
03748                                           {
03749                                             --ndigits;
03750                                             *p++ = digits[ndigits];
03751                                           }
03752                                       }
03753 
03754                                     free (digits);
03755                                   }
03756 
03757                                 *p++ = dp->conversion; /* 'e' or 'E' */
03758 #   if WIDE_CHAR_VERSION
03759                                 {
03760                                   static const wchar_t decimal_format[] =
03761                                     { '%', '+', '.', '2', 'd', '\0' };
03762                                   SNPRINTF (p, 6 + 1, decimal_format, exponent);
03763                                 }
03764                                 while (*p != '\0')
03765                                   p++;
03766 #   else
03767                                 if (sizeof (DCHAR_T) == 1)
03768                                   {
03769                                     sprintf ((char *) p, "%+.2d", exponent);
03770                                     while (*p != '\0')
03771                                       p++;
03772                                   }
03773                                 else
03774                                   {
03775                                     char expbuf[6 + 1];
03776                                     const char *ep;
03777                                     sprintf (expbuf, "%+.2d", exponent);
03778                                     for (ep = expbuf; (*p = *ep) != '\0'; ep++)
03779                                       p++;
03780                                   }
03781 #   endif
03782                               }
03783                             else if (dp->conversion == 'g' || dp->conversion == 'G')
03784                               {
03785                                 if (precision == 0)
03786                                   precision = 1;
03787                                 /* precision >= 1.  */
03788 
03789                                 if (arg == 0.0L)
03790                                   /* The exponent is 0, >= -4, < precision.
03791                                      Use fixed-point notation.  */
03792                                   {
03793                                     size_t ndigits = precision;
03794                                     /* Number of trailing zeroes that have to be
03795                                        dropped.  */
03796                                     size_t nzeroes =
03797                                       (flags & FLAG_ALT ? 0 : precision - 1);
03798 
03799                                     --ndigits;
03800                                     *p++ = '0';
03801                                     if ((flags & FLAG_ALT) || ndigits > nzeroes)
03802                                       {
03803                                         *p++ = decimal_point_char ();
03804                                         while (ndigits > nzeroes)
03805                                           {
03806                                             --ndigits;
03807                                             *p++ = '0';
03808                                           }
03809                                       }
03810                                   }
03811                                 else
03812                                   {
03813                                     /* arg > 0.0L.  */
03814                                     int exponent;
03815                                     int adjusted;
03816                                     char *digits;
03817                                     size_t ndigits;
03818                                     size_t nzeroes;
03819 
03820                                     exponent = floorlog10l (arg);
03821                                     adjusted = 0;
03822                                     for (;;)
03823                                       {
03824                                         digits =
03825                                           scale10_round_decimal_long_double (arg,
03826                                                                              (int)(precision - 1) - exponent);
03827                                         if (digits == NULL)
03828                                           {
03829                                             END_LONG_DOUBLE_ROUNDING ();
03830                                             goto out_of_memory;
03831                                           }
03832                                         ndigits = strlen (digits);
03833 
03834                                         if (ndigits == precision)
03835                                           break;
03836                                         if (ndigits < precision - 1
03837                                             || ndigits > precision + 1)
03838                                           /* The exponent was not guessed
03839                                              precisely enough.  */
03840                                           abort ();
03841                                         if (adjusted)
03842                                           /* None of two values of exponent is
03843                                              the right one.  Prevent an endless
03844                                              loop.  */
03845                                           abort ();
03846                                         free (digits);
03847                                         if (ndigits < precision)
03848                                           exponent -= 1;
03849                                         else
03850                                           exponent += 1;
03851                                         adjusted = 1;
03852                                       }
03853                                     /* Here ndigits = precision.  */
03854                                     if (is_borderline (digits, precision - 1))
03855                                       {
03856                                         /* Maybe the exponent guess was too high
03857                                            and a smaller exponent can be reached
03858                                            by turning a 10...0 into 9...9x.  */
03859                                         char *digits2 =
03860                                           scale10_round_decimal_long_double (arg,
03861                                                                              (int)(precision - 1) - exponent + 1);
03862                                         if (digits2 == NULL)
03863                                           {
03864                                             free (digits);
03865                                             END_LONG_DOUBLE_ROUNDING ();
03866                                             goto out_of_memory;
03867                                           }
03868                                         if (strlen (digits2) == precision)
03869                                           {
03870                                             free (digits);
03871                                             digits = digits2;
03872                                             exponent -= 1;
03873                                           }
03874                                         else
03875                                           free (digits2);
03876                                       }
03877                                     /* Here ndigits = precision.  */
03878 
03879                                     /* Determine the number of trailing zeroes
03880                                        that have to be dropped.  */
03881                                     nzeroes = 0;
03882                                     if ((flags & FLAG_ALT) == 0)
03883                                       while (nzeroes < ndigits
03884                                              && digits[nzeroes] == '0')
03885                                         nzeroes++;
03886 
03887                                     /* The exponent is now determined.  */
03888                                     if (exponent >= -4
03889                                         && exponent < (long)precision)
03890                                       {
03891                                         /* Fixed-point notation:
03892                                            max(exponent,0)+1 digits, then the
03893                                            decimal point, then the remaining
03894                                            digits without trailing zeroes.  */
03895                                         if (exponent >= 0)
03896                                           {
03897                                             size_t count = exponent + 1;
03898                                             /* Note: count <= precision = ndigits.  */
03899                                             for (; count > 0; count--)
03900                                               *p++ = digits[--ndigits];
03901                                             if ((flags & FLAG_ALT) || ndigits > nzeroes)
03902                                               {
03903                                                 *p++ = decimal_point_char ();
03904                                                 while (ndigits > nzeroes)
03905                                                   {
03906                                                     --ndigits;
03907                                                     *p++ = digits[ndigits];
03908                                                   }
03909                                               }
03910                                           }
03911                                         else
03912                                           {
03913                                             size_t count = -exponent - 1;
03914                                             *p++ = '0';
03915                                             *p++ = decimal_point_char ();
03916                                             for (; count > 0; count--)
03917                                               *p++ = '0';
03918                                             while (ndigits > nzeroes)
03919                                               {
03920                                                 --ndigits;
03921                                                 *p++ = digits[ndigits];
03922                                               }
03923                                           }
03924                                       }
03925                                     else
03926                                       {
03927                                         /* Exponential notation.  */
03928                                         *p++ = digits[--ndigits];
03929                                         if ((flags & FLAG_ALT) || ndigits > nzeroes)
03930                                           {
03931                                             *p++ = decimal_point_char ();
03932                                             while (ndigits > nzeroes)
03933                                               {
03934                                                 --ndigits;
03935                                                 *p++ = digits[ndigits];
03936                                               }
03937                                           }
03938                                         *p++ = dp->conversion - 'G' + 'E'; /* 'e' or 'E' */
03939 #   if WIDE_CHAR_VERSION
03940                                         {
03941                                           static const wchar_t decimal_format[] =
03942                                             { '%', '+', '.', '2', 'd', '\0' };
03943                                           SNPRINTF (p, 6 + 1, decimal_format, exponent);
03944                                         }
03945                                         while (*p != '\0')
03946                                           p++;
03947 #   else
03948                                         if (sizeof (DCHAR_T) == 1)
03949                                           {
03950                                             sprintf ((char *) p, "%+.2d", exponent);
03951                                             while (*p != '\0')
03952                                               p++;
03953                                           }
03954                                         else
03955                                           {
03956                                             char expbuf[6 + 1];
03957                                             const char *ep;
03958                                             sprintf (expbuf, "%+.2d", exponent);
03959                                             for (ep = expbuf; (*p = *ep) != '\0'; ep++)
03960                                               p++;
03961                                           }
03962 #   endif
03963                                       }
03964 
03965                                     free (digits);
03966                                   }
03967                               }
03968                             else
03969                               abort ();
03970 #  else
03971                             /* arg is finite.  */
03972                             if (!(arg == 0.0L))
03973                               abort ();
03974 
03975                             pad_ptr = p;
03976 
03977                             if (dp->conversion == 'f' || dp->conversion == 'F')
03978                               {
03979                                 *p++ = '0';
03980                                 if ((flags & FLAG_ALT) || precision > 0)
03981                                   {
03982                                     *p++ = decimal_point_char ();
03983                                     for (; precision > 0; precision--)
03984                                       *p++ = '0';
03985                                   }
03986                               }
03987                             else if (dp->conversion == 'e' || dp->conversion == 'E')
03988                               {
03989                                 *p++ = '0';
03990                                 if ((flags & FLAG_ALT) || precision > 0)
03991                                   {
03992                                     *p++ = decimal_point_char ();
03993                                     for (; precision > 0; precision--)
03994                                       *p++ = '0';
03995                                   }
03996                                 *p++ = dp->conversion; /* 'e' or 'E' */
03997                                 *p++ = '+';
03998                                 *p++ = '0';
03999                                 *p++ = '0';
04000                               }
04001                             else if (dp->conversion == 'g' || dp->conversion == 'G')
04002                               {
04003                                 *p++ = '0';
04004                                 if (flags & FLAG_ALT)
04005                                   {
04006                                     size_t ndigits =
04007                                       (precision > 0 ? precision - 1 : 0);
04008                                     *p++ = decimal_point_char ();
04009                                     for (; ndigits > 0; --ndigits)
04010                                       *p++ = '0';
04011                                   }
04012                               }
04013                             else if (dp->conversion == 'a' || dp->conversion == 'A')
04014                               {
04015                                 *p++ = '0';
04016                                 *p++ = dp->conversion - 'A' + 'X';
04017                                 pad_ptr = p;
04018                                 *p++ = '0';
04019                                 if ((flags & FLAG_ALT) || precision > 0)
04020                                   {
04021                                     *p++ = decimal_point_char ();
04022                                     for (; precision > 0; precision--)
04023                                       *p++ = '0';
04024                                   }
04025                                 *p++ = dp->conversion - 'A' + 'P';
04026                                 *p++ = '+';
04027                                 *p++ = '0';
04028                               }
04029                             else
04030                               abort ();
04031 #  endif
04032                           }
04033 
04034                         END_LONG_DOUBLE_ROUNDING ();
04035                       }
04036                   }
04037 #  if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
04038                 else
04039 #  endif
04040 # endif
04041 # if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
04042                   {
04043                     double arg = a.arg[dp->arg_index].a.a_double;
04044 
04045                     if (isnand (arg))
04046                       {
04047                         if (dp->conversion >= 'A' && dp->conversion <= 'Z')
04048                           {
04049                             *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
04050                           }
04051                         else
04052                           {
04053                             *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
04054                           }
04055                       }
04056                     else
04057                       {
04058                         int sign = 0;
04059 
04060                         if (signbit (arg)) /* arg < 0.0 or negative zero */
04061                           {
04062                             sign = -1;
04063                             arg = -arg;
04064                           }
04065 
04066                         if (sign < 0)
04067                           *p++ = '-';
04068                         else if (flags & FLAG_SHOWSIGN)
04069                           *p++ = '+';
04070                         else if (flags & FLAG_SPACE)
04071                           *p++ = ' ';
04072 
04073                         if (arg > 0.0 && arg + arg == arg)
04074                           {
04075                             if (dp->conversion >= 'A' && dp->conversion <= 'Z')
04076                               {
04077                                 *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
04078                               }
04079                             else
04080                               {
04081                                 *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
04082                               }
04083                           }
04084                         else
04085                           {
04086 #  if NEED_PRINTF_DOUBLE
04087                             pad_ptr = p;
04088 
04089                             if (dp->conversion == 'f' || dp->conversion == 'F')
04090                               {
04091                                 char *digits;
04092                                 size_t ndigits;
04093 
04094                                 digits =
04095                                   scale10_round_decimal_double (arg, precision);
04096                                 if (digits == NULL)
04097                                   goto out_of_memory;
04098                                 ndigits = strlen (digits);
04099 
04100                                 if (ndigits > precision)
04101                                   do
04102                                     {
04103                                       --ndigits;
04104                                       *p++ = digits[ndigits];
04105                                     }
04106                                   while (ndigits > precision);
04107                                 else
04108                                   *p++ = '0';
04109                                 /* Here ndigits <= precision.  */
04110                                 if ((flags & FLAG_ALT) || precision > 0)
04111                                   {
04112                                     *p++ = decimal_point_char ();
04113                                     for (; precision > ndigits; precision--)
04114                                       *p++ = '0';
04115                                     while (ndigits > 0)
04116                                       {
04117                                         --ndigits;
04118                                         *p++ = digits[ndigits];
04119                                       }
04120                                   }
04121 
04122                                 free (digits);
04123                               }
04124                             else if (dp->conversion == 'e' || dp->conversion == 'E')
04125                               {
04126                                 int exponent;
04127 
04128                                 if (arg == 0.0)
04129                                   {
04130                                     exponent = 0;
04131                                     *p++ = '0';
04132                                     if ((flags & FLAG_ALT) || precision > 0)
04133                                       {
04134                                         *p++ = decimal_point_char ();
04135                                         for (; precision > 0; precision--)
04136                                           *p++ = '0';
04137                                       }
04138                                   }
04139                                 else
04140                                   {
04141                                     /* arg > 0.0.  */
04142                                     int adjusted;
04143                                     char *digits;
04144                                     size_t ndigits;
04145 
04146                                     exponent = floorlog10 (arg);
04147                                     adjusted = 0;
04148                                     for (;;)
04149                                       {
04150                                         digits =
04151                                           scale10_round_decimal_double (arg,
04152                                                                         (int)precision - exponent);
04153                                         if (digits == NULL)
04154                                           goto out_of_memory;
04155                                         ndigits = strlen (digits);
04156 
04157                                         if (ndigits == precision + 1)
04158                                           break;
04159                                         if (ndigits < precision
04160                                             || ndigits > precision + 2)
04161                                           /* The exponent was not guessed
04162                                              precisely enough.  */
04163                                           abort ();
04164                                         if (adjusted)
04165                                           /* None of two values of exponent is
04166                                              the right one.  Prevent an endless
04167                                              loop.  */
04168                                           abort ();
04169                                         free (digits);
04170                                         if (ndigits == precision)
04171                                           exponent -= 1;
04172                                         else
04173                                           exponent += 1;
04174                                         adjusted = 1;
04175                                       }
04176                                     /* Here ndigits = precision+1.  */
04177                                     if (is_borderline (digits, precision))
04178                                       {
04179                                         /* Maybe the exponent guess was too high
04180                                            and a smaller exponent can be reached
04181                                            by turning a 10...0 into 9...9x.  */
04182                                         char *digits2 =
04183                                           scale10_round_decimal_double (arg,
04184                                                                         (int)precision - exponent + 1);
04185                                         if (digits2 == NULL)
04186                                           {
04187                                             free (digits);
04188                                             goto out_of_memory;
04189                                           }
04190                                         if (strlen (digits2) == precision + 1)
04191                                           {
04192                                             free (digits);
04193                                             digits = digits2;
04194                                             exponent -= 1;
04195                                           }
04196                                         else
04197                                           free (digits2);
04198                                       }
04199                                     /* Here ndigits = precision+1.  */
04200 
04201                                     *p++ = digits[--ndigits];
04202                                     if ((flags & FLAG_ALT) || precision > 0)
04203                                       {
04204                                         *p++ = decimal_point_char ();
04205                                         while (ndigits > 0)
04206                                           {
04207                                             --ndigits;
04208                                             *p++ = digits[ndigits];
04209                                           }
04210                                       }
04211 
04212                                     free (digits);
04213                                   }
04214 
04215                                 *p++ = dp->conversion; /* 'e' or 'E' */
04216 #   if WIDE_CHAR_VERSION
04217                                 {
04218                                   static const wchar_t decimal_format[] =
04219                                     /* Produce the same number of exponent digits
04220                                        as the native printf implementation.  */
04221 #    if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
04222                                     { '%', '+', '.', '3', 'd', '\0' };
04223 #    else
04224                                     { '%', '+', '.', '2', 'd', '\0' };
04225 #    endif
04226                                   SNPRINTF (p, 6 + 1, decimal_format, exponent);
04227                                 }
04228                                 while (*p != '\0')
04229                                   p++;
04230 #   else
04231                                 {
04232                                   static const char decimal_format[] =
04233                                     /* Produce the same number of exponent digits
04234                                        as the native printf implementation.  */
04235 #    if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
04236                                     "%+.3d";
04237 #    else
04238                                     "%+.2d";
04239 #    endif
04240                                   if (sizeof (DCHAR_T) == 1)
04241                                     {
04242                                       sprintf ((char *) p, decimal_format, exponent);
04243                                       while (*p != '\0')
04244                                         p++;
04245                                     }
04246                                   else
04247                                     {
04248                                       char expbuf[6 + 1];
04249                                       const char *ep;
04250                                       sprintf (expbuf, decimal_format, exponent);
04251                                       for (ep = expbuf; (*p = *ep) != '\0'; ep++)
04252                                         p++;
04253                                     }
04254                                 }
04255 #   endif
04256                               }
04257                             else if (dp->conversion == 'g' || dp->conversion == 'G')
04258                               {
04259                                 if (precision == 0)
04260                                   precision = 1;
04261                                 /* precision >= 1.  */
04262 
04263                                 if (arg == 0.0)
04264                                   /* The exponent is 0, >= -4, < precision.
04265                                      Use fixed-point notation.  */
04266                                   {
04267                                     size_t ndigits = precision;
04268                                     /* Number of trailing zeroes that have to be
04269                                        dropped.  */
04270                                     size_t nzeroes =
04271                                       (flags & FLAG_ALT ? 0 : precision - 1);
04272 
04273                                     --ndigits;
04274                                     *p++ = '0';
04275                                     if ((flags & FLAG_ALT) || ndigits > nzeroes)
04276                                       {
04277                                         *p++ = decimal_point_char ();
04278                                         while (ndigits > nzeroes)
04279                                           {
04280                                             --ndigits;
04281                                             *p++ = '0';
04282                                           }
04283                                       }
04284                                   }
04285                                 else
04286                                   {
04287                                     /* arg > 0.0.  */
04288                                     int exponent;
04289                                     int adjusted;
04290                                     char *digits;
04291                                     size_t ndigits;
04292                                     size_t nzeroes;
04293 
04294                                     exponent = floorlog10 (arg);
04295                                     adjusted = 0;
04296                                     for (;;)
04297                                       {
04298                                         digits =
04299                                           scale10_round_decimal_double (arg,
04300                                                                         (int)(precision - 1) - exponent);
04301                                         if (digits == NULL)
04302                                           goto out_of_memory;
04303                                         ndigits = strlen (digits);
04304 
04305                                         if (ndigits == precision)
04306                                           break;
04307                                         if (ndigits < precision - 1
04308                                             || ndigits > precision + 1)
04309                                           /* The exponent was not guessed
04310                                              precisely enough.  */
04311                                           abort ();
04312                                         if (adjusted)
04313                                           /* None of two values of exponent is
04314                                              the right one.  Prevent an endless
04315                                              loop.  */
04316                                           abort ();
04317                                         free (digits);
04318                                         if (ndigits < precision)
04319                                           exponent -= 1;
04320                                         else
04321                                           exponent += 1;
04322                                         adjusted = 1;
04323                                       }
04324                                     /* Here ndigits = precision.  */
04325                                     if (is_borderline (digits, precision - 1))
04326                                       {
04327                                         /* Maybe the exponent guess was too high
04328                                            and a smaller exponent can be reached
04329                                            by turning a 10...0 into 9...9x.  */
04330                                         char *digits2 =
04331                                           scale10_round_decimal_double (arg,
04332                                                                         (int)(precision - 1) - exponent + 1);
04333                                         if (digits2 == NULL)
04334                                           {
04335                                             free (digits);
04336                                             goto out_of_memory;
04337                                           }
04338                                         if (strlen (digits2) == precision)
04339                                           {
04340                                             free (digits);
04341                                             digits = digits2;
04342                                             exponent -= 1;
04343                                           }
04344                                         else
04345                                           free (digits2);
04346                                       }
04347                                     /* Here ndigits = precision.  */
04348 
04349                                     /* Determine the number of trailing zeroes
04350                                        that have to be dropped.  */
04351                                     nzeroes = 0;
04352                                     if ((flags & FLAG_ALT) == 0)
04353                                       while (nzeroes < ndigits
04354                                              && digits[nzeroes] == '0')
04355                                         nzeroes++;
04356 
04357                                     /* The exponent is now determined.  */
04358                                     if (exponent >= -4
04359                                         && exponent < (long)precision)
04360                                       {
04361                                         /* Fixed-point notation:
04362                                            max(exponent,0)+1 digits, then the
04363                                            decimal point, then the remaining
04364                                            digits without trailing zeroes.  */
04365                                         if (exponent >= 0)
04366                                           {
04367                                             size_t count = exponent + 1;
04368                                             /* Note: count <= precision = ndigits.  */
04369                                             for (; count > 0; count--)
04370                                               *p++ = digits[--ndigits];
04371                                             if ((flags & FLAG_ALT) || ndigits > nzeroes)
04372                                               {
04373                                                 *p++ = decimal_point_char ();
04374                                                 while (ndigits > nzeroes)
04375                                                   {
04376                                                     --ndigits;
04377                                                     *p++ = digits[ndigits];
04378                                                   }
04379                                               }
04380                                           }
04381                                         else
04382                                           {
04383                                             size_t count = -exponent - 1;
04384                                             *p++ = '0';
04385                                             *p++ = decimal_point_char ();
04386                                             for (; count > 0; count--)
04387                                               *p++ = '0';
04388                                             while (ndigits > nzeroes)
04389                                               {
04390                                                 --ndigits;
04391                                                 *p++ = digits[ndigits];
04392                                               }
04393                                           }
04394                                       }
04395                                     else
04396                                       {
04397                                         /* Exponential notation.  */
04398                                         *p++ = digits[--ndigits];
04399                                         if ((flags & FLAG_ALT) || ndigits > nzeroes)
04400                                           {
04401                                             *p++ = decimal_point_char ();
04402                                             while (ndigits > nzeroes)
04403                                               {
04404                                                 --ndigits;
04405                                                 *p++ = digits[ndigits];
04406                                               }
04407                                           }
04408                                         *p++ = dp->conversion - 'G' + 'E'; /* 'e' or 'E' */
04409 #   if WIDE_CHAR_VERSION
04410                                         {
04411                                           static const wchar_t decimal_format[] =
04412                                             /* Produce the same number of exponent digits
04413                                                as the native printf implementation.  */
04414 #    if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
04415                                             { '%', '+', '.', '3', 'd', '\0' };
04416 #    else
04417                                             { '%', '+', '.', '2', 'd', '\0' };
04418 #    endif
04419                                           SNPRINTF (p, 6 + 1, decimal_format, exponent);
04420                                         }
04421                                         while (*p != '\0')
04422                                           p++;
04423 #   else
04424                                         {
04425                                           static const char decimal_format[] =
04426                                             /* Produce the same number of exponent digits
04427                                                as the native printf implementation.  */
04428 #    if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
04429                                             "%+.3d";
04430 #    else
04431                                             "%+.2d";
04432 #    endif
04433                                           if (sizeof (DCHAR_T) == 1)
04434                                             {
04435                                               sprintf ((char *) p, decimal_format, exponent);
04436                                               while (*p != '\0')
04437                                                 p++;
04438                                             }
04439                                           else
04440                                             {
04441                                               char expbuf[6 + 1];
04442                                               const char *ep;
04443                                               sprintf (expbuf, decimal_format, exponent);
04444                                               for (ep = expbuf; (*p = *ep) != '\0'; ep++)
04445                                                 p++;
04446                                             }
04447                                         }
04448 #   endif
04449                                       }
04450 
04451                                     free (digits);
04452                                   }
04453                               }
04454                             else
04455                               abort ();
04456 #  else
04457                             /* arg is finite.  */
04458                             if (!(arg == 0.0))
04459                               abort ();
04460 
04461                             pad_ptr = p;
04462 
04463                             if (dp->conversion == 'f' || dp->conversion == 'F')
04464                               {
04465                                 *p++ = '0';
04466                                 if ((flags & FLAG_ALT) || precision > 0)
04467                                   {
04468                                     *p++ = decimal_point_char ();
04469                                     for (; precision > 0; precision--)
04470                                       *p++ = '0';
04471                                   }
04472                               }
04473                             else if (dp->conversion == 'e' || dp->conversion == 'E')
04474                               {
04475                                 *p++ = '0';
04476                                 if ((flags & FLAG_ALT) || precision > 0)
04477                                   {
04478                                     *p++ = decimal_point_char ();
04479                                     for (; precision > 0; precision--)
04480                                       *p++ = '0';
04481                                   }
04482                                 *p++ = dp->conversion; /* 'e' or 'E' */
04483                                 *p++ = '+';
04484                                 /* Produce the same number of exponent digits as
04485                                    the native printf implementation.  */
04486 #   if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
04487                                 *p++ = '0';
04488 #   endif
04489                                 *p++ = '0';
04490                                 *p++ = '0';
04491                               }
04492                             else if (dp->conversion == 'g' || dp->conversion == 'G')
04493                               {
04494                                 *p++ = '0';
04495                                 if (flags & FLAG_ALT)
04496                                   {
04497                                     size_t ndigits =
04498                                       (precision > 0 ? precision - 1 : 0);
04499                                     *p++ = decimal_point_char ();
04500                                     for (; ndigits > 0; --ndigits)
04501                                       *p++ = '0';
04502                                   }
04503                               }
04504                             else
04505                               abort ();
04506 #  endif
04507                           }
04508                       }
04509                   }
04510 # endif
04511 
04512                 /* The generated string now extends from tmp to p, with the
04513                    zero padding insertion point being at pad_ptr.  */
04514                 if (has_width && p - tmp < width)
04515                   {
04516                     size_t pad = width - (p - tmp);
04517                     DCHAR_T *end = p + pad;
04518 
04519                     if (flags & FLAG_LEFT)
04520                       {
04521                         /* Pad with spaces on the right.  */
04522                         for (; pad > 0; pad--)
04523                           *p++ = ' ';
04524                       }
04525                     else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
04526                       {
04527                         /* Pad with zeroes.  */
04528                         DCHAR_T *q = end;
04529 
04530                         while (p > pad_ptr)
04531                           *--q = *--p;
04532                         for (; pad > 0; pad--)
04533                           *p++ = '0';
04534                       }
04535                     else
04536                       {
04537                         /* Pad with spaces on the left.  */
04538                         DCHAR_T *q = end;
04539 
04540                         while (p > tmp)
04541                           *--q = *--p;
04542                         for (; pad > 0; pad--)
04543                           *p++ = ' ';
04544                       }
04545 
04546                     p = end;
04547                   }
04548 
04549                 {
04550                   size_t count = p - tmp;
04551 
04552                   if (count >= tmp_length)
04553                     /* tmp_length was incorrectly calculated - fix the
04554                        code above!  */
04555                     abort ();
04556 
04557                   /* Make room for the result.  */
04558                   if (count >= allocated - length)
04559                     {
04560                       size_t n = xsum (length, count);
04561 
04562                       ENSURE_ALLOCATION (n);
04563                     }
04564 
04565                   /* Append the result.  */
04566                   memcpy (result + length, tmp, count * sizeof (DCHAR_T));
04567                   if (tmp != tmpbuf)
04568                     free (tmp);
04569                   length += count;
04570                 }
04571               }
04572 #endif
04573             else
04574               {
04575                 arg_type type = a.arg[dp->arg_index].type;
04576                 int flags = dp->flags;
04577 #if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
04578                 int has_width;
04579                 size_t width;
04580 #endif
04581 #if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || NEED_PRINTF_UNBOUNDED_PRECISION
04582                 int has_precision;
04583                 size_t precision;
04584 #endif
04585 #if NEED_PRINTF_UNBOUNDED_PRECISION
04586                 int prec_ourselves;
04587 #else
04588 #               define prec_ourselves 0
04589 #endif
04590 #if NEED_PRINTF_FLAG_LEFTADJUST
04591 #               define pad_ourselves 1
04592 #elif !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
04593                 int pad_ourselves;
04594 #else
04595 #               define pad_ourselves 0
04596 #endif
04597                 TCHAR_T *fbp;
04598                 unsigned int prefix_count;
04599                 int prefixes[2] IF_LINT (= { 0 });
04600 #if !USE_SNPRINTF
04601                 size_t tmp_length;
04602                 TCHAR_T tmpbuf[700];
04603                 TCHAR_T *tmp;
04604 #endif
04605 
04606 #if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
04607                 has_width = 0;
04608                 width = 0;
04609                 if (dp->width_start != dp->width_end)
04610                   {
04611                     if (dp->width_arg_index != ARG_NONE)
04612                       {
04613                         int arg;
04614 
04615                         if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
04616                           abort ();
04617                         arg = a.arg[dp->width_arg_index].a.a_int;
04618                         if (arg < 0)
04619                           {
04620                             /* "A negative field width is taken as a '-' flag
04621                                 followed by a positive field width."  */
04622                             flags |= FLAG_LEFT;
04623                             width = (unsigned int) (-arg);
04624                           }
04625                         else
04626                           width = arg;
04627                       }
04628                     else
04629                       {
04630                         const FCHAR_T *digitp = dp->width_start;
04631 
04632                         do
04633                           width = xsum (xtimes (width, 10), *digitp++ - '0');
04634                         while (digitp != dp->width_end);
04635                       }
04636                     has_width = 1;
04637                   }
04638 #endif
04639 
04640 #if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || NEED_PRINTF_UNBOUNDED_PRECISION
04641                 has_precision = 0;
04642                 precision = 6;
04643                 if (dp->precision_start != dp->precision_end)
04644                   {
04645                     if (dp->precision_arg_index != ARG_NONE)
04646                       {
04647                         int arg;
04648 
04649                         if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
04650                           abort ();
04651                         arg = a.arg[dp->precision_arg_index].a.a_int;
04652                         /* "A negative precision is taken as if the precision
04653                             were omitted."  */
04654                         if (arg >= 0)
04655                           {
04656                             precision = arg;
04657                             has_precision = 1;
04658                           }
04659                       }
04660                     else
04661                       {
04662                         const FCHAR_T *digitp = dp->precision_start + 1;
04663 
04664                         precision = 0;
04665                         while (digitp != dp->precision_end)
04666                           precision = xsum (xtimes (precision, 10), *digitp++ - '0');
04667                         has_precision = 1;
04668                       }
04669                   }
04670 #endif
04671 
04672                 /* Decide whether to handle the precision ourselves.  */
04673 #if NEED_PRINTF_UNBOUNDED_PRECISION
04674                 switch (dp->conversion)
04675                   {
04676                   case 'd': case 'i': case 'u':
04677                   case 'o':
04678                   case 'x': case 'X': case 'p':
04679                     prec_ourselves = has_precision && (precision > 0);
04680                     break;
04681                   default:
04682                     prec_ourselves = 0;
04683                     break;
04684                   }
04685 #endif
04686 
04687                 /* Decide whether to perform the padding ourselves.  */
04688 #if !NEED_PRINTF_FLAG_LEFTADJUST && (!DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION)
04689                 switch (dp->conversion)
04690                   {
04691 # if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO
04692                   /* If we need conversion from TCHAR_T[] to DCHAR_T[], we need
04693                      to perform the padding after this conversion.  Functions
04694                      with unistdio extensions perform the padding based on
04695                      character count rather than element count.  */
04696                   case 'c': case 's':
04697 # endif
04698 # if NEED_PRINTF_FLAG_ZERO
04699                   case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
04700                   case 'a': case 'A':
04701 # endif
04702                     pad_ourselves = 1;
04703                     break;
04704                   default:
04705                     pad_ourselves = prec_ourselves;
04706                     break;
04707                   }
04708 #endif
04709 
04710 #if !USE_SNPRINTF
04711                 /* Allocate a temporary buffer of sufficient size for calling
04712                    sprintf.  */
04713                 tmp_length =
04714                   MAX_ROOM_NEEDED (&a, dp->arg_index, dp->conversion, type,
04715                                    flags, width, has_precision, precision,
04716                                    pad_ourselves);
04717 
04718                 if (tmp_length <= sizeof (tmpbuf) / sizeof (TCHAR_T))
04719                   tmp = tmpbuf;
04720                 else
04721                   {
04722                     size_t tmp_memsize = xtimes (tmp_length, sizeof (TCHAR_T));
04723 
04724                     if (size_overflow_p (tmp_memsize))
04725                       /* Overflow, would lead to out of memory.  */
04726                       goto out_of_memory;
04727                     tmp = (TCHAR_T *) malloc (tmp_memsize);
04728                     if (tmp == NULL)
04729                       /* Out of memory.  */
04730                       goto out_of_memory;
04731                   }
04732 #endif
04733 
04734                 /* Construct the format string for calling snprintf or
04735                    sprintf.  */
04736                 fbp = buf;
04737                 *fbp++ = '%';
04738 #if NEED_PRINTF_FLAG_GROUPING
04739                 /* The underlying implementation doesn't support the ' flag.
04740                    Produce no grouping characters in this case; this is
04741                    acceptable because the grouping is locale dependent.  */
04742 #else
04743                 if (flags & FLAG_GROUP)
04744                   *fbp++ = '\'';
04745 #endif
04746                 if (flags & FLAG_LEFT)
04747                   *fbp++ = '-';
04748                 if (flags & FLAG_SHOWSIGN)
04749                   *fbp++ = '+';
04750                 if (flags & FLAG_SPACE)
04751                   *fbp++ = ' ';
04752                 if (flags & FLAG_ALT)
04753                   *fbp++ = '#';
04754                 if (!pad_ourselves)
04755                   {
04756                     if (flags & FLAG_ZERO)
04757                       *fbp++ = '0';
04758                     if (dp->width_start != dp->width_end)
04759                       {
04760                         size_t n = dp->width_end - dp->width_start;
04761                         /* The width specification is known to consist only
04762                            of standard ASCII characters.  */
04763                         if (sizeof (FCHAR_T) == sizeof (TCHAR_T))
04764                           {
04765                             memcpy (fbp, dp->width_start, n * sizeof (TCHAR_T));
04766                             fbp += n;
04767                           }
04768                         else
04769                           {
04770                             const FCHAR_T *mp = dp->width_start;
04771                             do
04772                               *fbp++ = (unsigned char) *mp++;
04773                             while (--n > 0);
04774                           }
04775                       }
04776                   }
04777                 if (!prec_ourselves)
04778                   {
04779                     if (dp->precision_start != dp->precision_end)
04780                       {
04781                         size_t n = dp->precision_end - dp->precision_start;
04782                         /* The precision specification is known to consist only
04783                            of standard ASCII characters.  */
04784                         if (sizeof (FCHAR_T) == sizeof (TCHAR_T))
04785                           {
04786                             memcpy (fbp, dp->precision_start, n * sizeof (TCHAR_T));
04787                             fbp += n;
04788                           }
04789                         else
04790                           {
04791                             const FCHAR_T *mp = dp->precision_start;
04792                             do
04793                               *fbp++ = (unsigned char) *mp++;
04794                             while (--n > 0);
04795                           }
04796                       }
04797                   }
04798 
04799                 switch (type)
04800                   {
04801 #if HAVE_LONG_LONG_INT
04802                   case TYPE_LONGLONGINT:
04803                   case TYPE_ULONGLONGINT:
04804 # if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
04805                     *fbp++ = 'I';
04806                     *fbp++ = '6';
04807                     *fbp++ = '4';
04808                     break;
04809 # else
04810                     *fbp++ = 'l';
04811                     /*FALLTHROUGH*/
04812 # endif
04813 #endif
04814                   case TYPE_LONGINT:
04815                   case TYPE_ULONGINT:
04816 #if HAVE_WINT_T
04817                   case TYPE_WIDE_CHAR:
04818 #endif
04819 #if HAVE_WCHAR_T
04820                   case TYPE_WIDE_STRING:
04821 #endif
04822                     *fbp++ = 'l';
04823                     break;
04824                   case TYPE_LONGDOUBLE:
04825                     *fbp++ = 'L';
04826                     break;
04827                   default:
04828                     break;
04829                   }
04830 #if NEED_PRINTF_DIRECTIVE_F
04831                 if (dp->conversion == 'F')
04832                   *fbp = 'f';
04833                 else
04834 #endif
04835                   *fbp = dp->conversion;
04836 #if USE_SNPRINTF
04837 # if !(__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3) || ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__))
04838                 fbp[1] = '%';
04839                 fbp[2] = 'n';
04840                 fbp[3] = '\0';
04841 # else
04842                 /* On glibc2 systems from glibc >= 2.3 - probably also older
04843                    ones - we know that snprintf's returns value conforms to
04844                    ISO C 99: the gl_SNPRINTF_DIRECTIVE_N test passes.
04845                    Therefore we can avoid using %n in this situation.
04846                    On glibc2 systems from 2004-10-18 or newer, the use of %n
04847                    in format strings in writable memory may crash the program
04848                    (if compiled with _FORTIFY_SOURCE=2), so we should avoid it
04849                    in this situation.  */
04850                 /* On native Win32 systems (such as mingw), we can avoid using
04851                    %n because:
04852                      - Although the gl_SNPRINTF_TRUNCATION_C99 test fails,
04853                        snprintf does not write more than the specified number
04854                        of bytes. (snprintf (buf, 3, "%d %d", 4567, 89) writes
04855                        '4', '5', '6' into buf, not '4', '5', '\0'.)
04856                      - Although the gl_SNPRINTF_RETVAL_C99 test fails, snprintf
04857                        allows us to recognize the case of an insufficient
04858                        buffer size: it returns -1 in this case.
04859                    On native Win32 systems (such as mingw) where the OS is
04860                    Windows Vista, the use of %n in format strings by default
04861                    crashes the program. See
04862                      <http://gcc.gnu.org/ml/gcc/2007-06/msg00122.html> and
04863                      <http://msdn2.microsoft.com/en-us/library/ms175782(VS.80).aspx>
04864                    So we should avoid %n in this situation.  */
04865                 fbp[1] = '\0';
04866 # endif
04867 #else
04868                 fbp[1] = '\0';
04869 #endif
04870 
04871                 /* Construct the arguments for calling snprintf or sprintf.  */
04872                 prefix_count = 0;
04873                 if (!pad_ourselves && dp->width_arg_index != ARG_NONE)
04874                   {
04875                     if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
04876                       abort ();
04877                     prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int;
04878                   }
04879                 if (!prec_ourselves && dp->precision_arg_index != ARG_NONE)
04880                   {
04881                     if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
04882                       abort ();
04883                     prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int;
04884                   }
04885 
04886 #if USE_SNPRINTF
04887                 /* The SNPRINTF result is appended after result[0..length].
04888                    The latter is an array of DCHAR_T; SNPRINTF appends an
04889                    array of TCHAR_T to it.  This is possible because
04890                    sizeof (TCHAR_T) divides sizeof (DCHAR_T) and
04891                    alignof (TCHAR_T) <= alignof (DCHAR_T).  */
04892 # define TCHARS_PER_DCHAR (sizeof (DCHAR_T) / sizeof (TCHAR_T))
04893                 /* Ensure that maxlen below will be >= 2.  Needed on BeOS,
04894                    where an snprintf() with maxlen==1 acts like sprintf().  */
04895                 ENSURE_ALLOCATION (xsum (length,
04896                                          (2 + TCHARS_PER_DCHAR - 1)
04897                                          / TCHARS_PER_DCHAR));
04898                 /* Prepare checking whether snprintf returns the count
04899                    via %n.  */
04900                 *(TCHAR_T *) (result + length) = '\0';
04901 #endif
04902 
04903                 for (;;)
04904                   {
04905                     int count = -1;
04906 
04907 #if USE_SNPRINTF
04908                     int retcount = 0;
04909                     size_t maxlen = allocated - length;
04910                     /* SNPRINTF can fail if its second argument is
04911                        > INT_MAX.  */
04912                     if (maxlen > INT_MAX / TCHARS_PER_DCHAR)
04913                       maxlen = INT_MAX / TCHARS_PER_DCHAR;
04914                     maxlen = maxlen * TCHARS_PER_DCHAR;
04915 # define SNPRINTF_BUF(arg) \
04916                     switch (prefix_count)                                   \
04917                       {                                                     \
04918                       case 0:                                               \
04919                         retcount = SNPRINTF ((TCHAR_T *) (result + length), \
04920                                              maxlen, buf,                   \
04921                                              arg, &count);                  \
04922                         break;                                              \
04923                       case 1:                                               \
04924                         retcount = SNPRINTF ((TCHAR_T *) (result + length), \
04925                                              maxlen, buf,                   \
04926                                              prefixes[0], arg, &count);     \
04927                         break;                                              \
04928                       case 2:                                               \
04929                         retcount = SNPRINTF ((TCHAR_T *) (result + length), \
04930                                              maxlen, buf,                   \
04931                                              prefixes[0], prefixes[1], arg, \
04932                                              &count);                       \
04933                         break;                                              \
04934                       default:                                              \
04935                         abort ();                                           \
04936                       }
04937 #else
04938 # define SNPRINTF_BUF(arg) \
04939                     switch (prefix_count)                                   \
04940                       {                                                     \
04941                       case 0:                                               \
04942                         count = sprintf (tmp, buf, arg);                    \
04943                         break;                                              \
04944                       case 1:                                               \
04945                         count = sprintf (tmp, buf, prefixes[0], arg);       \
04946                         break;                                              \
04947                       case 2:                                               \
04948                         count = sprintf (tmp, buf, prefixes[0], prefixes[1],\
04949                                          arg);                              \
04950                         break;                                              \
04951                       default:                                              \
04952                         abort ();                                           \
04953                       }
04954 #endif
04955 
04956                     errno = 0;
04957                     switch (type)
04958                       {
04959                       case TYPE_SCHAR:
04960                         {
04961                           int arg = a.arg[dp->arg_index].a.a_schar;
04962                           SNPRINTF_BUF (arg);
04963                         }
04964                         break;
04965                       case TYPE_UCHAR:
04966                         {
04967                           unsigned int arg = a.arg[dp->arg_index].a.a_uchar;
04968                           SNPRINTF_BUF (arg);
04969                         }
04970                         break;
04971                       case TYPE_SHORT:
04972                         {
04973                           int arg = a.arg[dp->arg_index].a.a_short;
04974                           SNPRINTF_BUF (arg);
04975                         }
04976                         break;
04977                       case TYPE_USHORT:
04978                         {
04979                           unsigned int arg = a.arg[dp->arg_index].a.a_ushort;
04980                           SNPRINTF_BUF (arg);
04981                         }
04982                         break;
04983                       case TYPE_INT:
04984                         {
04985                           int arg = a.arg[dp->arg_index].a.a_int;
04986                           SNPRINTF_BUF (arg);
04987                         }
04988                         break;
04989                       case TYPE_UINT:
04990                         {
04991                           unsigned int arg = a.arg[dp->arg_index].a.a_uint;
04992                           SNPRINTF_BUF (arg);
04993                         }
04994                         break;
04995                       case TYPE_LONGINT:
04996                         {
04997                           long int arg = a.arg[dp->arg_index].a.a_longint;
04998                           SNPRINTF_BUF (arg);
04999                         }
05000                         break;
05001                       case TYPE_ULONGINT:
05002                         {
05003                           unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint;
05004                           SNPRINTF_BUF (arg);
05005                         }
05006                         break;
05007 #if HAVE_LONG_LONG_INT
05008                       case TYPE_LONGLONGINT:
05009                         {
05010                           long long int arg = a.arg[dp->arg_index].a.a_longlongint;
05011                           SNPRINTF_BUF (arg);
05012                         }
05013                         break;
05014                       case TYPE_ULONGLONGINT:
05015                         {
05016                           unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint;
05017                           SNPRINTF_BUF (arg);
05018                         }
05019                         break;
05020 #endif
05021                       case TYPE_DOUBLE:
05022                         {
05023                           double arg = a.arg[dp->arg_index].a.a_double;
05024                           SNPRINTF_BUF (arg);
05025                         }
05026                         break;
05027                       case TYPE_LONGDOUBLE:
05028                         {
05029                           long double arg = a.arg[dp->arg_index].a.a_longdouble;
05030                           SNPRINTF_BUF (arg);
05031                         }
05032                         break;
05033                       case TYPE_CHAR:
05034                         {
05035                           int arg = a.arg[dp->arg_index].a.a_char;
05036                           SNPRINTF_BUF (arg);
05037                         }
05038                         break;
05039 #if HAVE_WINT_T
05040                       case TYPE_WIDE_CHAR:
05041                         {
05042                           wint_t arg = a.arg[dp->arg_index].a.a_wide_char;
05043                           SNPRINTF_BUF (arg);
05044                         }
05045                         break;
05046 #endif
05047                       case TYPE_STRING:
05048                         {
05049                           const char *arg = a.arg[dp->arg_index].a.a_string;
05050                           SNPRINTF_BUF (arg);
05051                         }
05052                         break;
05053 #if HAVE_WCHAR_T
05054                       case TYPE_WIDE_STRING:
05055                         {
05056                           const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
05057                           SNPRINTF_BUF (arg);
05058                         }
05059                         break;
05060 #endif
05061                       case TYPE_POINTER:
05062                         {
05063                           void *arg = a.arg[dp->arg_index].a.a_pointer;
05064                           SNPRINTF_BUF (arg);
05065                         }
05066                         break;
05067                       default:
05068                         abort ();
05069                       }
05070 
05071 #if USE_SNPRINTF
05072                     /* Portability: Not all implementations of snprintf()
05073                        are ISO C 99 compliant.  Determine the number of
05074                        bytes that snprintf() has produced or would have
05075                        produced.  */
05076                     if (count >= 0)
05077                       {
05078                         /* Verify that snprintf() has NUL-terminated its
05079                            result.  */
05080                         if (count < maxlen
05081                             && ((TCHAR_T *) (result + length)) [count] != '\0')
05082                           abort ();
05083                         /* Portability hack.  */
05084                         if (retcount > count)
05085                           count = retcount;
05086                       }
05087                     else
05088                       {
05089                         /* snprintf() doesn't understand the '%n'
05090                            directive.  */
05091                         if (fbp[1] != '\0')
05092                           {
05093                             /* Don't use the '%n' directive; instead, look
05094                                at the snprintf() return value.  */
05095                             fbp[1] = '\0';
05096                             continue;
05097                           }
05098                         else
05099                           {
05100                             /* Look at the snprintf() return value.  */
05101                             if (retcount < 0)
05102                               {
05103 # if !HAVE_SNPRINTF_RETVAL_C99
05104                                 /* HP-UX 10.20 snprintf() is doubly deficient:
05105                                    It doesn't understand the '%n' directive,
05106                                    *and* it returns -1 (rather than the length
05107                                    that would have been required) when the
05108                                    buffer is too small.
05109                                    But a failure at this point can also come
05110                                    from other reasons than a too small buffer,
05111                                    such as an invalid wide string argument to
05112                                    the %ls directive, or possibly an invalid
05113                                    floating-point argument.  */
05114                                 size_t tmp_length =
05115                                   MAX_ROOM_NEEDED (&a, dp->arg_index,
05116                                                    dp->conversion, type, flags,
05117                                                    width, has_precision,
05118                                                    precision, pad_ourselves);
05119 
05120                                 if (maxlen < tmp_length)
05121                                   {
05122                                     /* Make more room.  But try to do through
05123                                        this reallocation only once.  */
05124                                     size_t bigger_need =
05125                                       xsum (length,
05126                                             xsum (tmp_length,
05127                                                   TCHARS_PER_DCHAR - 1)
05128                                             / TCHARS_PER_DCHAR);
05129                                     /* And always grow proportionally.
05130                                        (There may be several arguments, each
05131                                        needing a little more room than the
05132                                        previous one.)  */
05133                                     size_t bigger_need2 =
05134                                       xsum (xtimes (allocated, 2), 12);
05135                                     if (bigger_need < bigger_need2)
05136                                       bigger_need = bigger_need2;
05137                                     ENSURE_ALLOCATION (bigger_need);
05138                                     continue;
05139                                   }
05140 # endif
05141                               }
05142                             else
05143                               count = retcount;
05144                           }
05145                       }
05146 #endif
05147 
05148                     /* Attempt to handle failure.  */
05149                     if (count < 0)
05150                       {
05151                         /* SNPRINTF or sprintf failed.  Save and use the errno
05152                            that it has set, if any.  */
05153                         int saved_errno = errno;
05154 
05155                         if (!(result == resultbuf || result == NULL))
05156                           free (result);
05157                         if (buf_malloced != NULL)
05158                           free (buf_malloced);
05159                         CLEANUP ();
05160                         errno =
05161                           (saved_errno != 0
05162                            ? saved_errno
05163                            : (dp->conversion == 'c' || dp->conversion == 's'
05164                               ? EILSEQ
05165                               : EINVAL));
05166                         return NULL;
05167                       }
05168 
05169 #if USE_SNPRINTF
05170                     /* Handle overflow of the allocated buffer.
05171                        If such an overflow occurs, a C99 compliant snprintf()
05172                        returns a count >= maxlen.  However, a non-compliant
05173                        snprintf() function returns only count = maxlen - 1.  To
05174                        cover both cases, test whether count >= maxlen - 1.  */
05175                     if ((unsigned int) count + 1 >= maxlen)
05176                       {
05177                         /* If maxlen already has attained its allowed maximum,
05178                            allocating more memory will not increase maxlen.
05179                            Instead of looping, bail out.  */
05180                         if (maxlen == INT_MAX / TCHARS_PER_DCHAR)
05181                           goto overflow;
05182                         else
05183                           {
05184                             /* Need at least (count + 1) * sizeof (TCHAR_T)
05185                                bytes.  (The +1 is for the trailing NUL.)
05186                                But ask for (count + 2) * sizeof (TCHAR_T)
05187                                bytes, so that in the next round, we likely get
05188                                  maxlen > (unsigned int) count + 1
05189                                and so we don't get here again.
05190                                And allocate proportionally, to avoid looping
05191                                eternally if snprintf() reports a too small
05192                                count.  */
05193                             size_t n =
05194                               xmax (xsum (length,
05195                                           ((unsigned int) count + 2
05196                                            + TCHARS_PER_DCHAR - 1)
05197                                           / TCHARS_PER_DCHAR),
05198                                     xtimes (allocated, 2));
05199 
05200                             ENSURE_ALLOCATION (n);
05201                             continue;
05202                           }
05203                       }
05204 #endif
05205 
05206 #if NEED_PRINTF_UNBOUNDED_PRECISION
05207                     if (prec_ourselves)
05208                       {
05209                         /* Handle the precision.  */
05210                         TCHAR_T *prec_ptr =
05211 # if USE_SNPRINTF
05212                           (TCHAR_T *) (result + length);
05213 # else
05214                           tmp;
05215 # endif
05216                         size_t prefix_count;
05217                         size_t move;
05218 
05219                         prefix_count = 0;
05220                         /* Put the additional zeroes after the sign.  */
05221                         if (count >= 1
05222                             && (*prec_ptr == '-' || *prec_ptr == '+'
05223                                 || *prec_ptr == ' '))
05224                           prefix_count = 1;
05225                         /* Put the additional zeroes after the 0x prefix if
05226                            (flags & FLAG_ALT) || (dp->conversion == 'p').  */
05227                         else if (count >= 2
05228                                  && prec_ptr[0] == '0'
05229                                  && (prec_ptr[1] == 'x' || prec_ptr[1] == 'X'))
05230                           prefix_count = 2;
05231 
05232                         move = count - prefix_count;
05233                         if (precision > move)
05234                           {
05235                             /* Insert zeroes.  */
05236                             size_t insert = precision - move;
05237                             TCHAR_T *prec_end;
05238 
05239 # if USE_SNPRINTF
05240                             size_t n =
05241                               xsum (length,
05242                                     (count + insert + TCHARS_PER_DCHAR - 1)
05243                                     / TCHARS_PER_DCHAR);
05244                             length += (count + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR;
05245                             ENSURE_ALLOCATION (n);
05246                             length -= (count + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR;
05247                             prec_ptr = (TCHAR_T *) (result + length);
05248 # endif
05249 
05250                             prec_end = prec_ptr + count;
05251                             prec_ptr += prefix_count;
05252 
05253                             while (prec_end > prec_ptr)
05254                               {
05255                                 prec_end--;
05256                                 prec_end[insert] = prec_end[0];
05257                               }
05258 
05259                             prec_end += insert;
05260                             do
05261                               *--prec_end = '0';
05262                             while (prec_end > prec_ptr);
05263 
05264                             count += insert;
05265                           }
05266                       }
05267 #endif
05268 
05269 #if !USE_SNPRINTF
05270                     if (count >= tmp_length)
05271                       /* tmp_length was incorrectly calculated - fix the
05272                          code above!  */
05273                       abort ();
05274 #endif
05275 
05276 #if !DCHAR_IS_TCHAR
05277                     /* Convert from TCHAR_T[] to DCHAR_T[].  */
05278                     if (dp->conversion == 'c' || dp->conversion == 's')
05279                       {
05280                         /* type = TYPE_CHAR or TYPE_WIDE_CHAR or TYPE_STRING
05281                            TYPE_WIDE_STRING.
05282                            The result string is not certainly ASCII.  */
05283                         const TCHAR_T *tmpsrc;
05284                         DCHAR_T *tmpdst;
05285                         size_t tmpdst_len;
05286                         /* This code assumes that TCHAR_T is 'char'.  */
05287                         typedef int TCHAR_T_verify
05288                                     [2 * (sizeof (TCHAR_T) == 1) - 1];
05289 # if USE_SNPRINTF
05290                         tmpsrc = (TCHAR_T *) (result + length);
05291 # else
05292                         tmpsrc = tmp;
05293 # endif
05294                         tmpdst =
05295                           DCHAR_CONV_FROM_ENCODING (locale_charset (),
05296                                                     iconveh_question_mark,
05297                                                     tmpsrc, count,
05298                                                     NULL,
05299                                                     NULL, &tmpdst_len);
05300                         if (tmpdst == NULL)
05301                           {
05302                             int saved_errno = errno;
05303                             if (!(result == resultbuf || result == NULL))
05304                               free (result);
05305                             if (buf_malloced != NULL)
05306                               free (buf_malloced);
05307                             CLEANUP ();
05308                             errno = saved_errno;
05309                             return NULL;
05310                           }
05311                         ENSURE_ALLOCATION (xsum (length, tmpdst_len));
05312                         DCHAR_CPY (result + length, tmpdst, tmpdst_len);
05313                         free (tmpdst);
05314                         count = tmpdst_len;
05315                       }
05316                     else
05317                       {
05318                         /* The result string is ASCII.
05319                            Simple 1:1 conversion.  */
05320 # if USE_SNPRINTF
05321                         /* If sizeof (DCHAR_T) == sizeof (TCHAR_T), it's a
05322                            no-op conversion, in-place on the array starting
05323                            at (result + length).  */
05324                         if (sizeof (DCHAR_T) != sizeof (TCHAR_T))
05325 # endif
05326                           {
05327                             const TCHAR_T *tmpsrc;
05328                             DCHAR_T *tmpdst;
05329                             size_t n;
05330 
05331 # if USE_SNPRINTF
05332                             if (result == resultbuf)
05333                               {
05334                                 tmpsrc = (TCHAR_T *) (result + length);
05335                                 /* ENSURE_ALLOCATION will not move tmpsrc
05336                                    (because it's part of resultbuf).  */
05337                                 ENSURE_ALLOCATION (xsum (length, count));
05338                               }
05339                             else
05340                               {
05341                                 /* ENSURE_ALLOCATION will move the array
05342                                    (because it uses realloc().  */
05343                                 ENSURE_ALLOCATION (xsum (length, count));
05344                                 tmpsrc = (TCHAR_T *) (result + length);
05345                               }
05346 # else
05347                             tmpsrc = tmp;
05348                             ENSURE_ALLOCATION (xsum (length, count));
05349 # endif
05350                             tmpdst = result + length;
05351                             /* Copy backwards, because of overlapping.  */
05352                             tmpsrc += count;
05353                             tmpdst += count;
05354                             for (n = count; n > 0; n--)
05355                               *--tmpdst = (unsigned char) *--tmpsrc;
05356                           }
05357                       }
05358 #endif
05359 
05360 #if DCHAR_IS_TCHAR && !USE_SNPRINTF
05361                     /* Make room for the result.  */
05362                     if (count > allocated - length)
05363                       {
05364                         /* Need at least count elements.  But allocate
05365                            proportionally.  */
05366                         size_t n =
05367                           xmax (xsum (length, count), xtimes (allocated, 2));
05368 
05369                         ENSURE_ALLOCATION (n);
05370                       }
05371 #endif
05372 
05373                     /* Here count <= allocated - length.  */
05374 
05375                     /* Perform padding.  */
05376 #if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
05377                     if (pad_ourselves && has_width)
05378                       {
05379                         size_t w;
05380 # if ENABLE_UNISTDIO
05381                         /* Outside POSIX, it's preferrable to compare the width
05382                            against the number of _characters_ of the converted
05383                            value.  */
05384                         w = DCHAR_MBSNLEN (result + length, count);
05385 # else
05386                         /* The width is compared against the number of _bytes_
05387                            of the converted value, says POSIX.  */
05388                         w = count;
05389 # endif
05390                         if (w < width)
05391                           {
05392                             size_t pad = width - w;
05393 
05394                             /* Make room for the result.  */
05395                             if (xsum (count, pad) > allocated - length)
05396                               {
05397                                 /* Need at least count + pad elements.  But
05398                                    allocate proportionally.  */
05399                                 size_t n =
05400                                   xmax (xsum3 (length, count, pad),
05401                                         xtimes (allocated, 2));
05402 
05403 # if USE_SNPRINTF
05404                                 length += count;
05405                                 ENSURE_ALLOCATION (n);
05406                                 length -= count;
05407 # else
05408                                 ENSURE_ALLOCATION (n);
05409 # endif
05410                               }
05411                             /* Here count + pad <= allocated - length.  */
05412 
05413                             {
05414 # if !DCHAR_IS_TCHAR || USE_SNPRINTF
05415                               DCHAR_T * const rp = result + length;
05416 # else
05417                               DCHAR_T * const rp = tmp;
05418 # endif
05419                               DCHAR_T *p = rp + count;
05420                               DCHAR_T *end = p + pad;
05421                               DCHAR_T *pad_ptr;
05422 # if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO
05423                               if (dp->conversion == 'c'
05424                                   || dp->conversion == 's')
05425                                 /* No zero-padding for string directives.  */
05426                                 pad_ptr = NULL;
05427                               else
05428 # endif
05429                                 {
05430                                   pad_ptr = (*rp == '-' ? rp + 1 : rp);
05431                                   /* No zero-padding of "inf" and "nan".  */
05432                                   if ((*pad_ptr >= 'A' && *pad_ptr <= 'Z')
05433                                       || (*pad_ptr >= 'a' && *pad_ptr <= 'z'))
05434                                     pad_ptr = NULL;
05435                                 }
05436                               /* The generated string now extends from rp to p,
05437                                  with the zero padding insertion point being at
05438                                  pad_ptr.  */
05439 
05440                               count = count + pad; /* = end - rp */
05441 
05442                               if (flags & FLAG_LEFT)
05443                                 {
05444                                   /* Pad with spaces on the right.  */
05445                                   for (; pad > 0; pad--)
05446                                     *p++ = ' ';
05447                                 }
05448                               else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
05449                                 {
05450                                   /* Pad with zeroes.  */
05451                                   DCHAR_T *q = end;
05452 
05453                                   while (p > pad_ptr)
05454                                     *--q = *--p;
05455                                   for (; pad > 0; pad--)
05456                                     *p++ = '0';
05457                                 }
05458                               else
05459                                 {
05460                                   /* Pad with spaces on the left.  */
05461                                   DCHAR_T *q = end;
05462 
05463                                   while (p > rp)
05464                                     *--q = *--p;
05465                                   for (; pad > 0; pad--)
05466                                     *p++ = ' ';
05467                                 }
05468                             }
05469                           }
05470                       }
05471 #endif
05472 
05473                     /* Here still count <= allocated - length.  */
05474 
05475 #if !DCHAR_IS_TCHAR || USE_SNPRINTF
05476                     /* The snprintf() result did fit.  */
05477 #else
05478                     /* Append the sprintf() result.  */
05479                     memcpy (result + length, tmp, count * sizeof (DCHAR_T));
05480 #endif
05481 #if !USE_SNPRINTF
05482                     if (tmp != tmpbuf)
05483                       free (tmp);
05484 #endif
05485 
05486 #if NEED_PRINTF_DIRECTIVE_F
05487                     if (dp->conversion == 'F')
05488                       {
05489                         /* Convert the %f result to upper case for %F.  */
05490                         DCHAR_T *rp = result + length;
05491                         size_t rc;
05492                         for (rc = count; rc > 0; rc--, rp++)
05493                           if (*rp >= 'a' && *rp <= 'z')
05494                             *rp = *rp - 'a' + 'A';
05495                       }
05496 #endif
05497 
05498                     length += count;
05499                     break;
05500                   }
05501 #undef pad_ourselves
05502 #undef prec_ourselves
05503               }
05504           }
05505       }
05506 
05507     /* Add the final NUL.  */
05508     ENSURE_ALLOCATION (xsum (length, 1));
05509     result[length] = '\0';
05510 
05511     if (result != resultbuf && length + 1 < allocated)
05512       {
05513         /* Shrink the allocated memory if possible.  */
05514         DCHAR_T *memory;
05515 
05516         memory = (DCHAR_T *) realloc (result, (length + 1) * sizeof (DCHAR_T));
05517         if (memory != NULL)
05518           result = memory;
05519       }
05520 
05521     if (buf_malloced != NULL)
05522       free (buf_malloced);
05523     CLEANUP ();
05524     *lengthp = length;
05525     /* Note that we can produce a big string of a length > INT_MAX.  POSIX
05526        says that snprintf() fails with errno = EOVERFLOW in this case, but
05527        that's only because snprintf() returns an 'int'.  This function does
05528        not have this limitation.  */
05529     return result;
05530 
05531 #if USE_SNPRINTF
05532   overflow:
05533     if (!(result == resultbuf || result == NULL))
05534       free (result);
05535     if (buf_malloced != NULL)
05536       free (buf_malloced);
05537     CLEANUP ();
05538     errno = EOVERFLOW;
05539     return NULL;
05540 #endif
05541 
05542   out_of_memory:
05543     if (!(result == resultbuf || result == NULL))
05544       free (result);
05545     if (buf_malloced != NULL)
05546       free (buf_malloced);
05547   out_of_memory_1:
05548     CLEANUP ();
05549     errno = ENOMEM;
05550     return NULL;
05551   }
05552 }
05553 
05554 #undef MAX_ROOM_NEEDED
05555 #undef TCHARS_PER_DCHAR
05556 #undef SNPRINTF
05557 #undef USE_SNPRINTF
05558 #undef DCHAR_SET
05559 #undef DCHAR_CPY
05560 #undef PRINTF_PARSE
05561 #undef DIRECTIVES
05562 #undef DIRECTIVE
05563 #undef DCHAR_IS_TCHAR
05564 #undef TCHAR_T
05565 #undef DCHAR_T
05566 #undef FCHAR_T
05567 #undef VASNPRINTF