2N/A/* vsprintf with automatic memory allocation.
2N/A Copyright (C) 1999, 2002-2010 Free Software Foundation, Inc.
2N/A
2N/A This program is free software; you can redistribute it and/or modify
2N/A it under the terms of the GNU General Public License as published by
2N/A the Free Software Foundation; either version 3, or (at your option)
2N/A any later version.
2N/A
2N/A This program is distributed in the hope that it will be useful,
2N/A but WITHOUT ANY WARRANTY; without even the implied warranty of
2N/A MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2N/A GNU General Public License for more details.
2N/A
2N/A You should have received a copy of the GNU General Public License along
2N/A with this program; if not, write to the Free Software Foundation,
2N/A Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
2N/A
2N/A/* This file can be parametrized with the following macros:
2N/A VASNPRINTF The name of the function being defined.
2N/A FCHAR_T The element type of the format string.
2N/A DCHAR_T The element type of the destination (result) string.
2N/A FCHAR_T_ONLY_ASCII Set to 1 to enable verification that all characters
2N/A in the format string are ASCII. MUST be set if
2N/A FCHAR_T and DCHAR_T are not the same type.
2N/A DIRECTIVE Structure denoting a format directive.
2N/A Depends on FCHAR_T.
2N/A DIRECTIVES Structure denoting the set of format directives of a
2N/A format string. Depends on FCHAR_T.
2N/A PRINTF_PARSE Function that parses a format string.
2N/A Depends on FCHAR_T.
2N/A DCHAR_CPY memcpy like function for DCHAR_T[] arrays.
2N/A DCHAR_SET memset like function for DCHAR_T[] arrays.
2N/A DCHAR_MBSNLEN mbsnlen like function for DCHAR_T[] arrays.
2N/A SNPRINTF The system's snprintf (or similar) function.
2N/A This may be either snprintf or swprintf.
2N/A TCHAR_T The element type of the argument and result string
2N/A of the said SNPRINTF function. This may be either
2N/A char or wchar_t. The code exploits that
2N/A sizeof (TCHAR_T) | sizeof (DCHAR_T) and
2N/A alignof (TCHAR_T) <= alignof (DCHAR_T).
2N/A DCHAR_IS_TCHAR Set to 1 if DCHAR_T and TCHAR_T are the same type.
2N/A DCHAR_CONV_FROM_ENCODING A function to convert from char[] to DCHAR[].
2N/A DCHAR_IS_UINT8_T Set to 1 if DCHAR_T is uint8_t.
2N/A DCHAR_IS_UINT16_T Set to 1 if DCHAR_T is uint16_t.
2N/A DCHAR_IS_UINT32_T Set to 1 if DCHAR_T is uint32_t. */
2N/A
2N/A/* Tell glibc's <stdio.h> to provide a prototype for snprintf().
2N/A This must come before <config.h> because <config.h> may include
2N/A <features.h>, and once <features.h> has been included, it's too late. */
2N/A#ifndef _GNU_SOURCE
2N/A# define _GNU_SOURCE 1
2N/A#endif
2N/A
2N/A#ifndef VASNPRINTF
2N/A# include <config.h>
2N/A#endif
2N/A#ifndef IN_LIBINTL
2N/A# include <alloca.h>
2N/A#endif
2N/A
2N/A/* Specification. */
2N/A#ifndef VASNPRINTF
2N/A# if WIDE_CHAR_VERSION
2N/A# include "vasnwprintf.h"
2N/A# else
2N/A# include "vasnprintf.h"
2N/A# endif
2N/A#endif
2N/A
2N/A#include <locale.h> /* localeconv() */
2N/A#include <stdio.h> /* snprintf(), sprintf() */
2N/A#include <stdlib.h> /* abort(), malloc(), realloc(), free() */
2N/A#include <string.h> /* memcpy(), strlen() */
2N/A#include <errno.h> /* errno */
2N/A#include <limits.h> /* CHAR_BIT */
2N/A#include <float.h> /* DBL_MAX_EXP, LDBL_MAX_EXP */
2N/A#if HAVE_NL_LANGINFO
2N/A# include <langinfo.h>
2N/A#endif
2N/A#ifndef VASNPRINTF
2N/A# if WIDE_CHAR_VERSION
2N/A# include "wprintf-parse.h"
2N/A# else
2N/A# include "printf-parse.h"
2N/A# endif
2N/A#endif
2N/A
2N/A/* Checked size_t computations. */
2N/A#include "xsize.h"
2N/A
2N/A#if (NEED_PRINTF_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL
2N/A# include <math.h>
2N/A# include "float+.h"
2N/A#endif
2N/A
2N/A#if (NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL
2N/A# include <math.h>
2N/A# include "isnand-nolibm.h"
2N/A#endif
2N/A
2N/A#if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE) && !defined IN_LIBINTL
2N/A# include <math.h>
2N/A# include "isnanl-nolibm.h"
2N/A# include "fpucw.h"
2N/A#endif
2N/A
2N/A#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL
2N/A# include <math.h>
2N/A# include "isnand-nolibm.h"
2N/A# include "printf-frexp.h"
2N/A#endif
2N/A
2N/A#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL
2N/A# include <math.h>
2N/A# include "isnanl-nolibm.h"
2N/A# include "printf-frexpl.h"
2N/A# include "fpucw.h"
2N/A#endif
2N/A
2N/A/* Default parameters. */
2N/A#ifndef VASNPRINTF
2N/A# if WIDE_CHAR_VERSION
2N/A# define VASNPRINTF vasnwprintf
2N/A# define FCHAR_T wchar_t
2N/A# define DCHAR_T wchar_t
2N/A# define TCHAR_T wchar_t
2N/A# define DCHAR_IS_TCHAR 1
2N/A# define DIRECTIVE wchar_t_directive
2N/A# define DIRECTIVES wchar_t_directives
2N/A# define PRINTF_PARSE wprintf_parse
2N/A# define DCHAR_CPY wmemcpy
2N/A# define DCHAR_SET wmemset
2N/A# else
2N/A# define VASNPRINTF vasnprintf
2N/A# define FCHAR_T char
2N/A# define DCHAR_T char
2N/A# define TCHAR_T char
2N/A# define DCHAR_IS_TCHAR 1
2N/A# define DIRECTIVE char_directive
2N/A# define DIRECTIVES char_directives
2N/A# define PRINTF_PARSE printf_parse
2N/A# define DCHAR_CPY memcpy
2N/A# define DCHAR_SET memset
2N/A# endif
2N/A#endif
2N/A#if WIDE_CHAR_VERSION
2N/A /* TCHAR_T is wchar_t. */
2N/A# define USE_SNPRINTF 1
2N/A# if HAVE_DECL__SNWPRINTF
2N/A /* On Windows, the function swprintf() has a different signature than
2N/A on Unix; we use the function _snwprintf() or - on mingw - snwprintf()
2N/A instead. The mingw function snwprintf() has fewer bugs than the
2N/A MSVCRT function _snwprintf(), so prefer that. */
2N/A# if defined __MINGW32__
2N/A# define SNPRINTF snwprintf
2N/A# else
2N/A# define SNPRINTF _snwprintf
2N/A# endif
2N/A# else
2N/A /* Unix. */
2N/A# define SNPRINTF swprintf
2N/A# endif
2N/A#else
2N/A /* TCHAR_T is char. */
2N/A /* Use snprintf if it exists under the name 'snprintf' or '_snprintf'.
2N/A But don't use it on BeOS, since BeOS snprintf produces no output if the
2N/A size argument is >= 0x3000000.
2N/A Also don't use it on Linux libc5, since there snprintf with size = 1
2N/A writes any output without bounds, like sprintf. */
2N/A# if (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF) && !defined __BEOS__ && !(__GNU_LIBRARY__ == 1)
2N/A# define USE_SNPRINTF 1
2N/A# else
2N/A# define USE_SNPRINTF 0
2N/A# endif
2N/A# if HAVE_DECL__SNPRINTF
2N/A /* Windows. The mingw function snprintf() has fewer bugs than the MSVCRT
2N/A function _snprintf(), so prefer that. */
2N/A# if defined __MINGW32__
2N/A# define SNPRINTF snprintf
2N/A /* Here we need to call the native snprintf, not rpl_snprintf. */
2N/A# undef snprintf
2N/A# else
2N/A# define SNPRINTF _snprintf
2N/A# endif
2N/A# else
2N/A /* Unix. */
2N/A# define SNPRINTF snprintf
2N/A /* Here we need to call the native snprintf, not rpl_snprintf. */
2N/A# undef snprintf
2N/A# endif
2N/A#endif
2N/A/* Here we need to call the native sprintf, not rpl_sprintf. */
2N/A#undef sprintf
2N/A
2N/A/* GCC >= 4.0 with -Wall emits unjustified "... may be used uninitialized"
2N/A warnings in this file. Use -Dlint to suppress them. */
2N/A#ifdef lint
2N/A# define IF_LINT(Code) Code
2N/A#else
2N/A# define IF_LINT(Code) /* empty */
2N/A#endif
2N/A
2N/A/* Avoid some warnings from "gcc -Wshadow".
2N/A This file doesn't use the exp() and remainder() functions. */
2N/A#undef exp
2N/A#define exp expo
2N/A#undef remainder
2N/A#define remainder rem
2N/A
2N/A#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && !WIDE_CHAR_VERSION
2N/A# if (HAVE_STRNLEN && !defined _AIX)
2N/A# define local_strnlen strnlen
2N/A# else
2N/A# ifndef local_strnlen_defined
2N/A# define local_strnlen_defined 1
2N/Astatic size_t
2N/Alocal_strnlen (const char *string, size_t maxlen)
2N/A{
2N/A const char *end = memchr (string, '\0', maxlen);
2N/A return end ? (size_t) (end - string) : maxlen;
2N/A}
2N/A# endif
2N/A# endif
2N/A#endif
2N/A
2N/A#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
2N/A# if HAVE_WCSLEN
2N/A# define local_wcslen wcslen
2N/A# else
2N/A /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid
2N/A a dependency towards this library, here is a local substitute.
2N/A Define this substitute only once, even if this file is included
2N/A twice in the same compilation unit. */
2N/A# ifndef local_wcslen_defined
2N/A# define local_wcslen_defined 1
2N/Astatic size_t
2N/Alocal_wcslen (const wchar_t *s)
2N/A{
2N/A const wchar_t *ptr;
2N/A
2N/A for (ptr = s; *ptr != (wchar_t) 0; ptr++)
2N/A ;
2N/A return ptr - s;
2N/A}
2N/A# endif
2N/A# endif
2N/A#endif
2N/A
2N/A#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && HAVE_WCHAR_T && WIDE_CHAR_VERSION
2N/A# if HAVE_WCSNLEN
2N/A# define local_wcsnlen wcsnlen
2N/A# else
2N/A# ifndef local_wcsnlen_defined
2N/A# define local_wcsnlen_defined 1
2N/Astatic size_t
2N/Alocal_wcsnlen (const wchar_t *s, size_t maxlen)
2N/A{
2N/A const wchar_t *ptr;
2N/A
2N/A for (ptr = s; maxlen > 0 && *ptr != (wchar_t) 0; ptr++, maxlen--)
2N/A ;
2N/A return ptr - s;
2N/A}
2N/A# endif
2N/A# endif
2N/A#endif
2N/A
2N/A#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL
2N/A/* Determine the decimal-point character according to the current locale. */
2N/A# ifndef decimal_point_char_defined
2N/A# define decimal_point_char_defined 1
2N/Astatic char
2N/Adecimal_point_char (void)
2N/A{
2N/A const char *point;
2N/A /* Determine it in a multithread-safe way. We know nl_langinfo is
2N/A multithread-safe on glibc systems and MacOS X systems, but is not required
2N/A to be multithread-safe by POSIX. sprintf(), however, is multithread-safe.
2N/A localeconv() is rarely multithread-safe. */
2N/A# if HAVE_NL_LANGINFO && (__GLIBC__ || (defined __APPLE__ && defined __MACH__))
2N/A point = nl_langinfo (RADIXCHAR);
2N/A# elif 1
2N/A char pointbuf[5];
2N/A sprintf (pointbuf, "%#.0f", 1.0);
2N/A point = &pointbuf[1];
2N/A# else
2N/A point = localeconv () -> decimal_point;
2N/A# endif
2N/A /* The decimal point is always a single byte: either '.' or ','. */
2N/A return (point[0] != '\0' ? point[0] : '.');
2N/A}
2N/A# endif
2N/A#endif
2N/A
2N/A#if NEED_PRINTF_INFINITE_DOUBLE && !NEED_PRINTF_DOUBLE && !defined IN_LIBINTL
2N/A
2N/A/* Equivalent to !isfinite(x) || x == 0, but does not require libm. */
2N/Astatic int
2N/Ais_infinite_or_zero (double x)
2N/A{
2N/A return isnand (x) || x + x == x;
2N/A}
2N/A
2N/A#endif
2N/A
2N/A#if NEED_PRINTF_INFINITE_LONG_DOUBLE && !NEED_PRINTF_LONG_DOUBLE && !defined IN_LIBINTL
2N/A
2N/A/* Equivalent to !isfinite(x) || x == 0, but does not require libm. */
2N/Astatic int
2N/Ais_infinite_or_zerol (long double x)
2N/A{
2N/A return isnanl (x) || x + x == x;
2N/A}
2N/A
2N/A#endif
2N/A
2N/A#if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL
2N/A
2N/A/* Converting 'long double' to decimal without rare rounding bugs requires
2N/A real bignums. We use the naming conventions of GNU gmp, but vastly simpler
2N/A (and slower) algorithms. */
2N/A
2N/Atypedef unsigned int mp_limb_t;
2N/A# define GMP_LIMB_BITS 32
2N/Atypedef int mp_limb_verify[2 * (sizeof (mp_limb_t) * CHAR_BIT == GMP_LIMB_BITS) - 1];
2N/A
2N/Atypedef unsigned long long mp_twolimb_t;
2N/A# define GMP_TWOLIMB_BITS 64
2N/Atypedef int mp_twolimb_verify[2 * (sizeof (mp_twolimb_t) * CHAR_BIT == GMP_TWOLIMB_BITS) - 1];
2N/A
2N/A/* Representation of a bignum >= 0. */
2N/Atypedef struct
2N/A{
2N/A size_t nlimbs;
2N/A mp_limb_t *limbs; /* Bits in little-endian order, allocated with malloc(). */
2N/A} mpn_t;
2N/A
2N/A/* Compute the product of two bignums >= 0.
2N/A Return the allocated memory in case of success, NULL in case of memory
2N/A allocation failure. */
2N/Astatic void *
2N/Amultiply (mpn_t src1, mpn_t src2, mpn_t *dest)
2N/A{
2N/A const mp_limb_t *p1;
2N/A const mp_limb_t *p2;
2N/A size_t len1;
2N/A size_t len2;
2N/A
2N/A if (src1.nlimbs <= src2.nlimbs)
2N/A {
2N/A len1 = src1.nlimbs;
2N/A p1 = src1.limbs;
2N/A len2 = src2.nlimbs;
2N/A p2 = src2.limbs;
2N/A }
2N/A else
2N/A {
2N/A len1 = src2.nlimbs;
2N/A p1 = src2.limbs;
2N/A len2 = src1.nlimbs;
2N/A p2 = src1.limbs;
2N/A }
2N/A /* Now 0 <= len1 <= len2. */
2N/A if (len1 == 0)
2N/A {
2N/A /* src1 or src2 is zero. */
2N/A dest->nlimbs = 0;
2N/A dest->limbs = (mp_limb_t *) malloc (1);
2N/A }
2N/A else
2N/A {
2N/A /* Here 1 <= len1 <= len2. */
2N/A size_t dlen;
2N/A mp_limb_t *dp;
2N/A size_t k, i, j;
2N/A
2N/A dlen = len1 + len2;
2N/A dp = (mp_limb_t *) malloc (dlen * sizeof (mp_limb_t));
2N/A if (dp == NULL)
2N/A return NULL;
2N/A for (k = len2; k > 0; )
2N/A dp[--k] = 0;
2N/A for (i = 0; i < len1; i++)
2N/A {
2N/A mp_limb_t digit1 = p1[i];
2N/A mp_twolimb_t carry = 0;
2N/A for (j = 0; j < len2; j++)
2N/A {
2N/A mp_limb_t digit2 = p2[j];
2N/A carry += (mp_twolimb_t) digit1 * (mp_twolimb_t) digit2;
2N/A carry += dp[i + j];
2N/A dp[i + j] = (mp_limb_t) carry;
2N/A carry = carry >> GMP_LIMB_BITS;
2N/A }
2N/A dp[i + len2] = (mp_limb_t) carry;
2N/A }
2N/A /* Normalise. */
2N/A while (dlen > 0 && dp[dlen - 1] == 0)
2N/A dlen--;
2N/A dest->nlimbs = dlen;
2N/A dest->limbs = dp;
2N/A }
2N/A return dest->limbs;
2N/A}
2N/A
2N/A/* Compute the quotient of a bignum a >= 0 and a bignum b > 0.
2N/A a is written as a = q * b + r with 0 <= r < b. q is the quotient, r
2N/A the remainder.
2N/A Finally, round-to-even is performed: If r > b/2 or if r = b/2 and q is odd,
2N/A q is incremented.
2N/A Return the allocated memory in case of success, NULL in case of memory
2N/A allocation failure. */
2N/Astatic void *
2N/Adivide (mpn_t a, mpn_t b, mpn_t *q)
2N/A{
2N/A /* Algorithm:
2N/A First normalise a and b: a=[a[m-1],...,a[0]], b=[b[n-1],...,b[0]]
2N/A with m>=0 and n>0 (in base beta = 2^GMP_LIMB_BITS).
2N/A If m<n, then q:=0 and r:=a.
2N/A If m>=n=1, perform a single-precision division:
2N/A r:=0, j:=m,
2N/A while j>0 do
2N/A {Here (q[m-1]*beta^(m-1)+...+q[j]*beta^j) * b[0] + r*beta^j =
2N/A = a[m-1]*beta^(m-1)+...+a[j]*beta^j und 0<=r<b[0]<beta}
2N/A j:=j-1, r:=r*beta+a[j], q[j]:=floor(r/b[0]), r:=r-b[0]*q[j].
2N/A Normalise [q[m-1],...,q[0]], yields q.
2N/A If m>=n>1, perform a multiple-precision division:
2N/A We have a/b < beta^(m-n+1).
2N/A s:=intDsize-1-(highest bit in b[n-1]), 0<=s<intDsize.
2N/A Shift a and b left by s bits, copying them. r:=a.
2N/A r=[r[m],...,r[0]], b=[b[n-1],...,b[0]] with b[n-1]>=beta/2.
2N/A For j=m-n,...,0: {Here 0 <= r < b*beta^(j+1).}
2N/A Compute q* :
2N/A q* := floor((r[j+n]*beta+r[j+n-1])/b[n-1]).
2N/A In case of overflow (q* >= beta) set q* := beta-1.
2N/A Compute c2 := ((r[j+n]*beta+r[j+n-1]) - q* * b[n-1])*beta + r[j+n-2]
2N/A and c3 := b[n-2] * q*.
2N/A {We have 0 <= c2 < 2*beta^2, even 0 <= c2 < beta^2 if no overflow
2N/A occurred. Furthermore 0 <= c3 < beta^2.
2N/A If there was overflow and
2N/A r[j+n]*beta+r[j+n-1] - q* * b[n-1] >= beta, i.e. c2 >= beta^2,
2N/A the next test can be skipped.}
2N/A While c3 > c2, {Here 0 <= c2 < c3 < beta^2}
2N/A Put q* := q* - 1, c2 := c2 + b[n-1]*beta, c3 := c3 - b[n-2].
2N/A If q* > 0:
2N/A Put r := r - b * q* * beta^j. In detail:
2N/A [r[n+j],...,r[j]] := [r[n+j],...,r[j]] - q* * [b[n-1],...,b[0]].
2N/A hence: u:=0, for i:=0 to n-1 do
2N/A u := u + q* * b[i],
2N/A r[j+i]:=r[j+i]-(u mod beta) (+ beta, if carry),
2N/A u:=u div beta (+ 1, if carry in subtraction)
2N/A r[n+j]:=r[n+j]-u.
2N/A {Since always u = (q* * [b[i-1],...,b[0]] div beta^i) + 1
2N/A < q* + 1 <= beta,
2N/A the carry u does not overflow.}
2N/A If a negative carry occurs, put q* := q* - 1
2N/A and [r[n+j],...,r[j]] := [r[n+j],...,r[j]] + [0,b[n-1],...,b[0]].
2N/A Set q[j] := q*.
2N/A Normalise [q[m-n],..,q[0]]; this yields the quotient q.
2N/A Shift [r[n-1],...,r[0]] right by s bits and normalise; this yields the
2N/A rest r.
2N/A The room for q[j] can be allocated at the memory location of r[n+j].
2N/A Finally, round-to-even:
2N/A Shift r left by 1 bit.
2N/A If r > b or if r = b and q[0] is odd, q := q+1.
2N/A */
2N/A const mp_limb_t *a_ptr = a.limbs;
2N/A size_t a_len = a.nlimbs;
2N/A const mp_limb_t *b_ptr = b.limbs;
2N/A size_t b_len = b.nlimbs;
2N/A mp_limb_t *roomptr;
2N/A mp_limb_t *tmp_roomptr = NULL;
2N/A mp_limb_t *q_ptr;
2N/A size_t q_len;
2N/A mp_limb_t *r_ptr;
2N/A size_t r_len;
2N/A
2N/A /* Allocate room for a_len+2 digits.
2N/A (Need a_len+1 digits for the real division and 1 more digit for the
2N/A final rounding of q.) */
2N/A roomptr = (mp_limb_t *) malloc ((a_len + 2) * sizeof (mp_limb_t));
2N/A if (roomptr == NULL)
2N/A return NULL;
2N/A
2N/A /* Normalise a. */
2N/A while (a_len > 0 && a_ptr[a_len - 1] == 0)
2N/A a_len--;
2N/A
2N/A /* Normalise b. */
2N/A for (;;)
2N/A {
2N/A if (b_len == 0)
2N/A /* Division by zero. */
2N/A abort ();
2N/A if (b_ptr[b_len - 1] == 0)
2N/A b_len--;
2N/A else
2N/A break;
2N/A }
2N/A
2N/A /* Here m = a_len >= 0 and n = b_len > 0. */
2N/A
2N/A if (a_len < b_len)
2N/A {
2N/A /* m<n: trivial case. q=0, r := copy of a. */
2N/A r_ptr = roomptr;
2N/A r_len = a_len;
2N/A memcpy (r_ptr, a_ptr, a_len * sizeof (mp_limb_t));
2N/A q_ptr = roomptr + a_len;
2N/A q_len = 0;
2N/A }
2N/A else if (b_len == 1)
2N/A {
2N/A /* n=1: single precision division.
2N/A beta^(m-1) <= a < beta^m ==> beta^(m-2) <= a/b < beta^m */
2N/A r_ptr = roomptr;
2N/A q_ptr = roomptr + 1;
2N/A {
2N/A mp_limb_t den = b_ptr[0];
2N/A mp_limb_t remainder = 0;
2N/A const mp_limb_t *sourceptr = a_ptr + a_len;
2N/A mp_limb_t *destptr = q_ptr + a_len;
2N/A size_t count;
2N/A for (count = a_len; count > 0; count--)
2N/A {
2N/A mp_twolimb_t num =
2N/A ((mp_twolimb_t) remainder << GMP_LIMB_BITS) | *--sourceptr;
2N/A *--destptr = num / den;
2N/A remainder = num % den;
2N/A }
2N/A /* Normalise and store r. */
2N/A if (remainder > 0)
2N/A {
2N/A r_ptr[0] = remainder;
2N/A r_len = 1;
2N/A }
2N/A else
2N/A r_len = 0;
2N/A /* Normalise q. */
2N/A q_len = a_len;
2N/A if (q_ptr[q_len - 1] == 0)
2N/A q_len--;
2N/A }
2N/A }
2N/A else
2N/A {
2N/A /* n>1: multiple precision division.
2N/A beta^(m-1) <= a < beta^m, beta^(n-1) <= b < beta^n ==>
2N/A beta^(m-n-1) <= a/b < beta^(m-n+1). */
2N/A /* Determine s. */
2N/A size_t s;
2N/A {
2N/A mp_limb_t msd = b_ptr[b_len - 1]; /* = b[n-1], > 0 */
2N/A s = 31;
2N/A if (msd >= 0x10000)
2N/A {
2N/A msd = msd >> 16;
2N/A s -= 16;
2N/A }
2N/A if (msd >= 0x100)
2N/A {
2N/A msd = msd >> 8;
2N/A s -= 8;
2N/A }
2N/A if (msd >= 0x10)
2N/A {
2N/A msd = msd >> 4;
2N/A s -= 4;
2N/A }
2N/A if (msd >= 0x4)
2N/A {
2N/A msd = msd >> 2;
2N/A s -= 2;
2N/A }
2N/A if (msd >= 0x2)
2N/A {
2N/A msd = msd >> 1;
2N/A s -= 1;
2N/A }
2N/A }
2N/A /* 0 <= s < GMP_LIMB_BITS.
2N/A Copy b, shifting it left by s bits. */
2N/A if (s > 0)
2N/A {
2N/A tmp_roomptr = (mp_limb_t *) malloc (b_len * sizeof (mp_limb_t));
2N/A if (tmp_roomptr == NULL)
2N/A {
2N/A free (roomptr);
2N/A return NULL;
2N/A }
2N/A {
2N/A const mp_limb_t *sourceptr = b_ptr;
2N/A mp_limb_t *destptr = tmp_roomptr;
2N/A mp_twolimb_t accu = 0;
2N/A size_t count;
2N/A for (count = b_len; count > 0; count--)
2N/A {
2N/A accu += (mp_twolimb_t) *sourceptr++ << s;
2N/A *destptr++ = (mp_limb_t) accu;
2N/A accu = accu >> GMP_LIMB_BITS;
2N/A }
2N/A /* accu must be zero, since that was how s was determined. */
2N/A if (accu != 0)
2N/A abort ();
2N/A }
2N/A b_ptr = tmp_roomptr;
2N/A }
2N/A /* Copy a, shifting it left by s bits, yields r.
2N/A Memory layout:
2N/A At the beginning: r = roomptr[0..a_len],
2N/A at the end: r = roomptr[0..b_len-1], q = roomptr[b_len..a_len] */
2N/A r_ptr = roomptr;
2N/A if (s == 0)
2N/A {
2N/A memcpy (r_ptr, a_ptr, a_len * sizeof (mp_limb_t));
2N/A r_ptr[a_len] = 0;
2N/A }
2N/A else
2N/A {
2N/A const mp_limb_t *sourceptr = a_ptr;
2N/A mp_limb_t *destptr = r_ptr;
2N/A mp_twolimb_t accu = 0;
2N/A size_t count;
2N/A for (count = a_len; count > 0; count--)
2N/A {
2N/A accu += (mp_twolimb_t) *sourceptr++ << s;
2N/A *destptr++ = (mp_limb_t) accu;
2N/A accu = accu >> GMP_LIMB_BITS;
2N/A }
2N/A *destptr++ = (mp_limb_t) accu;
2N/A }
2N/A q_ptr = roomptr + b_len;
2N/A q_len = a_len - b_len + 1; /* q will have m-n+1 limbs */
2N/A {
2N/A size_t j = a_len - b_len; /* m-n */
2N/A mp_limb_t b_msd = b_ptr[b_len - 1]; /* b[n-1] */
2N/A mp_limb_t b_2msd = b_ptr[b_len - 2]; /* b[n-2] */
2N/A mp_twolimb_t b_msdd = /* b[n-1]*beta+b[n-2] */
2N/A ((mp_twolimb_t) b_msd << GMP_LIMB_BITS) | b_2msd;
2N/A /* Division loop, traversed m-n+1 times.
2N/A j counts down, b is unchanged, beta/2 <= b[n-1] < beta. */
2N/A for (;;)
2N/A {
2N/A mp_limb_t q_star;
2N/A mp_limb_t c1;
2N/A if (r_ptr[j + b_len] < b_msd) /* r[j+n] < b[n-1] ? */
2N/A {
2N/A /* Divide r[j+n]*beta+r[j+n-1] by b[n-1], no overflow. */
2N/A mp_twolimb_t num =
2N/A ((mp_twolimb_t) r_ptr[j + b_len] << GMP_LIMB_BITS)
2N/A | r_ptr[j + b_len - 1];
2N/A q_star = num / b_msd;
2N/A c1 = num % b_msd;
2N/A }
2N/A else
2N/A {
2N/A /* Overflow, hence r[j+n]*beta+r[j+n-1] >= beta*b[n-1]. */
2N/A q_star = (mp_limb_t)~(mp_limb_t)0; /* q* = beta-1 */
2N/A /* Test whether r[j+n]*beta+r[j+n-1] - (beta-1)*b[n-1] >= beta
2N/A <==> r[j+n]*beta+r[j+n-1] + b[n-1] >= beta*b[n-1]+beta
2N/A <==> b[n-1] < floor((r[j+n]*beta+r[j+n-1]+b[n-1])/beta)
2N/A {<= beta !}.
2N/A If yes, jump directly to the subtraction loop.
2N/A (Otherwise, r[j+n]*beta+r[j+n-1] - (beta-1)*b[n-1] < beta
2N/A <==> floor((r[j+n]*beta+r[j+n-1]+b[n-1])/beta) = b[n-1] ) */
2N/A if (r_ptr[j + b_len] > b_msd
2N/A || (c1 = r_ptr[j + b_len - 1] + b_msd) < b_msd)
2N/A /* r[j+n] >= b[n-1]+1 or
2N/A r[j+n] = b[n-1] and the addition r[j+n-1]+b[n-1] gives a
2N/A carry. */
2N/A goto subtract;
2N/A }
2N/A /* q_star = q*,
2N/A c1 = (r[j+n]*beta+r[j+n-1]) - q* * b[n-1] (>=0, <beta). */
2N/A {
2N/A mp_twolimb_t c2 = /* c1*beta+r[j+n-2] */
2N/A ((mp_twolimb_t) c1 << GMP_LIMB_BITS) | r_ptr[j + b_len - 2];
2N/A mp_twolimb_t c3 = /* b[n-2] * q* */
2N/A (mp_twolimb_t) b_2msd * (mp_twolimb_t) q_star;
2N/A /* While c2 < c3, increase c2 and decrease c3.
2N/A Consider c3-c2. While it is > 0, decrease it by
2N/A b[n-1]*beta+b[n-2]. Because of b[n-1]*beta+b[n-2] >= beta^2/2
2N/A this can happen only twice. */
2N/A if (c3 > c2)
2N/A {
2N/A q_star = q_star - 1; /* q* := q* - 1 */
2N/A if (c3 - c2 > b_msdd)
2N/A q_star = q_star - 1; /* q* := q* - 1 */
2N/A }
2N/A }
2N/A if (q_star > 0)
2N/A subtract:
2N/A {
2N/A /* Subtract r := r - b * q* * beta^j. */
2N/A mp_limb_t cr;
2N/A {
2N/A const mp_limb_t *sourceptr = b_ptr;
2N/A mp_limb_t *destptr = r_ptr + j;
2N/A mp_twolimb_t carry = 0;
2N/A size_t count;
2N/A for (count = b_len; count > 0; count--)
2N/A {
2N/A /* Here 0 <= carry <= q*. */
2N/A carry =
2N/A carry
2N/A + (mp_twolimb_t) q_star * (mp_twolimb_t) *sourceptr++
2N/A + (mp_limb_t) ~(*destptr);
2N/A /* Here 0 <= carry <= beta*q* + beta-1. */
2N/A *destptr++ = ~(mp_limb_t) carry;
2N/A carry = carry >> GMP_LIMB_BITS; /* <= q* */
2N/A }
2N/A cr = (mp_limb_t) carry;
2N/A }
2N/A /* Subtract cr from r_ptr[j + b_len], then forget about
2N/A r_ptr[j + b_len]. */
2N/A if (cr > r_ptr[j + b_len])
2N/A {
2N/A /* Subtraction gave a carry. */
2N/A q_star = q_star - 1; /* q* := q* - 1 */
2N/A /* Add b back. */
2N/A {
2N/A const mp_limb_t *sourceptr = b_ptr;
2N/A mp_limb_t *destptr = r_ptr + j;
2N/A mp_limb_t carry = 0;
2N/A size_t count;
2N/A for (count = b_len; count > 0; count--)
2N/A {
2N/A mp_limb_t source1 = *sourceptr++;
2N/A mp_limb_t source2 = *destptr;
2N/A *destptr++ = source1 + source2 + carry;
2N/A carry =
2N/A (carry
2N/A ? source1 >= (mp_limb_t) ~source2
2N/A : source1 > (mp_limb_t) ~source2);
2N/A }
2N/A }
2N/A /* Forget about the carry and about r[j+n]. */
2N/A }
2N/A }
2N/A /* q* is determined. Store it as q[j]. */
2N/A q_ptr[j] = q_star;
2N/A if (j == 0)
2N/A break;
2N/A j--;
2N/A }
2N/A }
2N/A r_len = b_len;
2N/A /* Normalise q. */
2N/A if (q_ptr[q_len - 1] == 0)
2N/A q_len--;
2N/A# if 0 /* Not needed here, since we need r only to compare it with b/2, and
2N/A b is shifted left by s bits. */
2N/A /* Shift r right by s bits. */
2N/A if (s > 0)
2N/A {
2N/A mp_limb_t ptr = r_ptr + r_len;
2N/A mp_twolimb_t accu = 0;
2N/A size_t count;
2N/A for (count = r_len; count > 0; count--)
2N/A {
2N/A accu = (mp_twolimb_t) (mp_limb_t) accu << GMP_LIMB_BITS;
2N/A accu += (mp_twolimb_t) *--ptr << (GMP_LIMB_BITS - s);
2N/A *ptr = (mp_limb_t) (accu >> GMP_LIMB_BITS);
2N/A }
2N/A }
2N/A# endif
2N/A /* Normalise r. */
2N/A while (r_len > 0 && r_ptr[r_len - 1] == 0)
2N/A r_len--;
2N/A }
2N/A /* Compare r << 1 with b. */
2N/A if (r_len > b_len)
2N/A goto increment_q;
2N/A {
2N/A size_t i;
2N/A for (i = b_len;;)
2N/A {
2N/A mp_limb_t r_i =
2N/A (i <= r_len && i > 0 ? r_ptr[i - 1] >> (GMP_LIMB_BITS - 1) : 0)
2N/A | (i < r_len ? r_ptr[i] << 1 : 0);
2N/A mp_limb_t b_i = (i < b_len ? b_ptr[i] : 0);
2N/A if (r_i > b_i)
2N/A goto increment_q;
2N/A if (r_i < b_i)
2N/A goto keep_q;
2N/A if (i == 0)
2N/A break;
2N/A i--;
2N/A }
2N/A }
2N/A if (q_len > 0 && ((q_ptr[0] & 1) != 0))
2N/A /* q is odd. */
2N/A increment_q:
2N/A {
2N/A size_t i;
2N/A for (i = 0; i < q_len; i++)
2N/A if (++(q_ptr[i]) != 0)
2N/A goto keep_q;
2N/A q_ptr[q_len++] = 1;
2N/A }
2N/A keep_q:
2N/A if (tmp_roomptr != NULL)
2N/A free (tmp_roomptr);
2N/A q->limbs = q_ptr;
2N/A q->nlimbs = q_len;
2N/A return roomptr;
2N/A}
2N/A
2N/A/* Convert a bignum a >= 0, multiplied with 10^extra_zeroes, to decimal
2N/A representation.
2N/A Destroys the contents of a.
2N/A Return the allocated memory - containing the decimal digits in low-to-high
2N/A order, terminated with a NUL character - in case of success, NULL in case
2N/A of memory allocation failure. */
2N/Astatic char *
2N/Aconvert_to_decimal (mpn_t a, size_t extra_zeroes)
2N/A{
2N/A mp_limb_t *a_ptr = a.limbs;
2N/A size_t a_len = a.nlimbs;
2N/A /* 0.03345 is slightly larger than log(2)/(9*log(10)). */
2N/A size_t c_len = 9 * ((size_t)(a_len * (GMP_LIMB_BITS * 0.03345f)) + 1);
2N/A char *c_ptr = (char *) malloc (xsum (c_len, extra_zeroes));
2N/A if (c_ptr != NULL)
2N/A {
2N/A char *d_ptr = c_ptr;
2N/A for (; extra_zeroes > 0; extra_zeroes--)
2N/A *d_ptr++ = '0';
2N/A while (a_len > 0)
2N/A {
2N/A /* Divide a by 10^9, in-place. */
2N/A mp_limb_t remainder = 0;
2N/A mp_limb_t *ptr = a_ptr + a_len;
2N/A size_t count;
2N/A for (count = a_len; count > 0; count--)
2N/A {
2N/A mp_twolimb_t num =
2N/A ((mp_twolimb_t) remainder << GMP_LIMB_BITS) | *--ptr;
2N/A *ptr = num / 1000000000;
2N/A remainder = num % 1000000000;
2N/A }
2N/A /* Store the remainder as 9 decimal digits. */
2N/A for (count = 9; count > 0; count--)
2N/A {
2N/A *d_ptr++ = '0' + (remainder % 10);
2N/A remainder = remainder / 10;
2N/A }
2N/A /* Normalize a. */
2N/A if (a_ptr[a_len - 1] == 0)
2N/A a_len--;
2N/A }
2N/A /* Remove leading zeroes. */
2N/A while (d_ptr > c_ptr && d_ptr[-1] == '0')
2N/A d_ptr--;
2N/A /* But keep at least one zero. */
2N/A if (d_ptr == c_ptr)
2N/A *d_ptr++ = '0';
2N/A /* Terminate the string. */
2N/A *d_ptr = '\0';
2N/A }
2N/A return c_ptr;
2N/A}
2N/A
2N/A# if NEED_PRINTF_LONG_DOUBLE
2N/A
2N/A/* Assuming x is finite and >= 0:
2N/A write x as x = 2^e * m, where m is a bignum.
2N/A Return the allocated memory in case of success, NULL in case of memory
2N/A allocation failure. */
2N/Astatic void *
2N/Adecode_long_double (long double x, int *ep, mpn_t *mp)
2N/A{
2N/A mpn_t m;
2N/A int exp;
2N/A long double y;
2N/A size_t i;
2N/A
2N/A /* Allocate memory for result. */
2N/A m.nlimbs = (LDBL_MANT_BIT + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS;
2N/A m.limbs = (mp_limb_t *) malloc (m.nlimbs * sizeof (mp_limb_t));
2N/A if (m.limbs == NULL)
2N/A return NULL;
2N/A /* Split into exponential part and mantissa. */
2N/A y = frexpl (x, &exp);
2N/A if (!(y >= 0.0L && y < 1.0L))
2N/A abort ();
2N/A /* x = 2^exp * y = 2^(exp - LDBL_MANT_BIT) * (y * LDBL_MANT_BIT), and the
2N/A latter is an integer. */
2N/A /* Convert the mantissa (y * LDBL_MANT_BIT) to a sequence of limbs.
2N/A I'm not sure whether it's safe to cast a 'long double' value between
2N/A 2^31 and 2^32 to 'unsigned int', therefore play safe and cast only
2N/A 'long double' values between 0 and 2^16 (to 'unsigned int' or 'int',
2N/A doesn't matter). */
2N/A# if (LDBL_MANT_BIT % GMP_LIMB_BITS) != 0
2N/A# if (LDBL_MANT_BIT % GMP_LIMB_BITS) > GMP_LIMB_BITS / 2
2N/A {
2N/A mp_limb_t hi, lo;
2N/A y *= (mp_limb_t) 1 << (LDBL_MANT_BIT % (GMP_LIMB_BITS / 2));
2N/A hi = (int) y;
2N/A y -= hi;
2N/A if (!(y >= 0.0L && y < 1.0L))
2N/A abort ();
2N/A y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
2N/A lo = (int) y;
2N/A y -= lo;
2N/A if (!(y >= 0.0L && y < 1.0L))
2N/A abort ();
2N/A m.limbs[LDBL_MANT_BIT / GMP_LIMB_BITS] = (hi << (GMP_LIMB_BITS / 2)) | lo;
2N/A }
2N/A# else
2N/A {
2N/A mp_limb_t d;
2N/A y *= (mp_limb_t) 1 << (LDBL_MANT_BIT % GMP_LIMB_BITS);
2N/A d = (int) y;
2N/A y -= d;
2N/A if (!(y >= 0.0L && y < 1.0L))
2N/A abort ();
2N/A m.limbs[LDBL_MANT_BIT / GMP_LIMB_BITS] = d;
2N/A }
2N/A# endif
2N/A# endif
2N/A for (i = LDBL_MANT_BIT / GMP_LIMB_BITS; i > 0; )
2N/A {
2N/A mp_limb_t hi, lo;
2N/A y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
2N/A hi = (int) y;
2N/A y -= hi;
2N/A if (!(y >= 0.0L && y < 1.0L))
2N/A abort ();
2N/A y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
2N/A lo = (int) y;
2N/A y -= lo;
2N/A if (!(y >= 0.0L && y < 1.0L))
2N/A abort ();
2N/A m.limbs[--i] = (hi << (GMP_LIMB_BITS / 2)) | lo;
2N/A }
2N/A#if 0 /* On FreeBSD 6.1/x86, 'long double' numbers sometimes have excess
2N/A precision. */
2N/A if (!(y == 0.0L))
2N/A abort ();
2N/A#endif
2N/A /* Normalise. */
2N/A while (m.nlimbs > 0 && m.limbs[m.nlimbs - 1] == 0)
2N/A m.nlimbs--;
2N/A *mp = m;
2N/A *ep = exp - LDBL_MANT_BIT;
2N/A return m.limbs;
2N/A}
2N/A
2N/A# endif
2N/A
2N/A# if NEED_PRINTF_DOUBLE
2N/A
2N/A/* Assuming x is finite and >= 0:
2N/A write x as x = 2^e * m, where m is a bignum.
2N/A Return the allocated memory in case of success, NULL in case of memory
2N/A allocation failure. */
2N/Astatic void *
2N/Adecode_double (double x, int *ep, mpn_t *mp)
2N/A{
2N/A mpn_t m;
2N/A int exp;
2N/A double y;
2N/A size_t i;
2N/A
2N/A /* Allocate memory for result. */
2N/A m.nlimbs = (DBL_MANT_BIT + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS;
2N/A m.limbs = (mp_limb_t *) malloc (m.nlimbs * sizeof (mp_limb_t));
2N/A if (m.limbs == NULL)
2N/A return NULL;
2N/A /* Split into exponential part and mantissa. */
2N/A y = frexp (x, &exp);
2N/A if (!(y >= 0.0 && y < 1.0))
2N/A abort ();
2N/A /* x = 2^exp * y = 2^(exp - DBL_MANT_BIT) * (y * DBL_MANT_BIT), and the
2N/A latter is an integer. */
2N/A /* Convert the mantissa (y * DBL_MANT_BIT) to a sequence of limbs.
2N/A I'm not sure whether it's safe to cast a 'double' value between
2N/A 2^31 and 2^32 to 'unsigned int', therefore play safe and cast only
2N/A 'double' values between 0 and 2^16 (to 'unsigned int' or 'int',
2N/A doesn't matter). */
2N/A# if (DBL_MANT_BIT % GMP_LIMB_BITS) != 0
2N/A# if (DBL_MANT_BIT % GMP_LIMB_BITS) > GMP_LIMB_BITS / 2
2N/A {
2N/A mp_limb_t hi, lo;
2N/A y *= (mp_limb_t) 1 << (DBL_MANT_BIT % (GMP_LIMB_BITS / 2));
2N/A hi = (int) y;
2N/A y -= hi;
2N/A if (!(y >= 0.0 && y < 1.0))
2N/A abort ();
2N/A y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
2N/A lo = (int) y;
2N/A y -= lo;
2N/A if (!(y >= 0.0 && y < 1.0))
2N/A abort ();
2N/A m.limbs[DBL_MANT_BIT / GMP_LIMB_BITS] = (hi << (GMP_LIMB_BITS / 2)) | lo;
2N/A }
2N/A# else
2N/A {
2N/A mp_limb_t d;
2N/A y *= (mp_limb_t) 1 << (DBL_MANT_BIT % GMP_LIMB_BITS);
2N/A d = (int) y;
2N/A y -= d;
2N/A if (!(y >= 0.0 && y < 1.0))
2N/A abort ();
2N/A m.limbs[DBL_MANT_BIT / GMP_LIMB_BITS] = d;
2N/A }
2N/A# endif
2N/A# endif
2N/A for (i = DBL_MANT_BIT / GMP_LIMB_BITS; i > 0; )
2N/A {
2N/A mp_limb_t hi, lo;
2N/A y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
2N/A hi = (int) y;
2N/A y -= hi;
2N/A if (!(y >= 0.0 && y < 1.0))
2N/A abort ();
2N/A y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
2N/A lo = (int) y;
2N/A y -= lo;
2N/A if (!(y >= 0.0 && y < 1.0))
2N/A abort ();
2N/A m.limbs[--i] = (hi << (GMP_LIMB_BITS / 2)) | lo;
2N/A }
2N/A if (!(y == 0.0))
2N/A abort ();
2N/A /* Normalise. */
2N/A while (m.nlimbs > 0 && m.limbs[m.nlimbs - 1] == 0)
2N/A m.nlimbs--;
2N/A *mp = m;
2N/A *ep = exp - DBL_MANT_BIT;
2N/A return m.limbs;
2N/A}
2N/A
2N/A# endif
2N/A
2N/A/* Assuming x = 2^e * m is finite and >= 0, and n is an integer:
2N/A Returns the decimal representation of round (x * 10^n).
2N/A Return the allocated memory - containing the decimal digits in low-to-high
2N/A order, terminated with a NUL character - in case of success, NULL in case
2N/A of memory allocation failure. */
2N/Astatic char *
2N/Ascale10_round_decimal_decoded (int e, mpn_t m, void *memory, int n)
2N/A{
2N/A int s;
2N/A size_t extra_zeroes;
2N/A unsigned int abs_n;
2N/A unsigned int abs_s;
2N/A mp_limb_t *pow5_ptr;
2N/A size_t pow5_len;
2N/A unsigned int s_limbs;
2N/A unsigned int s_bits;
2N/A mpn_t pow5;
2N/A mpn_t z;
2N/A void *z_memory;
2N/A char *digits;
2N/A
2N/A if (memory == NULL)
2N/A return NULL;
2N/A /* x = 2^e * m, hence
2N/A y = round (2^e * 10^n * m) = round (2^(e+n) * 5^n * m)
2N/A = round (2^s * 5^n * m). */
2N/A s = e + n;
2N/A extra_zeroes = 0;
2N/A /* Factor out a common power of 10 if possible. */
2N/A if (s > 0 && n > 0)
2N/A {
2N/A extra_zeroes = (s < n ? s : n);
2N/A s -= extra_zeroes;
2N/A n -= extra_zeroes;
2N/A }
2N/A /* Here y = round (2^s * 5^n * m) * 10^extra_zeroes.
2N/A Before converting to decimal, we need to compute
2N/A z = round (2^s * 5^n * m). */
2N/A /* Compute 5^|n|, possibly shifted by |s| bits if n and s have the same
2N/A sign. 2.322 is slightly larger than log(5)/log(2). */
2N/A abs_n = (n >= 0 ? n : -n);
2N/A abs_s = (s >= 0 ? s : -s);
2N/A pow5_ptr = (mp_limb_t *) malloc (((int)(abs_n * (2.322f / GMP_LIMB_BITS)) + 1
2N/A + abs_s / GMP_LIMB_BITS + 1)
2N/A * sizeof (mp_limb_t));
2N/A if (pow5_ptr == NULL)
2N/A {
2N/A free (memory);
2N/A return NULL;
2N/A }
2N/A /* Initialize with 1. */
2N/A pow5_ptr[0] = 1;
2N/A pow5_len = 1;
2N/A /* Multiply with 5^|n|. */
2N/A if (abs_n > 0)
2N/A {
2N/A static mp_limb_t const small_pow5[13 + 1] =
2N/A {
2N/A 1, 5, 25, 125, 625, 3125, 15625, 78125, 390625, 1953125, 9765625,
2N/A 48828125, 244140625, 1220703125
2N/A };
2N/A unsigned int n13;
2N/A for (n13 = 0; n13 <= abs_n; n13 += 13)
2N/A {
2N/A mp_limb_t digit1 = small_pow5[n13 + 13 <= abs_n ? 13 : abs_n - n13];
2N/A size_t j;
2N/A mp_twolimb_t carry = 0;
2N/A for (j = 0; j < pow5_len; j++)
2N/A {
2N/A mp_limb_t digit2 = pow5_ptr[j];
2N/A carry += (mp_twolimb_t) digit1 * (mp_twolimb_t) digit2;
2N/A pow5_ptr[j] = (mp_limb_t) carry;
2N/A carry = carry >> GMP_LIMB_BITS;
2N/A }
2N/A if (carry > 0)
2N/A pow5_ptr[pow5_len++] = (mp_limb_t) carry;
2N/A }
2N/A }
2N/A s_limbs = abs_s / GMP_LIMB_BITS;
2N/A s_bits = abs_s % GMP_LIMB_BITS;
2N/A if (n >= 0 ? s >= 0 : s <= 0)
2N/A {
2N/A /* Multiply with 2^|s|. */
2N/A if (s_bits > 0)
2N/A {
2N/A mp_limb_t *ptr = pow5_ptr;
2N/A mp_twolimb_t accu = 0;
2N/A size_t count;
2N/A for (count = pow5_len; count > 0; count--)
2N/A {
2N/A accu += (mp_twolimb_t) *ptr << s_bits;
2N/A *ptr++ = (mp_limb_t) accu;
2N/A accu = accu >> GMP_LIMB_BITS;
2N/A }
2N/A if (accu > 0)
2N/A {
2N/A *ptr = (mp_limb_t) accu;
2N/A pow5_len++;
2N/A }
2N/A }
2N/A if (s_limbs > 0)
2N/A {
2N/A size_t count;
2N/A for (count = pow5_len; count > 0;)
2N/A {
2N/A count--;
2N/A pow5_ptr[s_limbs + count] = pow5_ptr[count];
2N/A }
2N/A for (count = s_limbs; count > 0;)
2N/A {
2N/A count--;
2N/A pow5_ptr[count] = 0;
2N/A }
2N/A pow5_len += s_limbs;
2N/A }
2N/A pow5.limbs = pow5_ptr;
2N/A pow5.nlimbs = pow5_len;
2N/A if (n >= 0)
2N/A {
2N/A /* Multiply m with pow5. No division needed. */
2N/A z_memory = multiply (m, pow5, &z);
2N/A }
2N/A else
2N/A {
2N/A /* Divide m by pow5 and round. */
2N/A z_memory = divide (m, pow5, &z);
2N/A }
2N/A }
2N/A else
2N/A {
2N/A pow5.limbs = pow5_ptr;
2N/A pow5.nlimbs = pow5_len;
2N/A if (n >= 0)
2N/A {
2N/A /* n >= 0, s < 0.
2N/A Multiply m with pow5, then divide by 2^|s|. */
2N/A mpn_t numerator;
2N/A mpn_t denominator;
2N/A void *tmp_memory;
2N/A tmp_memory = multiply (m, pow5, &numerator);
2N/A if (tmp_memory == NULL)
2N/A {
2N/A free (pow5_ptr);
2N/A free (memory);
2N/A return NULL;
2N/A }
2N/A /* Construct 2^|s|. */
2N/A {
2N/A mp_limb_t *ptr = pow5_ptr + pow5_len;
2N/A size_t i;
2N/A for (i = 0; i < s_limbs; i++)
2N/A ptr[i] = 0;
2N/A ptr[s_limbs] = (mp_limb_t) 1 << s_bits;
2N/A denominator.limbs = ptr;
2N/A denominator.nlimbs = s_limbs + 1;
2N/A }
2N/A z_memory = divide (numerator, denominator, &z);
2N/A free (tmp_memory);
2N/A }
2N/A else
2N/A {
2N/A /* n < 0, s > 0.
2N/A Multiply m with 2^s, then divide by pow5. */
2N/A mpn_t numerator;
2N/A mp_limb_t *num_ptr;
2N/A num_ptr = (mp_limb_t *) malloc ((m.nlimbs + s_limbs + 1)
2N/A * sizeof (mp_limb_t));
2N/A if (num_ptr == NULL)
2N/A {
2N/A free (pow5_ptr);
2N/A free (memory);
2N/A return NULL;
2N/A }
2N/A {
2N/A mp_limb_t *destptr = num_ptr;
2N/A {
2N/A size_t i;
2N/A for (i = 0; i < s_limbs; i++)
2N/A *destptr++ = 0;
2N/A }
2N/A if (s_bits > 0)
2N/A {
2N/A const mp_limb_t *sourceptr = m.limbs;
2N/A mp_twolimb_t accu = 0;
2N/A size_t count;
2N/A for (count = m.nlimbs; count > 0; count--)
2N/A {
2N/A accu += (mp_twolimb_t) *sourceptr++ << s_bits;
2N/A *destptr++ = (mp_limb_t) accu;
2N/A accu = accu >> GMP_LIMB_BITS;
2N/A }
2N/A if (accu > 0)
2N/A *destptr++ = (mp_limb_t) accu;
2N/A }
2N/A else
2N/A {
2N/A const mp_limb_t *sourceptr = m.limbs;
2N/A size_t count;
2N/A for (count = m.nlimbs; count > 0; count--)
2N/A *destptr++ = *sourceptr++;
2N/A }
2N/A numerator.limbs = num_ptr;
2N/A numerator.nlimbs = destptr - num_ptr;
2N/A }
2N/A z_memory = divide (numerator, pow5, &z);
2N/A free (num_ptr);
2N/A }
2N/A }
2N/A free (pow5_ptr);
2N/A free (memory);
2N/A
2N/A /* Here y = round (x * 10^n) = z * 10^extra_zeroes. */
2N/A
2N/A if (z_memory == NULL)
2N/A return NULL;
2N/A digits = convert_to_decimal (z, extra_zeroes);
2N/A free (z_memory);
2N/A return digits;
2N/A}
2N/A
2N/A# if NEED_PRINTF_LONG_DOUBLE
2N/A
2N/A/* Assuming x is finite and >= 0, and n is an integer:
2N/A Returns the decimal representation of round (x * 10^n).
2N/A Return the allocated memory - containing the decimal digits in low-to-high
2N/A order, terminated with a NUL character - in case of success, NULL in case
2N/A of memory allocation failure. */
2N/Astatic char *
2N/Ascale10_round_decimal_long_double (long double x, int n)
2N/A{
2N/A int e IF_LINT(= 0);
2N/A mpn_t m;
2N/A void *memory = decode_long_double (x, &e, &m);
2N/A return scale10_round_decimal_decoded (e, m, memory, n);
2N/A}
2N/A
2N/A# endif
2N/A
2N/A# if NEED_PRINTF_DOUBLE
2N/A
2N/A/* Assuming x is finite and >= 0, and n is an integer:
2N/A Returns the decimal representation of round (x * 10^n).
2N/A Return the allocated memory - containing the decimal digits in low-to-high
2N/A order, terminated with a NUL character - in case of success, NULL in case
2N/A of memory allocation failure. */
2N/Astatic char *
2N/Ascale10_round_decimal_double (double x, int n)
2N/A{
2N/A int e IF_LINT(= 0);
2N/A mpn_t m;
2N/A void *memory = decode_double (x, &e, &m);
2N/A return scale10_round_decimal_decoded (e, m, memory, n);
2N/A}
2N/A
2N/A# endif
2N/A
2N/A# if NEED_PRINTF_LONG_DOUBLE
2N/A
2N/A/* Assuming x is finite and > 0:
2N/A Return an approximation for n with 10^n <= x < 10^(n+1).
2N/A The approximation is usually the right n, but may be off by 1 sometimes. */
2N/Astatic int
2N/Afloorlog10l (long double x)
2N/A{
2N/A int exp;
2N/A long double y;
2N/A double z;
2N/A double l;
2N/A
2N/A /* Split into exponential part and mantissa. */
2N/A y = frexpl (x, &exp);
2N/A if (!(y >= 0.0L && y < 1.0L))
2N/A abort ();
2N/A if (y == 0.0L)
2N/A return INT_MIN;
2N/A if (y < 0.5L)
2N/A {
2N/A while (y < (1.0L / (1 << (GMP_LIMB_BITS / 2)) / (1 << (GMP_LIMB_BITS / 2))))
2N/A {
2N/A y *= 1.0L * (1 << (GMP_LIMB_BITS / 2)) * (1 << (GMP_LIMB_BITS / 2));
2N/A exp -= GMP_LIMB_BITS;
2N/A }
2N/A if (y < (1.0L / (1 << 16)))
2N/A {
2N/A y *= 1.0L * (1 << 16);
2N/A exp -= 16;
2N/A }
2N/A if (y < (1.0L / (1 << 8)))
2N/A {
2N/A y *= 1.0L * (1 << 8);
2N/A exp -= 8;
2N/A }
2N/A if (y < (1.0L / (1 << 4)))
2N/A {
2N/A y *= 1.0L * (1 << 4);
2N/A exp -= 4;
2N/A }
2N/A if (y < (1.0L / (1 << 2)))
2N/A {
2N/A y *= 1.0L * (1 << 2);
2N/A exp -= 2;
2N/A }
2N/A if (y < (1.0L / (1 << 1)))
2N/A {
2N/A y *= 1.0L * (1 << 1);
2N/A exp -= 1;
2N/A }
2N/A }
2N/A if (!(y >= 0.5L && y < 1.0L))
2N/A abort ();
2N/A /* Compute an approximation for l = log2(x) = exp + log2(y). */
2N/A l = exp;
2N/A z = y;
2N/A if (z < 0.70710678118654752444)
2N/A {
2N/A z *= 1.4142135623730950488;
2N/A l -= 0.5;
2N/A }
2N/A if (z < 0.8408964152537145431)
2N/A {
2N/A z *= 1.1892071150027210667;
2N/A l -= 0.25;
2N/A }
2N/A if (z < 0.91700404320467123175)
2N/A {
2N/A z *= 1.0905077326652576592;
2N/A l -= 0.125;
2N/A }
2N/A if (z < 0.9576032806985736469)
2N/A {
2N/A z *= 1.0442737824274138403;
2N/A l -= 0.0625;
2N/A }
2N/A /* Now 0.95 <= z <= 1.01. */
2N/A z = 1 - z;
2N/A /* log2(1-z) = 1/log(2) * (- z - z^2/2 - z^3/3 - z^4/4 - ...)
2N/A Four terms are enough to get an approximation with error < 10^-7. */
2N/A l -= 1.4426950408889634074 * z * (1.0 + z * (0.5 + z * ((1.0 / 3) + z * 0.25)));
2N/A /* Finally multiply with log(2)/log(10), yields an approximation for
2N/A log10(x). */
2N/A l *= 0.30102999566398119523;
2N/A /* Round down to the next integer. */
2N/A return (int) l + (l < 0 ? -1 : 0);
2N/A}
2N/A
2N/A# endif
2N/A
2N/A# if NEED_PRINTF_DOUBLE
2N/A
2N/A/* Assuming x is finite and > 0:
2N/A Return an approximation for n with 10^n <= x < 10^(n+1).
2N/A The approximation is usually the right n, but may be off by 1 sometimes. */
2N/Astatic int
2N/Afloorlog10 (double x)
2N/A{
2N/A int exp;
2N/A double y;
2N/A double z;
2N/A double l;
2N/A
2N/A /* Split into exponential part and mantissa. */
2N/A y = frexp (x, &exp);
2N/A if (!(y >= 0.0 && y < 1.0))
2N/A abort ();
2N/A if (y == 0.0)
2N/A return INT_MIN;
2N/A if (y < 0.5)
2N/A {
2N/A while (y < (1.0 / (1 << (GMP_LIMB_BITS / 2)) / (1 << (GMP_LIMB_BITS / 2))))
2N/A {
2N/A y *= 1.0 * (1 << (GMP_LIMB_BITS / 2)) * (1 << (GMP_LIMB_BITS / 2));
2N/A exp -= GMP_LIMB_BITS;
2N/A }
2N/A if (y < (1.0 / (1 << 16)))
2N/A {
2N/A y *= 1.0 * (1 << 16);
2N/A exp -= 16;
2N/A }
2N/A if (y < (1.0 / (1 << 8)))
2N/A {
2N/A y *= 1.0 * (1 << 8);
2N/A exp -= 8;
2N/A }
2N/A if (y < (1.0 / (1 << 4)))
2N/A {
2N/A y *= 1.0 * (1 << 4);
2N/A exp -= 4;
2N/A }
2N/A if (y < (1.0 / (1 << 2)))
2N/A {
2N/A y *= 1.0 * (1 << 2);
2N/A exp -= 2;
2N/A }
2N/A if (y < (1.0 / (1 << 1)))
2N/A {
2N/A y *= 1.0 * (1 << 1);
2N/A exp -= 1;
2N/A }
2N/A }
2N/A if (!(y >= 0.5 && y < 1.0))
2N/A abort ();
2N/A /* Compute an approximation for l = log2(x) = exp + log2(y). */
2N/A l = exp;
2N/A z = y;
2N/A if (z < 0.70710678118654752444)
2N/A {
2N/A z *= 1.4142135623730950488;
2N/A l -= 0.5;
2N/A }
2N/A if (z < 0.8408964152537145431)
2N/A {
2N/A z *= 1.1892071150027210667;
2N/A l -= 0.25;
2N/A }
2N/A if (z < 0.91700404320467123175)
2N/A {
2N/A z *= 1.0905077326652576592;
2N/A l -= 0.125;
2N/A }
2N/A if (z < 0.9576032806985736469)
2N/A {
2N/A z *= 1.0442737824274138403;
2N/A l -= 0.0625;
2N/A }
2N/A /* Now 0.95 <= z <= 1.01. */
2N/A z = 1 - z;
2N/A /* log2(1-z) = 1/log(2) * (- z - z^2/2 - z^3/3 - z^4/4 - ...)
2N/A Four terms are enough to get an approximation with error < 10^-7. */
2N/A l -= 1.4426950408889634074 * z * (1.0 + z * (0.5 + z * ((1.0 / 3) + z * 0.25)));
2N/A /* Finally multiply with log(2)/log(10), yields an approximation for
2N/A log10(x). */
2N/A l *= 0.30102999566398119523;
2N/A /* Round down to the next integer. */
2N/A return (int) l + (l < 0 ? -1 : 0);
2N/A}
2N/A
2N/A# endif
2N/A
2N/A/* Tests whether a string of digits consists of exactly PRECISION zeroes and
2N/A a single '1' digit. */
2N/Astatic int
2N/Ais_borderline (const char *digits, size_t precision)
2N/A{
2N/A for (; precision > 0; precision--, digits++)
2N/A if (*digits != '0')
2N/A return 0;
2N/A if (*digits != '1')
2N/A return 0;
2N/A digits++;
2N/A return *digits == '\0';
2N/A}
2N/A
2N/A#endif
2N/A
2N/A#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99
2N/A
2N/A/* Use a different function name, to make it possible that the 'wchar_t'
2N/A parametrization and the 'char' parametrization get compiled in the same
2N/A translation unit. */
2N/A# if WIDE_CHAR_VERSION
2N/A# define MAX_ROOM_NEEDED wmax_room_needed
2N/A# else
2N/A# define MAX_ROOM_NEEDED max_room_needed
2N/A# endif
2N/A
2N/A/* Returns the number of TCHAR_T units needed as temporary space for the result
2N/A of sprintf or SNPRINTF of a single conversion directive. */
2N/Astatic inline size_t
2N/AMAX_ROOM_NEEDED (const arguments *ap, size_t arg_index, FCHAR_T conversion,
2N/A arg_type type, int flags, size_t width, int has_precision,
2N/A size_t precision, int pad_ourselves)
2N/A{
2N/A size_t tmp_length;
2N/A
2N/A switch (conversion)
2N/A {
2N/A case 'd': case 'i': case 'u':
2N/A# if HAVE_LONG_LONG_INT
2N/A if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
2N/A tmp_length =
2N/A (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
2N/A * 0.30103 /* binary -> decimal */
2N/A )
2N/A + 1; /* turn floor into ceil */
2N/A else
2N/A# endif
2N/A if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
2N/A tmp_length =
2N/A (unsigned int) (sizeof (unsigned long) * CHAR_BIT
2N/A * 0.30103 /* binary -> decimal */
2N/A )
2N/A + 1; /* turn floor into ceil */
2N/A else
2N/A tmp_length =
2N/A (unsigned int) (sizeof (unsigned int) * CHAR_BIT
2N/A * 0.30103 /* binary -> decimal */
2N/A )
2N/A + 1; /* turn floor into ceil */
2N/A if (tmp_length < precision)
2N/A tmp_length = precision;
2N/A /* Multiply by 2, as an estimate for FLAG_GROUP. */
2N/A tmp_length = xsum (tmp_length, tmp_length);
2N/A /* Add 1, to account for a leading sign. */
2N/A tmp_length = xsum (tmp_length, 1);
2N/A break;
2N/A
2N/A case 'o':
2N/A# if HAVE_LONG_LONG_INT
2N/A if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
2N/A tmp_length =
2N/A (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
2N/A * 0.333334 /* binary -> octal */
2N/A )
2N/A + 1; /* turn floor into ceil */
2N/A else
2N/A# endif
2N/A if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
2N/A tmp_length =
2N/A (unsigned int) (sizeof (unsigned long) * CHAR_BIT
2N/A * 0.333334 /* binary -> octal */
2N/A )
2N/A + 1; /* turn floor into ceil */
2N/A else
2N/A tmp_length =
2N/A (unsigned int) (sizeof (unsigned int) * CHAR_BIT
2N/A * 0.333334 /* binary -> octal */
2N/A )
2N/A + 1; /* turn floor into ceil */
2N/A if (tmp_length < precision)
2N/A tmp_length = precision;
2N/A /* Add 1, to account for a leading sign. */
2N/A tmp_length = xsum (tmp_length, 1);
2N/A break;
2N/A
2N/A case 'x': case 'X':
2N/A# if HAVE_LONG_LONG_INT
2N/A if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
2N/A tmp_length =
2N/A (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
2N/A * 0.25 /* binary -> hexadecimal */
2N/A )
2N/A + 1; /* turn floor into ceil */
2N/A else
2N/A# endif
2N/A if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
2N/A tmp_length =
2N/A (unsigned int) (sizeof (unsigned long) * CHAR_BIT
2N/A * 0.25 /* binary -> hexadecimal */
2N/A )
2N/A + 1; /* turn floor into ceil */
2N/A else
2N/A tmp_length =
2N/A (unsigned int) (sizeof (unsigned int) * CHAR_BIT
2N/A * 0.25 /* binary -> hexadecimal */
2N/A )
2N/A + 1; /* turn floor into ceil */
2N/A if (tmp_length < precision)
2N/A tmp_length = precision;
2N/A /* Add 2, to account for a leading sign or alternate form. */
2N/A tmp_length = xsum (tmp_length, 2);
2N/A break;
2N/A
2N/A case 'f': case 'F':
2N/A if (type == TYPE_LONGDOUBLE)
2N/A tmp_length =
2N/A (unsigned int) (LDBL_MAX_EXP
2N/A * 0.30103 /* binary -> decimal */
2N/A * 2 /* estimate for FLAG_GROUP */
2N/A )
2N/A + 1 /* turn floor into ceil */
2N/A + 10; /* sign, decimal point etc. */
2N/A else
2N/A tmp_length =
2N/A (unsigned int) (DBL_MAX_EXP
2N/A * 0.30103 /* binary -> decimal */
2N/A * 2 /* estimate for FLAG_GROUP */
2N/A )
2N/A + 1 /* turn floor into ceil */
2N/A + 10; /* sign, decimal point etc. */
2N/A tmp_length = xsum (tmp_length, precision);
2N/A break;
2N/A
2N/A case 'e': case 'E': case 'g': case 'G':
2N/A tmp_length =
2N/A 12; /* sign, decimal point, exponent etc. */
2N/A tmp_length = xsum (tmp_length, precision);
2N/A break;
2N/A
2N/A case 'a': case 'A':
2N/A if (type == TYPE_LONGDOUBLE)
2N/A tmp_length =
2N/A (unsigned int) (LDBL_DIG
2N/A * 0.831 /* decimal -> hexadecimal */
2N/A )
2N/A + 1; /* turn floor into ceil */
2N/A else
2N/A tmp_length =
2N/A (unsigned int) (DBL_DIG
2N/A * 0.831 /* decimal -> hexadecimal */
2N/A )
2N/A + 1; /* turn floor into ceil */
2N/A if (tmp_length < precision)
2N/A tmp_length = precision;
2N/A /* Account for sign, decimal point etc. */
2N/A tmp_length = xsum (tmp_length, 12);
2N/A break;
2N/A
2N/A case 'c':
2N/A# if HAVE_WINT_T && !WIDE_CHAR_VERSION
2N/A if (type == TYPE_WIDE_CHAR)
2N/A tmp_length = MB_CUR_MAX;
2N/A else
2N/A# endif
2N/A tmp_length = 1;
2N/A break;
2N/A
2N/A case 's':
2N/A# if HAVE_WCHAR_T
2N/A if (type == TYPE_WIDE_STRING)
2N/A {
2N/A# if WIDE_CHAR_VERSION
2N/A /* ISO C says about %ls in fwprintf:
2N/A "If the precision is not specified or is greater than the size
2N/A of the array, the array shall contain a null wide character."
2N/A So if there is a precision, we must not use wcslen. */
2N/A const wchar_t *arg = ap->arg[arg_index].a.a_wide_string;
2N/A
2N/A if (has_precision)
2N/A tmp_length = local_wcsnlen (arg, precision);
2N/A else
2N/A tmp_length = local_wcslen (arg);
2N/A# else
2N/A /* ISO C says about %ls in fprintf:
2N/A "If a precision is specified, no more than that many bytes are
2N/A written (including shift sequences, if any), and the array
2N/A shall contain a null wide character if, to equal the multibyte
2N/A character sequence length given by the precision, the function
2N/A would need to access a wide character one past the end of the
2N/A array."
2N/A So if there is a precision, we must not use wcslen. */
2N/A /* This case has already been handled separately in VASNPRINTF. */
2N/A abort ();
2N/A# endif
2N/A }
2N/A else
2N/A# endif
2N/A {
2N/A# if WIDE_CHAR_VERSION
2N/A /* ISO C says about %s in fwprintf:
2N/A "If the precision is not specified or is greater than the size
2N/A of the converted array, the converted array shall contain a
2N/A null wide character."
2N/A So if there is a precision, we must not use strlen. */
2N/A /* This case has already been handled separately in VASNPRINTF. */
2N/A abort ();
2N/A# else
2N/A /* ISO C says about %s in fprintf:
2N/A "If the precision is not specified or greater than the size of
2N/A the array, the array shall contain a null character."
2N/A So if there is a precision, we must not use strlen. */
2N/A const char *arg = ap->arg[arg_index].a.a_string;
2N/A
2N/A if (has_precision)
2N/A tmp_length = local_strnlen (arg, precision);
2N/A else
2N/A tmp_length = strlen (arg);
2N/A# endif
2N/A }
2N/A break;
2N/A
2N/A case 'p':
2N/A tmp_length =
2N/A (unsigned int) (sizeof (void *) * CHAR_BIT
2N/A * 0.25 /* binary -> hexadecimal */
2N/A )
2N/A + 1 /* turn floor into ceil */
2N/A + 2; /* account for leading 0x */
2N/A break;
2N/A
2N/A default:
2N/A abort ();
2N/A }
2N/A
2N/A if (!pad_ourselves)
2N/A {
2N/A# if ENABLE_UNISTDIO
2N/A /* Padding considers the number of characters, therefore the number of
2N/A elements after padding may be
2N/A > max (tmp_length, width)
2N/A but is certainly
2N/A <= tmp_length + width. */
2N/A tmp_length = xsum (tmp_length, width);
2N/A# else
2N/A /* Padding considers the number of elements, says POSIX. */
2N/A if (tmp_length < width)
2N/A tmp_length = width;
2N/A# endif
2N/A }
2N/A
2N/A tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
2N/A
2N/A return tmp_length;
2N/A}
2N/A
2N/A#endif
2N/A
2N/ADCHAR_T *
2N/AVASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2N/A const FCHAR_T *format, va_list args)
2N/A{
2N/A DIRECTIVES d;
2N/A arguments a;
2N/A
2N/A if (PRINTF_PARSE (format, &d, &a) < 0)
2N/A /* errno is already set. */
2N/A return NULL;
2N/A
2N/A#define CLEANUP() \
2N/A free (d.dir); \
2N/A if (a.arg) \
2N/A free (a.arg);
2N/A
2N/A if (PRINTF_FETCHARGS (args, &a) < 0)
2N/A {
2N/A CLEANUP ();
2N/A errno = EINVAL;
2N/A return NULL;
2N/A }
2N/A
2N/A {
2N/A size_t buf_neededlength;
2N/A TCHAR_T *buf;
2N/A TCHAR_T *buf_malloced;
2N/A const FCHAR_T *cp;
2N/A size_t i;
2N/A DIRECTIVE *dp;
2N/A /* Output string accumulator. */
2N/A DCHAR_T *result;
2N/A size_t allocated;
2N/A size_t length;
2N/A
2N/A /* Allocate a small buffer that will hold a directive passed to
2N/A sprintf or snprintf. */
2N/A buf_neededlength =
2N/A xsum4 (7, d.max_width_length, d.max_precision_length, 6);
2N/A#if HAVE_ALLOCA
2N/A if (buf_neededlength < 4000 / sizeof (TCHAR_T))
2N/A {
2N/A buf = (TCHAR_T *) alloca (buf_neededlength * sizeof (TCHAR_T));
2N/A buf_malloced = NULL;
2N/A }
2N/A else
2N/A#endif
2N/A {
2N/A size_t buf_memsize = xtimes (buf_neededlength, sizeof (TCHAR_T));
2N/A if (size_overflow_p (buf_memsize))
2N/A goto out_of_memory_1;
2N/A buf = (TCHAR_T *) malloc (buf_memsize);
2N/A if (buf == NULL)
2N/A goto out_of_memory_1;
2N/A buf_malloced = buf;
2N/A }
2N/A
2N/A if (resultbuf != NULL)
2N/A {
2N/A result = resultbuf;
2N/A allocated = *lengthp;
2N/A }
2N/A else
2N/A {
2N/A result = NULL;
2N/A allocated = 0;
2N/A }
2N/A length = 0;
2N/A /* Invariants:
2N/A result is either == resultbuf or == NULL or malloc-allocated.
2N/A If length > 0, then result != NULL. */
2N/A
2N/A /* Ensures that allocated >= needed. Aborts through a jump to
2N/A out_of_memory if needed is SIZE_MAX or otherwise too big. */
2N/A#define ENSURE_ALLOCATION(needed) \
2N/A if ((needed) > allocated) \
2N/A { \
2N/A size_t memory_size; \
2N/A DCHAR_T *memory; \
2N/A \
2N/A allocated = (allocated > 0 ? xtimes (allocated, 2) : 12); \
2N/A if ((needed) > allocated) \
2N/A allocated = (needed); \
2N/A memory_size = xtimes (allocated, sizeof (DCHAR_T)); \
2N/A if (size_overflow_p (memory_size)) \
2N/A goto out_of_memory; \
2N/A if (result == resultbuf || result == NULL) \
2N/A memory = (DCHAR_T *) malloc (memory_size); \
2N/A else \
2N/A memory = (DCHAR_T *) realloc (result, memory_size); \
2N/A if (memory == NULL) \
2N/A goto out_of_memory; \
2N/A if (result == resultbuf && length > 0) \
2N/A DCHAR_CPY (memory, result, length); \
2N/A result = memory; \
2N/A }
2N/A
2N/A for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++)
2N/A {
2N/A if (cp != dp->dir_start)
2N/A {
2N/A size_t n = dp->dir_start - cp;
2N/A size_t augmented_length = xsum (length, n);
2N/A
2N/A ENSURE_ALLOCATION (augmented_length);
2N/A /* This copies a piece of FCHAR_T[] into a DCHAR_T[]. Here we
2N/A need that the format string contains only ASCII characters
2N/A if FCHAR_T and DCHAR_T are not the same type. */
2N/A if (sizeof (FCHAR_T) == sizeof (DCHAR_T))
2N/A {
2N/A DCHAR_CPY (result + length, (const DCHAR_T *) cp, n);
2N/A length = augmented_length;
2N/A }
2N/A else
2N/A {
2N/A do
2N/A result[length++] = (unsigned char) *cp++;
2N/A while (--n > 0);
2N/A }
2N/A }
2N/A if (i == d.count)
2N/A break;
2N/A
2N/A /* Execute a single directive. */
2N/A if (dp->conversion == '%')
2N/A {
2N/A size_t augmented_length;
2N/A
2N/A if (!(dp->arg_index == ARG_NONE))
2N/A abort ();
2N/A augmented_length = xsum (length, 1);
2N/A ENSURE_ALLOCATION (augmented_length);
2N/A result[length] = '%';
2N/A length = augmented_length;
2N/A }
2N/A else
2N/A {
2N/A if (!(dp->arg_index != ARG_NONE))
2N/A abort ();
2N/A
2N/A if (dp->conversion == 'n')
2N/A {
2N/A switch (a.arg[dp->arg_index].type)
2N/A {
2N/A case TYPE_COUNT_SCHAR_POINTER:
2N/A *a.arg[dp->arg_index].a.a_count_schar_pointer = length;
2N/A break;
2N/A case TYPE_COUNT_SHORT_POINTER:
2N/A *a.arg[dp->arg_index].a.a_count_short_pointer = length;
2N/A break;
2N/A case TYPE_COUNT_INT_POINTER:
2N/A *a.arg[dp->arg_index].a.a_count_int_pointer = length;
2N/A break;
2N/A case TYPE_COUNT_LONGINT_POINTER:
2N/A *a.arg[dp->arg_index].a.a_count_longint_pointer = length;
2N/A break;
2N/A#if HAVE_LONG_LONG_INT
2N/A case TYPE_COUNT_LONGLONGINT_POINTER:
2N/A *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length;
2N/A break;
2N/A#endif
2N/A default:
2N/A abort ();
2N/A }
2N/A }
2N/A#if ENABLE_UNISTDIO
2N/A /* The unistdio extensions. */
2N/A else if (dp->conversion == 'U')
2N/A {
2N/A arg_type type = a.arg[dp->arg_index].type;
2N/A int flags = dp->flags;
2N/A int has_width;
2N/A size_t width;
2N/A int has_precision;
2N/A size_t precision;
2N/A
2N/A has_width = 0;
2N/A width = 0;
2N/A if (dp->width_start != dp->width_end)
2N/A {
2N/A if (dp->width_arg_index != ARG_NONE)
2N/A {
2N/A int arg;
2N/A
2N/A if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
2N/A abort ();
2N/A arg = a.arg[dp->width_arg_index].a.a_int;
2N/A if (arg < 0)
2N/A {
2N/A /* "A negative field width is taken as a '-' flag
2N/A followed by a positive field width." */
2N/A flags |= FLAG_LEFT;
2N/A width = (unsigned int) (-arg);
2N/A }
2N/A else
2N/A width = arg;
2N/A }
2N/A else
2N/A {
2N/A const FCHAR_T *digitp = dp->width_start;
2N/A
2N/A do
2N/A width = xsum (xtimes (width, 10), *digitp++ - '0');
2N/A while (digitp != dp->width_end);
2N/A }
2N/A has_width = 1;
2N/A }
2N/A
2N/A has_precision = 0;
2N/A precision = 0;
2N/A if (dp->precision_start != dp->precision_end)
2N/A {
2N/A if (dp->precision_arg_index != ARG_NONE)
2N/A {
2N/A int arg;
2N/A
2N/A if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
2N/A abort ();
2N/A arg = a.arg[dp->precision_arg_index].a.a_int;
2N/A /* "A negative precision is taken as if the precision
2N/A were omitted." */
2N/A if (arg >= 0)
2N/A {
2N/A precision = arg;
2N/A has_precision = 1;
2N/A }
2N/A }
2N/A else
2N/A {
2N/A const FCHAR_T *digitp = dp->precision_start + 1;
2N/A
2N/A precision = 0;
2N/A while (digitp != dp->precision_end)
2N/A precision = xsum (xtimes (precision, 10), *digitp++ - '0');
2N/A has_precision = 1;
2N/A }
2N/A }
2N/A
2N/A switch (type)
2N/A {
2N/A case TYPE_U8_STRING:
2N/A {
2N/A const uint8_t *arg = a.arg[dp->arg_index].a.a_u8_string;
2N/A const uint8_t *arg_end;
2N/A size_t characters;
2N/A
2N/A if (has_precision)
2N/A {
2N/A /* Use only PRECISION characters, from the left. */
2N/A arg_end = arg;
2N/A characters = 0;
2N/A for (; precision > 0; precision--)
2N/A {
2N/A int count = u8_strmblen (arg_end);
2N/A if (count == 0)
2N/A break;
2N/A if (count < 0)
2N/A {
2N/A if (!(result == resultbuf || result == NULL))
2N/A free (result);
2N/A if (buf_malloced != NULL)
2N/A free (buf_malloced);
2N/A CLEANUP ();
2N/A errno = EILSEQ;
2N/A return NULL;
2N/A }
2N/A arg_end += count;
2N/A characters++;
2N/A }
2N/A }
2N/A else if (has_width)
2N/A {
2N/A /* Use the entire string, and count the number of
2N/A characters. */
2N/A arg_end = arg;
2N/A characters = 0;
2N/A for (;;)
2N/A {
2N/A int count = u8_strmblen (arg_end);
2N/A if (count == 0)
2N/A break;
2N/A if (count < 0)
2N/A {
2N/A if (!(result == resultbuf || result == NULL))
2N/A free (result);
2N/A if (buf_malloced != NULL)
2N/A free (buf_malloced);
2N/A CLEANUP ();
2N/A errno = EILSEQ;
2N/A return NULL;
2N/A }
2N/A arg_end += count;
2N/A characters++;
2N/A }
2N/A }
2N/A else
2N/A {
2N/A /* Use the entire string. */
2N/A arg_end = arg + u8_strlen (arg);
2N/A /* The number of characters doesn't matter. */
2N/A characters = 0;
2N/A }
2N/A
2N/A if (has_width && width > characters
2N/A && !(dp->flags & FLAG_LEFT))
2N/A {
2N/A size_t n = width - characters;
2N/A ENSURE_ALLOCATION (xsum (length, n));
2N/A DCHAR_SET (result + length, ' ', n);
2N/A length += n;
2N/A }
2N/A
2N/A# if DCHAR_IS_UINT8_T
2N/A {
2N/A size_t n = arg_end - arg;
2N/A ENSURE_ALLOCATION (xsum (length, n));
2N/A DCHAR_CPY (result + length, arg, n);
2N/A length += n;
2N/A }
2N/A# else
2N/A { /* Convert. */
2N/A DCHAR_T *converted = result + length;
2N/A size_t converted_len = allocated - length;
2N/A# if DCHAR_IS_TCHAR
2N/A /* Convert from UTF-8 to locale encoding. */
2N/A converted =
2N/A u8_conv_to_encoding (locale_charset (),
2N/A iconveh_question_mark,
2N/A arg, arg_end - arg, NULL,
2N/A converted, &converted_len);
2N/A# else
2N/A /* Convert from UTF-8 to UTF-16/UTF-32. */
2N/A converted =
2N/A U8_TO_DCHAR (arg, arg_end - arg,
2N/A converted, &converted_len);
2N/A# endif
2N/A if (converted == NULL)
2N/A {
2N/A int saved_errno = errno;
2N/A if (!(result == resultbuf || result == NULL))
2N/A free (result);
2N/A if (buf_malloced != NULL)
2N/A free (buf_malloced);
2N/A CLEANUP ();
2N/A errno = saved_errno;
2N/A return NULL;
2N/A }
2N/A if (converted != result + length)
2N/A {
2N/A ENSURE_ALLOCATION (xsum (length, converted_len));
2N/A DCHAR_CPY (result + length, converted, converted_len);
2N/A free (converted);
2N/A }
2N/A length += converted_len;
2N/A }
2N/A# endif
2N/A
2N/A if (has_width && width > characters
2N/A && (dp->flags & FLAG_LEFT))
2N/A {
2N/A size_t n = width - characters;
2N/A ENSURE_ALLOCATION (xsum (length, n));
2N/A DCHAR_SET (result + length, ' ', n);
2N/A length += n;
2N/A }
2N/A }
2N/A break;
2N/A
2N/A case TYPE_U16_STRING:
2N/A {
2N/A const uint16_t *arg = a.arg[dp->arg_index].a.a_u16_string;
2N/A const uint16_t *arg_end;
2N/A size_t characters;
2N/A
2N/A if (has_precision)
2N/A {
2N/A /* Use only PRECISION characters, from the left. */
2N/A arg_end = arg;
2N/A characters = 0;
2N/A for (; precision > 0; precision--)
2N/A {
2N/A int count = u16_strmblen (arg_end);
2N/A if (count == 0)
2N/A break;
2N/A if (count < 0)
2N/A {
2N/A if (!(result == resultbuf || result == NULL))
2N/A free (result);
2N/A if (buf_malloced != NULL)
2N/A free (buf_malloced);
2N/A CLEANUP ();
2N/A errno = EILSEQ;
2N/A return NULL;
2N/A }
2N/A arg_end += count;
2N/A characters++;
2N/A }
2N/A }
2N/A else if (has_width)
2N/A {
2N/A /* Use the entire string, and count the number of
2N/A characters. */
2N/A arg_end = arg;
2N/A characters = 0;
2N/A for (;;)
2N/A {
2N/A int count = u16_strmblen (arg_end);
2N/A if (count == 0)
2N/A break;
2N/A if (count < 0)
2N/A {
2N/A if (!(result == resultbuf || result == NULL))
2N/A free (result);
2N/A if (buf_malloced != NULL)
2N/A free (buf_malloced);
2N/A CLEANUP ();
2N/A errno = EILSEQ;
2N/A return NULL;
2N/A }
2N/A arg_end += count;
2N/A characters++;
2N/A }
2N/A }
2N/A else
2N/A {
2N/A /* Use the entire string. */
2N/A arg_end = arg + u16_strlen (arg);
2N/A /* The number of characters doesn't matter. */
2N/A characters = 0;
2N/A }
2N/A
2N/A if (has_width && width > characters
2N/A && !(dp->flags & FLAG_LEFT))
2N/A {
2N/A size_t n = width - characters;
2N/A ENSURE_ALLOCATION (xsum (length, n));
2N/A DCHAR_SET (result + length, ' ', n);
2N/A length += n;
2N/A }
2N/A
2N/A# if DCHAR_IS_UINT16_T
2N/A {
2N/A size_t n = arg_end - arg;
2N/A ENSURE_ALLOCATION (xsum (length, n));
2N/A DCHAR_CPY (result + length, arg, n);
2N/A length += n;
2N/A }
2N/A# else
2N/A { /* Convert. */
2N/A DCHAR_T *converted = result + length;
2N/A size_t converted_len = allocated - length;
2N/A# if DCHAR_IS_TCHAR
2N/A /* Convert from UTF-16 to locale encoding. */
2N/A converted =
2N/A u16_conv_to_encoding (locale_charset (),
2N/A iconveh_question_mark,
2N/A arg, arg_end - arg, NULL,
2N/A converted, &converted_len);
2N/A# else
2N/A /* Convert from UTF-16 to UTF-8/UTF-32. */
2N/A converted =
2N/A U16_TO_DCHAR (arg, arg_end - arg,
2N/A converted, &converted_len);
2N/A# endif
2N/A if (converted == NULL)
2N/A {
2N/A int saved_errno = errno;
2N/A if (!(result == resultbuf || result == NULL))
2N/A free (result);
2N/A if (buf_malloced != NULL)
2N/A free (buf_malloced);
2N/A CLEANUP ();
2N/A errno = saved_errno;
2N/A return NULL;
2N/A }
2N/A if (converted != result + length)
2N/A {
2N/A ENSURE_ALLOCATION (xsum (length, converted_len));
2N/A DCHAR_CPY (result + length, converted, converted_len);
2N/A free (converted);
2N/A }
2N/A length += converted_len;
2N/A }
2N/A# endif
2N/A
2N/A if (has_width && width > characters
2N/A && (dp->flags & FLAG_LEFT))
2N/A {
2N/A size_t n = width - characters;
2N/A ENSURE_ALLOCATION (xsum (length, n));
2N/A DCHAR_SET (result + length, ' ', n);
2N/A length += n;
2N/A }
2N/A }
2N/A break;
2N/A
2N/A case TYPE_U32_STRING:
2N/A {
2N/A const uint32_t *arg = a.arg[dp->arg_index].a.a_u32_string;
2N/A const uint32_t *arg_end;
2N/A size_t characters;
2N/A
2N/A if (has_precision)
2N/A {
2N/A /* Use only PRECISION characters, from the left. */
2N/A arg_end = arg;
2N/A characters = 0;
2N/A for (; precision > 0; precision--)
2N/A {
2N/A int count = u32_strmblen (arg_end);
2N/A if (count == 0)
2N/A break;
2N/A if (count < 0)
2N/A {
2N/A if (!(result == resultbuf || result == NULL))
2N/A free (result);
2N/A if (buf_malloced != NULL)
2N/A free (buf_malloced);
2N/A CLEANUP ();
2N/A errno = EILSEQ;
2N/A return NULL;
2N/A }
2N/A arg_end += count;
2N/A characters++;
2N/A }
2N/A }
2N/A else if (has_width)
2N/A {
2N/A /* Use the entire string, and count the number of
2N/A characters. */
2N/A arg_end = arg;
2N/A characters = 0;
2N/A for (;;)
2N/A {
2N/A int count = u32_strmblen (arg_end);
2N/A if (count == 0)
2N/A break;
2N/A if (count < 0)
2N/A {
2N/A if (!(result == resultbuf || result == NULL))
2N/A free (result);
2N/A if (buf_malloced != NULL)
2N/A free (buf_malloced);
2N/A CLEANUP ();
2N/A errno = EILSEQ;
2N/A return NULL;
2N/A }
2N/A arg_end += count;
2N/A characters++;
2N/A }
2N/A }
2N/A else
2N/A {
2N/A /* Use the entire string. */
2N/A arg_end = arg + u32_strlen (arg);
2N/A /* The number of characters doesn't matter. */
2N/A characters = 0;
2N/A }
2N/A
2N/A if (has_width && width > characters
2N/A && !(dp->flags & FLAG_LEFT))
2N/A {
2N/A size_t n = width - characters;
2N/A ENSURE_ALLOCATION (xsum (length, n));
2N/A DCHAR_SET (result + length, ' ', n);
2N/A length += n;
2N/A }
2N/A
2N/A# if DCHAR_IS_UINT32_T
2N/A {
2N/A size_t n = arg_end - arg;
2N/A ENSURE_ALLOCATION (xsum (length, n));
2N/A DCHAR_CPY (result + length, arg, n);
2N/A length += n;
2N/A }
2N/A# else
2N/A { /* Convert. */
2N/A DCHAR_T *converted = result + length;
2N/A size_t converted_len = allocated - length;
2N/A# if DCHAR_IS_TCHAR
2N/A /* Convert from UTF-32 to locale encoding. */
2N/A converted =
2N/A u32_conv_to_encoding (locale_charset (),
2N/A iconveh_question_mark,
2N/A arg, arg_end - arg, NULL,
2N/A converted, &converted_len);
2N/A# else
2N/A /* Convert from UTF-32 to UTF-8/UTF-16. */
2N/A converted =
2N/A U32_TO_DCHAR (arg, arg_end - arg,
2N/A converted, &converted_len);
2N/A# endif
2N/A if (converted == NULL)
2N/A {
2N/A int saved_errno = errno;
2N/A if (!(result == resultbuf || result == NULL))
2N/A free (result);
2N/A if (buf_malloced != NULL)
2N/A free (buf_malloced);
2N/A CLEANUP ();
2N/A errno = saved_errno;
2N/A return NULL;
2N/A }
2N/A if (converted != result + length)
2N/A {
2N/A ENSURE_ALLOCATION (xsum (length, converted_len));
2N/A DCHAR_CPY (result + length, converted, converted_len);
2N/A free (converted);
2N/A }
2N/A length += converted_len;
2N/A }
2N/A# endif
2N/A
2N/A if (has_width && width > characters
2N/A && (dp->flags & FLAG_LEFT))
2N/A {
2N/A size_t n = width - characters;
2N/A ENSURE_ALLOCATION (xsum (length, n));
2N/A DCHAR_SET (result + length, ' ', n);
2N/A length += n;
2N/A }
2N/A }
2N/A break;
2N/A
2N/A default:
2N/A abort ();
2N/A }
2N/A }
2N/A#endif
2N/A#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && HAVE_WCHAR_T
2N/A else if (dp->conversion == 's'
2N/A# if WIDE_CHAR_VERSION
2N/A && a.arg[dp->arg_index].type != TYPE_WIDE_STRING
2N/A# else
2N/A && a.arg[dp->arg_index].type == TYPE_WIDE_STRING
2N/A# endif
2N/A )
2N/A {
2N/A /* The normal handling of the 's' directive below requires
2N/A allocating a temporary buffer. The determination of its
2N/A length (tmp_length), in the case when a precision is
2N/A specified, below requires a conversion between a char[]
2N/A string and a wchar_t[] wide string. It could be done, but
2N/A we have no guarantee that the implementation of sprintf will
2N/A use the exactly same algorithm. Without this guarantee, it
2N/A is possible to have buffer overrun bugs. In order to avoid
2N/A such bugs, we implement the entire processing of the 's'
2N/A directive ourselves. */
2N/A int flags = dp->flags;
2N/A int has_width;
2N/A size_t width;
2N/A int has_precision;
2N/A size_t precision;
2N/A
2N/A has_width = 0;
2N/A width = 0;
2N/A if (dp->width_start != dp->width_end)
2N/A {
2N/A if (dp->width_arg_index != ARG_NONE)
2N/A {
2N/A int arg;
2N/A
2N/A if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
2N/A abort ();
2N/A arg = a.arg[dp->width_arg_index].a.a_int;
2N/A if (arg < 0)
2N/A {
2N/A /* "A negative field width is taken as a '-' flag
2N/A followed by a positive field width." */
2N/A flags |= FLAG_LEFT;
2N/A width = (unsigned int) (-arg);
2N/A }
2N/A else
2N/A width = arg;
2N/A }
2N/A else
2N/A {
2N/A const FCHAR_T *digitp = dp->width_start;
2N/A
2N/A do
2N/A width = xsum (xtimes (width, 10), *digitp++ - '0');
2N/A while (digitp != dp->width_end);
2N/A }
2N/A has_width = 1;
2N/A }
2N/A
2N/A has_precision = 0;
2N/A precision = 6;
2N/A if (dp->precision_start != dp->precision_end)
2N/A {
2N/A if (dp->precision_arg_index != ARG_NONE)
2N/A {
2N/A int arg;
2N/A
2N/A if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
2N/A abort ();
2N/A arg = a.arg[dp->precision_arg_index].a.a_int;
2N/A /* "A negative precision is taken as if the precision
2N/A were omitted." */
2N/A if (arg >= 0)
2N/A {
2N/A precision = arg;
2N/A has_precision = 1;
2N/A }
2N/A }
2N/A else
2N/A {
2N/A const FCHAR_T *digitp = dp->precision_start + 1;
2N/A
2N/A precision = 0;
2N/A while (digitp != dp->precision_end)
2N/A precision = xsum (xtimes (precision, 10), *digitp++ - '0');
2N/A has_precision = 1;
2N/A }
2N/A }
2N/A
2N/A# if WIDE_CHAR_VERSION
2N/A /* %s in vasnwprintf. See the specification of fwprintf. */
2N/A {
2N/A const char *arg = a.arg[dp->arg_index].a.a_string;
2N/A const char *arg_end;
2N/A size_t characters;
2N/A
2N/A if (has_precision)
2N/A {
2N/A /* Use only as many bytes as needed to produce PRECISION
2N/A wide characters, from the left. */
2N/A# if HAVE_MBRTOWC
2N/A mbstate_t state;
2N/A memset (&state, '\0', sizeof (mbstate_t));
2N/A# endif
2N/A arg_end = arg;
2N/A characters = 0;
2N/A for (; precision > 0; precision--)
2N/A {
2N/A int count;
2N/A# if HAVE_MBRTOWC
2N/A count = mbrlen (arg_end, MB_CUR_MAX, &state);
2N/A# else
2N/A count = mblen (arg_end, MB_CUR_MAX);
2N/A# endif
2N/A if (count == 0)
2N/A /* Found the terminating NUL. */
2N/A break;
2N/A if (count < 0)
2N/A {
2N/A /* Invalid or incomplete multibyte character. */
2N/A if (!(result == resultbuf || result == NULL))
2N/A free (result);
2N/A if (buf_malloced != NULL)
2N/A free (buf_malloced);
2N/A CLEANUP ();
2N/A errno = EILSEQ;
2N/A return NULL;
2N/A }
2N/A arg_end += count;
2N/A characters++;
2N/A }
2N/A }
2N/A else if (has_width)
2N/A {
2N/A /* Use the entire string, and count the number of wide
2N/A characters. */
2N/A# if HAVE_MBRTOWC
2N/A mbstate_t state;
2N/A memset (&state, '\0', sizeof (mbstate_t));
2N/A# endif
2N/A arg_end = arg;
2N/A characters = 0;
2N/A for (;;)
2N/A {
2N/A int count;
2N/A# if HAVE_MBRTOWC
2N/A count = mbrlen (arg_end, MB_CUR_MAX, &state);
2N/A# else
2N/A count = mblen (arg_end, MB_CUR_MAX);
2N/A# endif
2N/A if (count == 0)
2N/A /* Found the terminating NUL. */
2N/A break;
2N/A if (count < 0)
2N/A {
2N/A /* Invalid or incomplete multibyte character. */
2N/A if (!(result == resultbuf || result == NULL))
2N/A free (result);
2N/A if (buf_malloced != NULL)
2N/A free (buf_malloced);
2N/A CLEANUP ();
2N/A errno = EILSEQ;
2N/A return NULL;
2N/A }
2N/A arg_end += count;
2N/A characters++;
2N/A }
2N/A }
2N/A else
2N/A {
2N/A /* Use the entire string. */
2N/A arg_end = arg + strlen (arg);
2N/A /* The number of characters doesn't matter. */
2N/A characters = 0;
2N/A }
2N/A
2N/A if (has_width && width > characters
2N/A && !(dp->flags & FLAG_LEFT))
2N/A {
2N/A size_t n = width - characters;
2N/A ENSURE_ALLOCATION (xsum (length, n));
2N/A DCHAR_SET (result + length, ' ', n);
2N/A length += n;
2N/A }
2N/A
2N/A if (has_precision || has_width)
2N/A {
2N/A /* We know the number of wide characters in advance. */
2N/A size_t remaining;
2N/A# if HAVE_MBRTOWC
2N/A mbstate_t state;
2N/A memset (&state, '\0', sizeof (mbstate_t));
2N/A# endif
2N/A ENSURE_ALLOCATION (xsum (length, characters));
2N/A for (remaining = characters; remaining > 0; remaining--)
2N/A {
2N/A wchar_t wc;
2N/A int count;
2N/A# if HAVE_MBRTOWC
2N/A count = mbrtowc (&wc, arg, arg_end - arg, &state);
2N/A# else
2N/A count = mbtowc (&wc, arg, arg_end - arg);
2N/A# endif
2N/A if (count <= 0)
2N/A /* mbrtowc not consistent with mbrlen, or mbtowc
2N/A not consistent with mblen. */
2N/A abort ();
2N/A result[length++] = wc;
2N/A arg += count;
2N/A }
2N/A if (!(arg == arg_end))
2N/A abort ();
2N/A }
2N/A else
2N/A {
2N/A# if HAVE_MBRTOWC
2N/A mbstate_t state;
2N/A memset (&state, '\0', sizeof (mbstate_t));
2N/A# endif
2N/A while (arg < arg_end)
2N/A {
2N/A wchar_t wc;
2N/A int count;
2N/A# if HAVE_MBRTOWC
2N/A count = mbrtowc (&wc, arg, arg_end - arg, &state);
2N/A# else
2N/A count = mbtowc (&wc, arg, arg_end - arg);
2N/A# endif
2N/A if (count <= 0)
2N/A /* mbrtowc not consistent with mbrlen, or mbtowc
2N/A not consistent with mblen. */
2N/A abort ();
2N/A ENSURE_ALLOCATION (xsum (length, 1));
2N/A result[length++] = wc;
2N/A arg += count;
2N/A }
2N/A }
2N/A
2N/A if (has_width && width > characters
2N/A && (dp->flags & FLAG_LEFT))
2N/A {
2N/A size_t n = width - characters;
2N/A ENSURE_ALLOCATION (xsum (length, n));
2N/A DCHAR_SET (result + length, ' ', n);
2N/A length += n;
2N/A }
2N/A }
2N/A# else
2N/A /* %ls in vasnprintf. See the specification of fprintf. */
2N/A {
2N/A const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
2N/A const wchar_t *arg_end;
2N/A size_t characters;
2N/A# if !DCHAR_IS_TCHAR
2N/A /* This code assumes that TCHAR_T is 'char'. */
2N/A typedef int TCHAR_T_verify[2 * (sizeof (TCHAR_T) == 1) - 1];
2N/A TCHAR_T *tmpsrc;
2N/A DCHAR_T *tmpdst;
2N/A size_t tmpdst_len;
2N/A# endif
2N/A size_t w;
2N/A
2N/A if (has_precision)
2N/A {
2N/A /* Use only as many wide characters as needed to produce
2N/A at most PRECISION bytes, from the left. */
2N/A# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2N/A mbstate_t state;
2N/A memset (&state, '\0', sizeof (mbstate_t));
2N/A# endif
2N/A arg_end = arg;
2N/A characters = 0;
2N/A while (precision > 0)
2N/A {
2N/A char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
2N/A int count;
2N/A
2N/A if (*arg_end == 0)
2N/A /* Found the terminating null wide character. */
2N/A break;
2N/A# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2N/A count = wcrtomb (cbuf, *arg_end, &state);
2N/A# else
2N/A count = wctomb (cbuf, *arg_end);
2N/A# endif
2N/A if (count < 0)
2N/A {
2N/A /* Cannot convert. */
2N/A if (!(result == resultbuf || result == NULL))
2N/A free (result);
2N/A if (buf_malloced != NULL)
2N/A free (buf_malloced);
2N/A CLEANUP ();
2N/A errno = EILSEQ;
2N/A return NULL;
2N/A }
2N/A if (precision < count)
2N/A break;
2N/A arg_end++;
2N/A characters += count;
2N/A precision -= count;
2N/A }
2N/A }
2N/A# if DCHAR_IS_TCHAR
2N/A else if (has_width)
2N/A# else
2N/A else
2N/A# endif
2N/A {
2N/A /* Use the entire string, and count the number of
2N/A bytes. */
2N/A# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2N/A mbstate_t state;
2N/A memset (&state, '\0', sizeof (mbstate_t));
2N/A# endif
2N/A arg_end = arg;
2N/A characters = 0;
2N/A for (;;)
2N/A {
2N/A char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
2N/A int count;
2N/A
2N/A if (*arg_end == 0)
2N/A /* Found the terminating null wide character. */
2N/A break;
2N/A# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2N/A count = wcrtomb (cbuf, *arg_end, &state);
2N/A# else
2N/A count = wctomb (cbuf, *arg_end);
2N/A# endif
2N/A if (count < 0)
2N/A {
2N/A /* Cannot convert. */
2N/A if (!(result == resultbuf || result == NULL))
2N/A free (result);
2N/A if (buf_malloced != NULL)
2N/A free (buf_malloced);
2N/A CLEANUP ();
2N/A errno = EILSEQ;
2N/A return NULL;
2N/A }
2N/A arg_end++;
2N/A characters += count;
2N/A }
2N/A }
2N/A# if DCHAR_IS_TCHAR
2N/A else
2N/A {
2N/A /* Use the entire string. */
2N/A arg_end = arg + local_wcslen (arg);
2N/A /* The number of bytes doesn't matter. */
2N/A characters = 0;
2N/A }
2N/A# endif
2N/A
2N/A# if !DCHAR_IS_TCHAR
2N/A /* Convert the string into a piece of temporary memory. */
2N/A tmpsrc = (TCHAR_T *) malloc (characters * sizeof (TCHAR_T));
2N/A if (tmpsrc == NULL)
2N/A goto out_of_memory;
2N/A {
2N/A TCHAR_T *tmpptr = tmpsrc;
2N/A size_t remaining;
2N/A# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2N/A mbstate_t state;
2N/A memset (&state, '\0', sizeof (mbstate_t));
2N/A# endif
2N/A for (remaining = characters; remaining > 0; )
2N/A {
2N/A char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
2N/A int count;
2N/A
2N/A if (*arg == 0)
2N/A abort ();
2N/A# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2N/A count = wcrtomb (cbuf, *arg, &state);
2N/A# else
2N/A count = wctomb (cbuf, *arg);
2N/A# endif
2N/A if (count <= 0)
2N/A /* Inconsistency. */
2N/A abort ();
2N/A memcpy (tmpptr, cbuf, count);
2N/A tmpptr += count;
2N/A arg++;
2N/A remaining -= count;
2N/A }
2N/A if (!(arg == arg_end))
2N/A abort ();
2N/A }
2N/A
2N/A /* Convert from TCHAR_T[] to DCHAR_T[]. */
2N/A tmpdst =
2N/A DCHAR_CONV_FROM_ENCODING (locale_charset (),
2N/A iconveh_question_mark,
2N/A tmpsrc, characters,
2N/A NULL,
2N/A NULL, &tmpdst_len);
2N/A if (tmpdst == NULL)
2N/A {
2N/A int saved_errno = errno;
2N/A free (tmpsrc);
2N/A if (!(result == resultbuf || result == NULL))
2N/A free (result);
2N/A if (buf_malloced != NULL)
2N/A free (buf_malloced);
2N/A CLEANUP ();
2N/A errno = saved_errno;
2N/A return NULL;
2N/A }
2N/A free (tmpsrc);
2N/A# endif
2N/A
2N/A if (has_width)
2N/A {
2N/A# if ENABLE_UNISTDIO
2N/A /* Outside POSIX, it's preferrable to compare the width
2N/A against the number of _characters_ of the converted
2N/A value. */
2N/A w = DCHAR_MBSNLEN (result + length, characters);
2N/A# else
2N/A /* The width is compared against the number of _bytes_
2N/A of the converted value, says POSIX. */
2N/A w = characters;
2N/A# endif
2N/A }
2N/A else
2N/A /* w doesn't matter. */
2N/A w = 0;
2N/A
2N/A if (has_width && width > w
2N/A && !(dp->flags & FLAG_LEFT))
2N/A {
2N/A size_t n = width - w;
2N/A ENSURE_ALLOCATION (xsum (length, n));
2N/A DCHAR_SET (result + length, ' ', n);
2N/A length += n;
2N/A }
2N/A
2N/A# if DCHAR_IS_TCHAR
2N/A if (has_precision || has_width)
2N/A {
2N/A /* We know the number of bytes in advance. */
2N/A size_t remaining;
2N/A# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2N/A mbstate_t state;
2N/A memset (&state, '\0', sizeof (mbstate_t));
2N/A# endif
2N/A ENSURE_ALLOCATION (xsum (length, characters));
2N/A for (remaining = characters; remaining > 0; )
2N/A {
2N/A char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
2N/A int count;
2N/A
2N/A if (*arg == 0)
2N/A abort ();
2N/A# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2N/A count = wcrtomb (cbuf, *arg, &state);
2N/A# else
2N/A count = wctomb (cbuf, *arg);
2N/A# endif
2N/A if (count <= 0)
2N/A /* Inconsistency. */
2N/A abort ();
2N/A memcpy (result + length, cbuf, count);
2N/A length += count;
2N/A arg++;
2N/A remaining -= count;
2N/A }
2N/A if (!(arg == arg_end))
2N/A abort ();
2N/A }
2N/A else
2N/A {
2N/A# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2N/A mbstate_t state;
2N/A memset (&state, '\0', sizeof (mbstate_t));
2N/A# endif
2N/A while (arg < arg_end)
2N/A {
2N/A char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
2N/A int count;
2N/A
2N/A if (*arg == 0)
2N/A abort ();
2N/A# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2N/A count = wcrtomb (cbuf, *arg, &state);
2N/A# else
2N/A count = wctomb (cbuf, *arg);
2N/A# endif
2N/A if (count <= 0)
2N/A {
2N/A /* Cannot convert. */
2N/A if (!(result == resultbuf || result == NULL))
2N/A free (result);
2N/A if (buf_malloced != NULL)
2N/A free (buf_malloced);
2N/A CLEANUP ();
2N/A errno = EILSEQ;
2N/A return NULL;
2N/A }
2N/A ENSURE_ALLOCATION (xsum (length, count));
2N/A memcpy (result + length, cbuf, count);
2N/A length += count;
2N/A arg++;
2N/A }
2N/A }
2N/A# else
2N/A ENSURE_ALLOCATION (xsum (length, tmpdst_len));
2N/A DCHAR_CPY (result + length, tmpdst, tmpdst_len);
2N/A free (tmpdst);
2N/A length += tmpdst_len;
2N/A# endif
2N/A
2N/A if (has_width && width > w
2N/A && (dp->flags & FLAG_LEFT))
2N/A {
2N/A size_t n = width - w;
2N/A ENSURE_ALLOCATION (xsum (length, n));
2N/A DCHAR_SET (result + length, ' ', n);
2N/A length += n;
2N/A }
2N/A }
2N/A# endif
2N/A }
2N/A#endif
2N/A#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL
2N/A else if ((dp->conversion == 'a' || dp->conversion == 'A')
2N/A# if !(NEED_PRINTF_DIRECTIVE_A || (NEED_PRINTF_LONG_DOUBLE && NEED_PRINTF_DOUBLE))
2N/A && (0
2N/A# if NEED_PRINTF_DOUBLE
2N/A || a.arg[dp->arg_index].type == TYPE_DOUBLE
2N/A# endif
2N/A# if NEED_PRINTF_LONG_DOUBLE
2N/A || a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
2N/A# endif
2N/A )
2N/A# endif
2N/A )
2N/A {
2N/A arg_type type = a.arg[dp->arg_index].type;
2N/A int flags = dp->flags;
2N/A int has_width;
2N/A size_t width;
2N/A int has_precision;
2N/A size_t precision;
2N/A size_t tmp_length;
2N/A DCHAR_T tmpbuf[700];
2N/A DCHAR_T *tmp;
2N/A DCHAR_T *pad_ptr;
2N/A DCHAR_T *p;
2N/A
2N/A has_width = 0;
2N/A width = 0;
2N/A if (dp->width_start != dp->width_end)
2N/A {
2N/A if (dp->width_arg_index != ARG_NONE)
2N/A {
2N/A int arg;
2N/A
2N/A if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
2N/A abort ();
2N/A arg = a.arg[dp->width_arg_index].a.a_int;
2N/A if (arg < 0)
2N/A {
2N/A /* "A negative field width is taken as a '-' flag
2N/A followed by a positive field width." */
2N/A flags |= FLAG_LEFT;
2N/A width = (unsigned int) (-arg);
2N/A }
2N/A else
2N/A width = arg;
2N/A }
2N/A else
2N/A {
2N/A const FCHAR_T *digitp = dp->width_start;
2N/A
2N/A do
2N/A width = xsum (xtimes (width, 10), *digitp++ - '0');
2N/A while (digitp != dp->width_end);
2N/A }
2N/A has_width = 1;
2N/A }
2N/A
2N/A has_precision = 0;
2N/A precision = 0;
2N/A if (dp->precision_start != dp->precision_end)
2N/A {
2N/A if (dp->precision_arg_index != ARG_NONE)
2N/A {
2N/A int arg;
2N/A
2N/A if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
2N/A abort ();
2N/A arg = a.arg[dp->precision_arg_index].a.a_int;
2N/A /* "A negative precision is taken as if the precision
2N/A were omitted." */
2N/A if (arg >= 0)
2N/A {
2N/A precision = arg;
2N/A has_precision = 1;
2N/A }
2N/A }
2N/A else
2N/A {
2N/A const FCHAR_T *digitp = dp->precision_start + 1;
2N/A
2N/A precision = 0;
2N/A while (digitp != dp->precision_end)
2N/A precision = xsum (xtimes (precision, 10), *digitp++ - '0');
2N/A has_precision = 1;
2N/A }
2N/A }
2N/A
2N/A /* Allocate a temporary buffer of sufficient size. */
2N/A if (type == TYPE_LONGDOUBLE)
2N/A tmp_length =
2N/A (unsigned int) ((LDBL_DIG + 1)
2N/A * 0.831 /* decimal -> hexadecimal */
2N/A )
2N/A + 1; /* turn floor into ceil */
2N/A else
2N/A tmp_length =
2N/A (unsigned int) ((DBL_DIG + 1)
2N/A * 0.831 /* decimal -> hexadecimal */
2N/A )
2N/A + 1; /* turn floor into ceil */
2N/A if (tmp_length < precision)
2N/A tmp_length = precision;
2N/A /* Account for sign, decimal point etc. */
2N/A tmp_length = xsum (tmp_length, 12);
2N/A
2N/A if (tmp_length < width)
2N/A tmp_length = width;
2N/A
2N/A tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
2N/A
2N/A if (tmp_length <= sizeof (tmpbuf) / sizeof (DCHAR_T))
2N/A tmp = tmpbuf;
2N/A else
2N/A {
2N/A size_t tmp_memsize = xtimes (tmp_length, sizeof (DCHAR_T));
2N/A
2N/A if (size_overflow_p (tmp_memsize))
2N/A /* Overflow, would lead to out of memory. */
2N/A goto out_of_memory;
2N/A tmp = (DCHAR_T *) malloc (tmp_memsize);
2N/A if (tmp == NULL)
2N/A /* Out of memory. */
2N/A goto out_of_memory;
2N/A }
2N/A
2N/A pad_ptr = NULL;
2N/A p = tmp;
2N/A if (type == TYPE_LONGDOUBLE)
2N/A {
2N/A# if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE
2N/A long double arg = a.arg[dp->arg_index].a.a_longdouble;
2N/A
2N/A if (isnanl (arg))
2N/A {
2N/A if (dp->conversion == 'A')
2N/A {
2N/A *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
2N/A }
2N/A else
2N/A {
2N/A *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
2N/A }
2N/A }
2N/A else
2N/A {
2N/A int sign = 0;
2N/A DECL_LONG_DOUBLE_ROUNDING
2N/A
2N/A BEGIN_LONG_DOUBLE_ROUNDING ();
2N/A
2N/A if (signbit (arg)) /* arg < 0.0L or negative zero */
2N/A {
2N/A sign = -1;
2N/A arg = -arg;
2N/A }
2N/A
2N/A if (sign < 0)
2N/A *p++ = '-';
2N/A else if (flags & FLAG_SHOWSIGN)
2N/A *p++ = '+';
2N/A else if (flags & FLAG_SPACE)
2N/A *p++ = ' ';
2N/A
2N/A if (arg > 0.0L && arg + arg == arg)
2N/A {
2N/A if (dp->conversion == 'A')
2N/A {
2N/A *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
2N/A }
2N/A else
2N/A {
2N/A *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
2N/A }
2N/A }
2N/A else
2N/A {
2N/A int exponent;
2N/A long double mantissa;
2N/A
2N/A if (arg > 0.0L)
2N/A mantissa = printf_frexpl (arg, &exponent);
2N/A else
2N/A {
2N/A exponent = 0;
2N/A mantissa = 0.0L;
2N/A }
2N/A
2N/A if (has_precision
2N/A && precision < (unsigned int) ((LDBL_DIG + 1) * 0.831) + 1)
2N/A {
2N/A /* Round the mantissa. */
2N/A long double tail = mantissa;
2N/A size_t q;
2N/A
2N/A for (q = precision; ; q--)
2N/A {
2N/A int digit = (int) tail;
2N/A tail -= digit;
2N/A if (q == 0)
2N/A {
2N/A if (digit & 1 ? tail >= 0.5L : tail > 0.5L)
2N/A tail = 1 - tail;
2N/A else
2N/A tail = - tail;
2N/A break;
2N/A }
2N/A tail *= 16.0L;
2N/A }
2N/A if (tail != 0.0L)
2N/A for (q = precision; q > 0; q--)
2N/A tail *= 0.0625L;
2N/A mantissa += tail;
2N/A }
2N/A
2N/A *p++ = '0';
2N/A *p++ = dp->conversion - 'A' + 'X';
2N/A pad_ptr = p;
2N/A {
2N/A int digit;
2N/A
2N/A digit = (int) mantissa;
2N/A mantissa -= digit;
2N/A *p++ = '0' + digit;
2N/A if ((flags & FLAG_ALT)
2N/A || mantissa > 0.0L || precision > 0)
2N/A {
2N/A *p++ = decimal_point_char ();
2N/A /* This loop terminates because we assume
2N/A that FLT_RADIX is a power of 2. */
2N/A while (mantissa > 0.0L)
2N/A {
2N/A mantissa *= 16.0L;
2N/A digit = (int) mantissa;
2N/A mantissa -= digit;
2N/A *p++ = digit
2N/A + (digit < 10
2N/A ? '0'
2N/A : dp->conversion - 10);
2N/A if (precision > 0)
2N/A precision--;
2N/A }
2N/A while (precision > 0)
2N/A {
2N/A *p++ = '0';
2N/A precision--;
2N/A }
2N/A }
2N/A }
2N/A *p++ = dp->conversion - 'A' + 'P';
2N/A# if WIDE_CHAR_VERSION
2N/A {
2N/A static const wchar_t decimal_format[] =
2N/A { '%', '+', 'd', '\0' };
2N/A SNPRINTF (p, 6 + 1, decimal_format, exponent);
2N/A }
2N/A while (*p != '\0')
2N/A p++;
2N/A# else
2N/A if (sizeof (DCHAR_T) == 1)
2N/A {
2N/A sprintf ((char *) p, "%+d", exponent);
2N/A while (*p != '\0')
2N/A p++;
2N/A }
2N/A else
2N/A {
2N/A char expbuf[6 + 1];
2N/A const char *ep;
2N/A sprintf (expbuf, "%+d", exponent);
2N/A for (ep = expbuf; (*p = *ep) != '\0'; ep++)
2N/A p++;
2N/A }
2N/A# endif
2N/A }
2N/A
2N/A END_LONG_DOUBLE_ROUNDING ();
2N/A }
2N/A# else
2N/A abort ();
2N/A# endif
2N/A }
2N/A else
2N/A {
2N/A# if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE
2N/A double arg = a.arg[dp->arg_index].a.a_double;
2N/A
2N/A if (isnand (arg))
2N/A {
2N/A if (dp->conversion == 'A')
2N/A {
2N/A *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
2N/A }
2N/A else
2N/A {
2N/A *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
2N/A }
2N/A }
2N/A else
2N/A {
2N/A int sign = 0;
2N/A
2N/A if (signbit (arg)) /* arg < 0.0 or negative zero */
2N/A {
2N/A sign = -1;
2N/A arg = -arg;
2N/A }
2N/A
2N/A if (sign < 0)
2N/A *p++ = '-';
2N/A else if (flags & FLAG_SHOWSIGN)
2N/A *p++ = '+';
2N/A else if (flags & FLAG_SPACE)
2N/A *p++ = ' ';
2N/A
2N/A if (arg > 0.0 && arg + arg == arg)
2N/A {
2N/A if (dp->conversion == 'A')
2N/A {
2N/A *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
2N/A }
2N/A else
2N/A {
2N/A *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
2N/A }
2N/A }
2N/A else
2N/A {
2N/A int exponent;
2N/A double mantissa;
2N/A
2N/A if (arg > 0.0)
2N/A mantissa = printf_frexp (arg, &exponent);
2N/A else
2N/A {
2N/A exponent = 0;
2N/A mantissa = 0.0;
2N/A }
2N/A
2N/A if (has_precision
2N/A && precision < (unsigned int) ((DBL_DIG + 1) * 0.831) + 1)
2N/A {
2N/A /* Round the mantissa. */
2N/A double tail = mantissa;
2N/A size_t q;
2N/A
2N/A for (q = precision; ; q--)
2N/A {
2N/A int digit = (int) tail;
2N/A tail -= digit;
2N/A if (q == 0)
2N/A {
2N/A if (digit & 1 ? tail >= 0.5 : tail > 0.5)
2N/A tail = 1 - tail;
2N/A else
2N/A tail = - tail;
2N/A break;
2N/A }
2N/A tail *= 16.0;
2N/A }
2N/A if (tail != 0.0)
2N/A for (q = precision; q > 0; q--)
2N/A tail *= 0.0625;
2N/A mantissa += tail;
2N/A }
2N/A
2N/A *p++ = '0';
2N/A *p++ = dp->conversion - 'A' + 'X';
2N/A pad_ptr = p;
2N/A {
2N/A int digit;
2N/A
2N/A digit = (int) mantissa;
2N/A mantissa -= digit;
2N/A *p++ = '0' + digit;
2N/A if ((flags & FLAG_ALT)
2N/A || mantissa > 0.0 || precision > 0)
2N/A {
2N/A *p++ = decimal_point_char ();
2N/A /* This loop terminates because we assume
2N/A that FLT_RADIX is a power of 2. */
2N/A while (mantissa > 0.0)
2N/A {
2N/A mantissa *= 16.0;
2N/A digit = (int) mantissa;
2N/A mantissa -= digit;
2N/A *p++ = digit
2N/A + (digit < 10
2N/A ? '0'
2N/A : dp->conversion - 10);
2N/A if (precision > 0)
2N/A precision--;
2N/A }
2N/A while (precision > 0)
2N/A {
2N/A *p++ = '0';
2N/A precision--;
2N/A }
2N/A }
2N/A }
2N/A *p++ = dp->conversion - 'A' + 'P';
2N/A# if WIDE_CHAR_VERSION
2N/A {
2N/A static const wchar_t decimal_format[] =
2N/A { '%', '+', 'd', '\0' };
2N/A SNPRINTF (p, 6 + 1, decimal_format, exponent);
2N/A }
2N/A while (*p != '\0')
2N/A p++;
2N/A# else
2N/A if (sizeof (DCHAR_T) == 1)
2N/A {
2N/A sprintf ((char *) p, "%+d", exponent);
2N/A while (*p != '\0')
2N/A p++;
2N/A }
2N/A else
2N/A {
2N/A char expbuf[6 + 1];
2N/A const char *ep;
2N/A sprintf (expbuf, "%+d", exponent);
2N/A for (ep = expbuf; (*p = *ep) != '\0'; ep++)
2N/A p++;
2N/A }
2N/A# endif
2N/A }
2N/A }
2N/A# else
2N/A abort ();
2N/A# endif
2N/A }
2N/A /* The generated string now extends from tmp to p, with the
2N/A zero padding insertion point being at pad_ptr. */
2N/A if (has_width && p - tmp < width)
2N/A {
2N/A size_t pad = width - (p - tmp);
2N/A DCHAR_T *end = p + pad;
2N/A
2N/A if (flags & FLAG_LEFT)
2N/A {
2N/A /* Pad with spaces on the right. */
2N/A for (; pad > 0; pad--)
2N/A *p++ = ' ';
2N/A }
2N/A else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
2N/A {
2N/A /* Pad with zeroes. */
2N/A DCHAR_T *q = end;
2N/A
2N/A while (p > pad_ptr)
2N/A *--q = *--p;
2N/A for (; pad > 0; pad--)
2N/A *p++ = '0';
2N/A }
2N/A else
2N/A {
2N/A /* Pad with spaces on the left. */
2N/A DCHAR_T *q = end;
2N/A
2N/A while (p > tmp)
2N/A *--q = *--p;
2N/A for (; pad > 0; pad--)
2N/A *p++ = ' ';
2N/A }
2N/A
2N/A p = end;
2N/A }
2N/A
2N/A {
2N/A size_t count = p - tmp;
2N/A
2N/A if (count >= tmp_length)
2N/A /* tmp_length was incorrectly calculated - fix the
2N/A code above! */
2N/A abort ();
2N/A
2N/A /* Make room for the result. */
2N/A if (count >= allocated - length)
2N/A {
2N/A size_t n = xsum (length, count);
2N/A
2N/A ENSURE_ALLOCATION (n);
2N/A }
2N/A
2N/A /* Append the result. */
2N/A memcpy (result + length, tmp, count * sizeof (DCHAR_T));
2N/A if (tmp != tmpbuf)
2N/A free (tmp);
2N/A length += count;
2N/A }
2N/A }
2N/A#endif
2N/A#if (NEED_PRINTF_INFINITE_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL
2N/A else if ((dp->conversion == 'f' || dp->conversion == 'F'
2N/A || dp->conversion == 'e' || dp->conversion == 'E'
2N/A || dp->conversion == 'g' || dp->conversion == 'G'
2N/A || dp->conversion == 'a' || dp->conversion == 'A')
2N/A && (0
2N/A# if NEED_PRINTF_DOUBLE
2N/A || a.arg[dp->arg_index].type == TYPE_DOUBLE
2N/A# elif NEED_PRINTF_INFINITE_DOUBLE
2N/A || (a.arg[dp->arg_index].type == TYPE_DOUBLE
2N/A /* The systems (mingw) which produce wrong output
2N/A for Inf, -Inf, and NaN also do so for -0.0.
2N/A Therefore we treat this case here as well. */
2N/A && is_infinite_or_zero (a.arg[dp->arg_index].a.a_double))
2N/A# endif
2N/A# if NEED_PRINTF_LONG_DOUBLE
2N/A || a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
2N/A# elif NEED_PRINTF_INFINITE_LONG_DOUBLE
2N/A || (a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
2N/A /* Some systems produce wrong output for Inf,
2N/A -Inf, and NaN. Some systems in this category
2N/A (IRIX 5.3) also do so for -0.0. Therefore we
2N/A treat this case here as well. */
2N/A && is_infinite_or_zerol (a.arg[dp->arg_index].a.a_longdouble))
2N/A# endif
2N/A ))
2N/A {
2N/A# if (NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE)
2N/A arg_type type = a.arg[dp->arg_index].type;
2N/A# endif
2N/A int flags = dp->flags;
2N/A int has_width;
2N/A size_t width;
2N/A int has_precision;
2N/A size_t precision;
2N/A size_t tmp_length;
2N/A DCHAR_T tmpbuf[700];
2N/A DCHAR_T *tmp;
2N/A DCHAR_T *pad_ptr;
2N/A DCHAR_T *p;
2N/A
2N/A has_width = 0;
2N/A width = 0;
2N/A if (dp->width_start != dp->width_end)
2N/A {
2N/A if (dp->width_arg_index != ARG_NONE)
2N/A {
2N/A int arg;
2N/A
2N/A if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
2N/A abort ();
2N/A arg = a.arg[dp->width_arg_index].a.a_int;
2N/A if (arg < 0)
2N/A {
2N/A /* "A negative field width is taken as a '-' flag
2N/A followed by a positive field width." */
2N/A flags |= FLAG_LEFT;
2N/A width = (unsigned int) (-arg);
2N/A }
2N/A else
2N/A width = arg;
2N/A }
2N/A else
2N/A {
2N/A const FCHAR_T *digitp = dp->width_start;
2N/A
2N/A do
2N/A width = xsum (xtimes (width, 10), *digitp++ - '0');
2N/A while (digitp != dp->width_end);
2N/A }
2N/A has_width = 1;
2N/A }
2N/A
2N/A has_precision = 0;
2N/A precision = 0;
2N/A if (dp->precision_start != dp->precision_end)
2N/A {
2N/A if (dp->precision_arg_index != ARG_NONE)
2N/A {
2N/A int arg;
2N/A
2N/A if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
2N/A abort ();
2N/A arg = a.arg[dp->precision_arg_index].a.a_int;
2N/A /* "A negative precision is taken as if the precision
2N/A were omitted." */
2N/A if (arg >= 0)
2N/A {
2N/A precision = arg;
2N/A has_precision = 1;
2N/A }
2N/A }
2N/A else
2N/A {
2N/A const FCHAR_T *digitp = dp->precision_start + 1;
2N/A
2N/A precision = 0;
2N/A while (digitp != dp->precision_end)
2N/A precision = xsum (xtimes (precision, 10), *digitp++ - '0');
2N/A has_precision = 1;
2N/A }
2N/A }
2N/A
2N/A /* POSIX specifies the default precision to be 6 for %f, %F,
2N/A %e, %E, but not for %g, %G. Implementations appear to use
2N/A the same default precision also for %g, %G. But for %a, %A,
2N/A the default precision is 0. */
2N/A if (!has_precision)
2N/A if (!(dp->conversion == 'a' || dp->conversion == 'A'))
2N/A precision = 6;
2N/A
2N/A /* Allocate a temporary buffer of sufficient size. */
2N/A# if NEED_PRINTF_DOUBLE && NEED_PRINTF_LONG_DOUBLE
2N/A tmp_length = (type == TYPE_LONGDOUBLE ? LDBL_DIG + 1 : DBL_DIG + 1);
2N/A# elif NEED_PRINTF_INFINITE_DOUBLE && NEED_PRINTF_LONG_DOUBLE
2N/A tmp_length = (type == TYPE_LONGDOUBLE ? LDBL_DIG + 1 : 0);
2N/A# elif NEED_PRINTF_LONG_DOUBLE
2N/A tmp_length = LDBL_DIG + 1;
2N/A# elif NEED_PRINTF_DOUBLE
2N/A tmp_length = DBL_DIG + 1;
2N/A# else
2N/A tmp_length = 0;
2N/A# endif
2N/A if (tmp_length < precision)
2N/A tmp_length = precision;
2N/A# if NEED_PRINTF_LONG_DOUBLE
2N/A# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
2N/A if (type == TYPE_LONGDOUBLE)
2N/A# endif
2N/A if (dp->conversion == 'f' || dp->conversion == 'F')
2N/A {
2N/A long double arg = a.arg[dp->arg_index].a.a_longdouble;
2N/A if (!(isnanl (arg) || arg + arg == arg))
2N/A {
2N/A /* arg is finite and nonzero. */
2N/A int exponent = floorlog10l (arg < 0 ? -arg : arg);
2N/A if (exponent >= 0 && tmp_length < exponent + precision)
2N/A tmp_length = exponent + precision;
2N/A }
2N/A }
2N/A# endif
2N/A# if NEED_PRINTF_DOUBLE
2N/A# if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE
2N/A if (type == TYPE_DOUBLE)
2N/A# endif
2N/A if (dp->conversion == 'f' || dp->conversion == 'F')
2N/A {
2N/A double arg = a.arg[dp->arg_index].a.a_double;
2N/A if (!(isnand (arg) || arg + arg == arg))
2N/A {
2N/A /* arg is finite and nonzero. */
2N/A int exponent = floorlog10 (arg < 0 ? -arg : arg);
2N/A if (exponent >= 0 && tmp_length < exponent + precision)
2N/A tmp_length = exponent + precision;
2N/A }
2N/A }
2N/A# endif
2N/A /* Account for sign, decimal point etc. */
2N/A tmp_length = xsum (tmp_length, 12);
2N/A
2N/A if (tmp_length < width)
2N/A tmp_length = width;
2N/A
2N/A tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
2N/A
2N/A if (tmp_length <= sizeof (tmpbuf) / sizeof (DCHAR_T))
2N/A tmp = tmpbuf;
2N/A else
2N/A {
2N/A size_t tmp_memsize = xtimes (tmp_length, sizeof (DCHAR_T));
2N/A
2N/A if (size_overflow_p (tmp_memsize))
2N/A /* Overflow, would lead to out of memory. */
2N/A goto out_of_memory;
2N/A tmp = (DCHAR_T *) malloc (tmp_memsize);
2N/A if (tmp == NULL)
2N/A /* Out of memory. */
2N/A goto out_of_memory;
2N/A }
2N/A
2N/A pad_ptr = NULL;
2N/A p = tmp;
2N/A
2N/A# if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE
2N/A# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
2N/A if (type == TYPE_LONGDOUBLE)
2N/A# endif
2N/A {
2N/A long double arg = a.arg[dp->arg_index].a.a_longdouble;
2N/A
2N/A if (isnanl (arg))
2N/A {
2N/A if (dp->conversion >= 'A' && dp->conversion <= 'Z')
2N/A {
2N/A *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
2N/A }
2N/A else
2N/A {
2N/A *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
2N/A }
2N/A }
2N/A else
2N/A {
2N/A int sign = 0;
2N/A DECL_LONG_DOUBLE_ROUNDING
2N/A
2N/A BEGIN_LONG_DOUBLE_ROUNDING ();
2N/A
2N/A if (signbit (arg)) /* arg < 0.0L or negative zero */
2N/A {
2N/A sign = -1;
2N/A arg = -arg;
2N/A }
2N/A
2N/A if (sign < 0)
2N/A *p++ = '-';
2N/A else if (flags & FLAG_SHOWSIGN)
2N/A *p++ = '+';
2N/A else if (flags & FLAG_SPACE)
2N/A *p++ = ' ';
2N/A
2N/A if (arg > 0.0L && arg + arg == arg)
2N/A {
2N/A if (dp->conversion >= 'A' && dp->conversion <= 'Z')
2N/A {
2N/A *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
2N/A }
2N/A else
2N/A {
2N/A *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
2N/A }
2N/A }
2N/A else
2N/A {
2N/A# if NEED_PRINTF_LONG_DOUBLE
2N/A pad_ptr = p;
2N/A
2N/A if (dp->conversion == 'f' || dp->conversion == 'F')
2N/A {
2N/A char *digits;
2N/A size_t ndigits;
2N/A
2N/A digits =
2N/A scale10_round_decimal_long_double (arg, precision);
2N/A if (digits == NULL)
2N/A {
2N/A END_LONG_DOUBLE_ROUNDING ();
2N/A goto out_of_memory;
2N/A }
2N/A ndigits = strlen (digits);
2N/A
2N/A if (ndigits > precision)
2N/A do
2N/A {
2N/A --ndigits;
2N/A *p++ = digits[ndigits];
2N/A }
2N/A while (ndigits > precision);
2N/A else
2N/A *p++ = '0';
2N/A /* Here ndigits <= precision. */
2N/A if ((flags & FLAG_ALT) || precision > 0)
2N/A {
2N/A *p++ = decimal_point_char ();
2N/A for (; precision > ndigits; precision--)
2N/A *p++ = '0';
2N/A while (ndigits > 0)
2N/A {
2N/A --ndigits;
2N/A *p++ = digits[ndigits];
2N/A }
2N/A }
2N/A
2N/A free (digits);
2N/A }
2N/A else if (dp->conversion == 'e' || dp->conversion == 'E')
2N/A {
2N/A int exponent;
2N/A
2N/A if (arg == 0.0L)
2N/A {
2N/A exponent = 0;
2N/A *p++ = '0';
2N/A if ((flags & FLAG_ALT) || precision > 0)
2N/A {
2N/A *p++ = decimal_point_char ();
2N/A for (; precision > 0; precision--)
2N/A *p++ = '0';
2N/A }
2N/A }
2N/A else
2N/A {
2N/A /* arg > 0.0L. */
2N/A int adjusted;
2N/A char *digits;
2N/A size_t ndigits;
2N/A
2N/A exponent = floorlog10l (arg);
2N/A adjusted = 0;
2N/A for (;;)
2N/A {
2N/A digits =
2N/A scale10_round_decimal_long_double (arg,
2N/A (int)precision - exponent);
2N/A if (digits == NULL)
2N/A {
2N/A END_LONG_DOUBLE_ROUNDING ();
2N/A goto out_of_memory;
2N/A }
2N/A ndigits = strlen (digits);
2N/A
2N/A if (ndigits == precision + 1)
2N/A break;
2N/A if (ndigits < precision
2N/A || ndigits > precision + 2)
2N/A /* The exponent was not guessed
2N/A precisely enough. */
2N/A abort ();
2N/A if (adjusted)
2N/A /* None of two values of exponent is
2N/A the right one. Prevent an endless
2N/A loop. */
2N/A abort ();
2N/A free (digits);
2N/A if (ndigits == precision)
2N/A exponent -= 1;
2N/A else
2N/A exponent += 1;
2N/A adjusted = 1;
2N/A }
2N/A /* Here ndigits = precision+1. */
2N/A if (is_borderline (digits, precision))
2N/A {
2N/A /* Maybe the exponent guess was too high
2N/A and a smaller exponent can be reached
2N/A by turning a 10...0 into 9...9x. */
2N/A char *digits2 =
2N/A scale10_round_decimal_long_double (arg,
2N/A (int)precision - exponent + 1);
2N/A if (digits2 == NULL)
2N/A {
2N/A free (digits);
2N/A END_LONG_DOUBLE_ROUNDING ();
2N/A goto out_of_memory;
2N/A }
2N/A if (strlen (digits2) == precision + 1)
2N/A {
2N/A free (digits);
2N/A digits = digits2;
2N/A exponent -= 1;
2N/A }
2N/A else
2N/A free (digits2);
2N/A }
2N/A /* Here ndigits = precision+1. */
2N/A
2N/A *p++ = digits[--ndigits];
2N/A if ((flags & FLAG_ALT) || precision > 0)
2N/A {
2N/A *p++ = decimal_point_char ();
2N/A while (ndigits > 0)
2N/A {
2N/A --ndigits;
2N/A *p++ = digits[ndigits];
2N/A }
2N/A }
2N/A
2N/A free (digits);
2N/A }
2N/A
2N/A *p++ = dp->conversion; /* 'e' or 'E' */
2N/A# if WIDE_CHAR_VERSION
2N/A {
2N/A static const wchar_t decimal_format[] =
2N/A { '%', '+', '.', '2', 'd', '\0' };
2N/A SNPRINTF (p, 6 + 1, decimal_format, exponent);
2N/A }
2N/A while (*p != '\0')
2N/A p++;
2N/A# else
2N/A if (sizeof (DCHAR_T) == 1)
2N/A {
2N/A sprintf ((char *) p, "%+.2d", exponent);
2N/A while (*p != '\0')
2N/A p++;
2N/A }
2N/A else
2N/A {
2N/A char expbuf[6 + 1];
2N/A const char *ep;
2N/A sprintf (expbuf, "%+.2d", exponent);
2N/A for (ep = expbuf; (*p = *ep) != '\0'; ep++)
2N/A p++;
2N/A }
2N/A# endif
2N/A }
2N/A else if (dp->conversion == 'g' || dp->conversion == 'G')
2N/A {
2N/A if (precision == 0)
2N/A precision = 1;
2N/A /* precision >= 1. */
2N/A
2N/A if (arg == 0.0L)
2N/A /* The exponent is 0, >= -4, < precision.
2N/A Use fixed-point notation. */
2N/A {
2N/A size_t ndigits = precision;
2N/A /* Number of trailing zeroes that have to be
2N/A dropped. */
2N/A size_t nzeroes =
2N/A (flags & FLAG_ALT ? 0 : precision - 1);
2N/A
2N/A --ndigits;
2N/A *p++ = '0';
2N/A if ((flags & FLAG_ALT) || ndigits > nzeroes)
2N/A {
2N/A *p++ = decimal_point_char ();
2N/A while (ndigits > nzeroes)
2N/A {
2N/A --ndigits;
2N/A *p++ = '0';
2N/A }
2N/A }
2N/A }
2N/A else
2N/A {
2N/A /* arg > 0.0L. */
2N/A int exponent;
2N/A int adjusted;
2N/A char *digits;
2N/A size_t ndigits;
2N/A size_t nzeroes;
2N/A
2N/A exponent = floorlog10l (arg);
2N/A adjusted = 0;
2N/A for (;;)
2N/A {
2N/A digits =
2N/A scale10_round_decimal_long_double (arg,
2N/A (int)(precision - 1) - exponent);
2N/A if (digits == NULL)
2N/A {
2N/A END_LONG_DOUBLE_ROUNDING ();
2N/A goto out_of_memory;
2N/A }
2N/A ndigits = strlen (digits);
2N/A
2N/A if (ndigits == precision)
2N/A break;
2N/A if (ndigits < precision - 1
2N/A || ndigits > precision + 1)
2N/A /* The exponent was not guessed
2N/A precisely enough. */
2N/A abort ();
2N/A if (adjusted)
2N/A /* None of two values of exponent is
2N/A the right one. Prevent an endless
2N/A loop. */
2N/A abort ();
2N/A free (digits);
2N/A if (ndigits < precision)
2N/A exponent -= 1;
2N/A else
2N/A exponent += 1;
2N/A adjusted = 1;
2N/A }
2N/A /* Here ndigits = precision. */
2N/A if (is_borderline (digits, precision - 1))
2N/A {
2N/A /* Maybe the exponent guess was too high
2N/A and a smaller exponent can be reached
2N/A by turning a 10...0 into 9...9x. */
2N/A char *digits2 =
2N/A scale10_round_decimal_long_double (arg,
2N/A (int)(precision - 1) - exponent + 1);
2N/A if (digits2 == NULL)
2N/A {
2N/A free (digits);
2N/A END_LONG_DOUBLE_ROUNDING ();
2N/A goto out_of_memory;
2N/A }
2N/A if (strlen (digits2) == precision)
2N/A {
2N/A free (digits);
2N/A digits = digits2;
2N/A exponent -= 1;
2N/A }
2N/A else
2N/A free (digits2);
2N/A }
2N/A /* Here ndigits = precision. */
2N/A
2N/A /* Determine the number of trailing zeroes
2N/A that have to be dropped. */
2N/A nzeroes = 0;
2N/A if ((flags & FLAG_ALT) == 0)
2N/A while (nzeroes < ndigits
2N/A && digits[nzeroes] == '0')
2N/A nzeroes++;
2N/A
2N/A /* The exponent is now determined. */
2N/A if (exponent >= -4
2N/A && exponent < (long)precision)
2N/A {
2N/A /* Fixed-point notation:
2N/A max(exponent,0)+1 digits, then the
2N/A decimal point, then the remaining
2N/A digits without trailing zeroes. */
2N/A if (exponent >= 0)
2N/A {
2N/A size_t count = exponent + 1;
2N/A /* Note: count <= precision = ndigits. */
2N/A for (; count > 0; count--)
2N/A *p++ = digits[--ndigits];
2N/A if ((flags & FLAG_ALT) || ndigits > nzeroes)
2N/A {
2N/A *p++ = decimal_point_char ();
2N/A while (ndigits > nzeroes)
2N/A {
2N/A --ndigits;
2N/A *p++ = digits[ndigits];
2N/A }
2N/A }
2N/A }
2N/A else
2N/A {
2N/A size_t count = -exponent - 1;
2N/A *p++ = '0';
2N/A *p++ = decimal_point_char ();
2N/A for (; count > 0; count--)
2N/A *p++ = '0';
2N/A while (ndigits > nzeroes)
2N/A {
2N/A --ndigits;
2N/A *p++ = digits[ndigits];
2N/A }
2N/A }
2N/A }
2N/A else
2N/A {
2N/A /* Exponential notation. */
2N/A *p++ = digits[--ndigits];
2N/A if ((flags & FLAG_ALT) || ndigits > nzeroes)
2N/A {
2N/A *p++ = decimal_point_char ();
2N/A while (ndigits > nzeroes)
2N/A {
2N/A --ndigits;
2N/A *p++ = digits[ndigits];
2N/A }
2N/A }
2N/A *p++ = dp->conversion - 'G' + 'E'; /* 'e' or 'E' */
2N/A# if WIDE_CHAR_VERSION
2N/A {
2N/A static const wchar_t decimal_format[] =
2N/A { '%', '+', '.', '2', 'd', '\0' };
2N/A SNPRINTF (p, 6 + 1, decimal_format, exponent);
2N/A }
2N/A while (*p != '\0')
2N/A p++;
2N/A# else
2N/A if (sizeof (DCHAR_T) == 1)
2N/A {
2N/A sprintf ((char *) p, "%+.2d", exponent);
2N/A while (*p != '\0')
2N/A p++;
2N/A }
2N/A else
2N/A {
2N/A char expbuf[6 + 1];
2N/A const char *ep;
2N/A sprintf (expbuf, "%+.2d", exponent);
2N/A for (ep = expbuf; (*p = *ep) != '\0'; ep++)
2N/A p++;
2N/A }
2N/A# endif
2N/A }
2N/A
2N/A free (digits);
2N/A }
2N/A }
2N/A else
2N/A abort ();
2N/A# else
2N/A /* arg is finite. */
2N/A if (!(arg == 0.0L))
2N/A abort ();
2N/A
2N/A pad_ptr = p;
2N/A
2N/A if (dp->conversion == 'f' || dp->conversion == 'F')
2N/A {
2N/A *p++ = '0';
2N/A if ((flags & FLAG_ALT) || precision > 0)
2N/A {
2N/A *p++ = decimal_point_char ();
2N/A for (; precision > 0; precision--)
2N/A *p++ = '0';
2N/A }
2N/A }
2N/A else if (dp->conversion == 'e' || dp->conversion == 'E')
2N/A {
2N/A *p++ = '0';
2N/A if ((flags & FLAG_ALT) || precision > 0)
2N/A {
2N/A *p++ = decimal_point_char ();
2N/A for (; precision > 0; precision--)
2N/A *p++ = '0';
2N/A }
2N/A *p++ = dp->conversion; /* 'e' or 'E' */
2N/A *p++ = '+';
2N/A *p++ = '0';
2N/A *p++ = '0';
2N/A }
2N/A else if (dp->conversion == 'g' || dp->conversion == 'G')
2N/A {
2N/A *p++ = '0';
2N/A if (flags & FLAG_ALT)
2N/A {
2N/A size_t ndigits =
2N/A (precision > 0 ? precision - 1 : 0);
2N/A *p++ = decimal_point_char ();
2N/A for (; ndigits > 0; --ndigits)
2N/A *p++ = '0';
2N/A }
2N/A }
2N/A else if (dp->conversion == 'a' || dp->conversion == 'A')
2N/A {
2N/A *p++ = '0';
2N/A *p++ = dp->conversion - 'A' + 'X';
2N/A pad_ptr = p;
2N/A *p++ = '0';
2N/A if ((flags & FLAG_ALT) || precision > 0)
2N/A {
2N/A *p++ = decimal_point_char ();
2N/A for (; precision > 0; precision--)
2N/A *p++ = '0';
2N/A }
2N/A *p++ = dp->conversion - 'A' + 'P';
2N/A *p++ = '+';
2N/A *p++ = '0';
2N/A }
2N/A else
2N/A abort ();
2N/A# endif
2N/A }
2N/A
2N/A END_LONG_DOUBLE_ROUNDING ();
2N/A }
2N/A }
2N/A# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
2N/A else
2N/A# endif
2N/A# endif
2N/A# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
2N/A {
2N/A double arg = a.arg[dp->arg_index].a.a_double;
2N/A
2N/A if (isnand (arg))
2N/A {
2N/A if (dp->conversion >= 'A' && dp->conversion <= 'Z')
2N/A {
2N/A *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
2N/A }
2N/A else
2N/A {
2N/A *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
2N/A }
2N/A }
2N/A else
2N/A {
2N/A int sign = 0;
2N/A
2N/A if (signbit (arg)) /* arg < 0.0 or negative zero */
2N/A {
2N/A sign = -1;
2N/A arg = -arg;
2N/A }
2N/A
2N/A if (sign < 0)
2N/A *p++ = '-';
2N/A else if (flags & FLAG_SHOWSIGN)
2N/A *p++ = '+';
2N/A else if (flags & FLAG_SPACE)
2N/A *p++ = ' ';
2N/A
2N/A if (arg > 0.0 && arg + arg == arg)
2N/A {
2N/A if (dp->conversion >= 'A' && dp->conversion <= 'Z')
2N/A {
2N/A *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
2N/A }
2N/A else
2N/A {
2N/A *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
2N/A }
2N/A }
2N/A else
2N/A {
2N/A# if NEED_PRINTF_DOUBLE
2N/A pad_ptr = p;
2N/A
2N/A if (dp->conversion == 'f' || dp->conversion == 'F')
2N/A {
2N/A char *digits;
2N/A size_t ndigits;
2N/A
2N/A digits =
2N/A scale10_round_decimal_double (arg, precision);
2N/A if (digits == NULL)
2N/A goto out_of_memory;
2N/A ndigits = strlen (digits);
2N/A
2N/A if (ndigits > precision)
2N/A do
2N/A {
2N/A --ndigits;
2N/A *p++ = digits[ndigits];
2N/A }
2N/A while (ndigits > precision);
2N/A else
2N/A *p++ = '0';
2N/A /* Here ndigits <= precision. */
2N/A if ((flags & FLAG_ALT) || precision > 0)
2N/A {
2N/A *p++ = decimal_point_char ();
2N/A for (; precision > ndigits; precision--)
2N/A *p++ = '0';
2N/A while (ndigits > 0)
2N/A {
2N/A --ndigits;
2N/A *p++ = digits[ndigits];
2N/A }
2N/A }
2N/A
2N/A free (digits);
2N/A }
2N/A else if (dp->conversion == 'e' || dp->conversion == 'E')
2N/A {
2N/A int exponent;
2N/A
2N/A if (arg == 0.0)
2N/A {
2N/A exponent = 0;
2N/A *p++ = '0';
2N/A if ((flags & FLAG_ALT) || precision > 0)
2N/A {
2N/A *p++ = decimal_point_char ();
2N/A for (; precision > 0; precision--)
2N/A *p++ = '0';
2N/A }
2N/A }
2N/A else
2N/A {
2N/A /* arg > 0.0. */
2N/A int adjusted;
2N/A char *digits;
2N/A size_t ndigits;
2N/A
2N/A exponent = floorlog10 (arg);
2N/A adjusted = 0;
2N/A for (;;)
2N/A {
2N/A digits =
2N/A scale10_round_decimal_double (arg,
2N/A (int)precision - exponent);
2N/A if (digits == NULL)
2N/A goto out_of_memory;
2N/A ndigits = strlen (digits);
2N/A
2N/A if (ndigits == precision + 1)
2N/A break;
2N/A if (ndigits < precision
2N/A || ndigits > precision + 2)
2N/A /* The exponent was not guessed
2N/A precisely enough. */
2N/A abort ();
2N/A if (adjusted)
2N/A /* None of two values of exponent is
2N/A the right one. Prevent an endless
2N/A loop. */
2N/A abort ();
2N/A free (digits);
2N/A if (ndigits == precision)
2N/A exponent -= 1;
2N/A else
2N/A exponent += 1;
2N/A adjusted = 1;
2N/A }
2N/A /* Here ndigits = precision+1. */
2N/A if (is_borderline (digits, precision))
2N/A {
2N/A /* Maybe the exponent guess was too high
2N/A and a smaller exponent can be reached
2N/A by turning a 10...0 into 9...9x. */
2N/A char *digits2 =
2N/A scale10_round_decimal_double (arg,
2N/A (int)precision - exponent + 1);
2N/A if (digits2 == NULL)
2N/A {
2N/A free (digits);
2N/A goto out_of_memory;
2N/A }
2N/A if (strlen (digits2) == precision + 1)
2N/A {
2N/A free (digits);
2N/A digits = digits2;
2N/A exponent -= 1;
2N/A }
2N/A else
2N/A free (digits2);
2N/A }
2N/A /* Here ndigits = precision+1. */
2N/A
2N/A *p++ = digits[--ndigits];
2N/A if ((flags & FLAG_ALT) || precision > 0)
2N/A {
2N/A *p++ = decimal_point_char ();
2N/A while (ndigits > 0)
2N/A {
2N/A --ndigits;
2N/A *p++ = digits[ndigits];
2N/A }
2N/A }
2N/A
2N/A free (digits);
2N/A }
2N/A
2N/A *p++ = dp->conversion; /* 'e' or 'E' */
2N/A# if WIDE_CHAR_VERSION
2N/A {
2N/A static const wchar_t decimal_format[] =
2N/A /* Produce the same number of exponent digits
2N/A as the native printf implementation. */
2N/A# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
2N/A { '%', '+', '.', '3', 'd', '\0' };
2N/A# else
2N/A { '%', '+', '.', '2', 'd', '\0' };
2N/A# endif
2N/A SNPRINTF (p, 6 + 1, decimal_format, exponent);
2N/A }
2N/A while (*p != '\0')
2N/A p++;
2N/A# else
2N/A {
2N/A static const char decimal_format[] =
2N/A /* Produce the same number of exponent digits
2N/A as the native printf implementation. */
2N/A# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
2N/A "%+.3d";
2N/A# else
2N/A "%+.2d";
2N/A# endif
2N/A if (sizeof (DCHAR_T) == 1)
2N/A {
2N/A sprintf ((char *) p, decimal_format, exponent);
2N/A while (*p != '\0')
2N/A p++;
2N/A }
2N/A else
2N/A {
2N/A char expbuf[6 + 1];
2N/A const char *ep;
2N/A sprintf (expbuf, decimal_format, exponent);
2N/A for (ep = expbuf; (*p = *ep) != '\0'; ep++)
2N/A p++;
2N/A }
2N/A }
2N/A# endif
2N/A }
2N/A else if (dp->conversion == 'g' || dp->conversion == 'G')
2N/A {
2N/A if (precision == 0)
2N/A precision = 1;
2N/A /* precision >= 1. */
2N/A
2N/A if (arg == 0.0)
2N/A /* The exponent is 0, >= -4, < precision.
2N/A Use fixed-point notation. */
2N/A {
2N/A size_t ndigits = precision;
2N/A /* Number of trailing zeroes that have to be
2N/A dropped. */
2N/A size_t nzeroes =
2N/A (flags & FLAG_ALT ? 0 : precision - 1);
2N/A
2N/A --ndigits;
2N/A *p++ = '0';
2N/A if ((flags & FLAG_ALT) || ndigits > nzeroes)
2N/A {
2N/A *p++ = decimal_point_char ();
2N/A while (ndigits > nzeroes)
2N/A {
2N/A --ndigits;
2N/A *p++ = '0';
2N/A }
2N/A }
2N/A }
2N/A else
2N/A {
2N/A /* arg > 0.0. */
2N/A int exponent;
2N/A int adjusted;
2N/A char *digits;
2N/A size_t ndigits;
2N/A size_t nzeroes;
2N/A
2N/A exponent = floorlog10 (arg);
2N/A adjusted = 0;
2N/A for (;;)
2N/A {
2N/A digits =
2N/A scale10_round_decimal_double (arg,
2N/A (int)(precision - 1) - exponent);
2N/A if (digits == NULL)
2N/A goto out_of_memory;
2N/A ndigits = strlen (digits);
2N/A
2N/A if (ndigits == precision)
2N/A break;
2N/A if (ndigits < precision - 1
2N/A || ndigits > precision + 1)
2N/A /* The exponent was not guessed
2N/A precisely enough. */
2N/A abort ();
2N/A if (adjusted)
2N/A /* None of two values of exponent is
2N/A the right one. Prevent an endless
2N/A loop. */
2N/A abort ();
2N/A free (digits);
2N/A if (ndigits < precision)
2N/A exponent -= 1;
2N/A else
2N/A exponent += 1;
2N/A adjusted = 1;
2N/A }
2N/A /* Here ndigits = precision. */
2N/A if (is_borderline (digits, precision - 1))
2N/A {
2N/A /* Maybe the exponent guess was too high
2N/A and a smaller exponent can be reached
2N/A by turning a 10...0 into 9...9x. */
2N/A char *digits2 =
2N/A scale10_round_decimal_double (arg,
2N/A (int)(precision - 1) - exponent + 1);
2N/A if (digits2 == NULL)
2N/A {
2N/A free (digits);
2N/A goto out_of_memory;
2N/A }
2N/A if (strlen (digits2) == precision)
2N/A {
2N/A free (digits);
2N/A digits = digits2;
2N/A exponent -= 1;
2N/A }
2N/A else
2N/A free (digits2);
2N/A }
2N/A /* Here ndigits = precision. */
2N/A
2N/A /* Determine the number of trailing zeroes
2N/A that have to be dropped. */
2N/A nzeroes = 0;
2N/A if ((flags & FLAG_ALT) == 0)
2N/A while (nzeroes < ndigits
2N/A && digits[nzeroes] == '0')
2N/A nzeroes++;
2N/A
2N/A /* The exponent is now determined. */
2N/A if (exponent >= -4
2N/A && exponent < (long)precision)
2N/A {
2N/A /* Fixed-point notation:
2N/A max(exponent,0)+1 digits, then the
2N/A decimal point, then the remaining
2N/A digits without trailing zeroes. */
2N/A if (exponent >= 0)
2N/A {
2N/A size_t count = exponent + 1;
2N/A /* Note: count <= precision = ndigits. */
2N/A for (; count > 0; count--)
2N/A *p++ = digits[--ndigits];
2N/A if ((flags & FLAG_ALT) || ndigits > nzeroes)
2N/A {
2N/A *p++ = decimal_point_char ();
2N/A while (ndigits > nzeroes)
2N/A {
2N/A --ndigits;
2N/A *p++ = digits[ndigits];
2N/A }
2N/A }
2N/A }
2N/A else
2N/A {
2N/A size_t count = -exponent - 1;
2N/A *p++ = '0';
2N/A *p++ = decimal_point_char ();
2N/A for (; count > 0; count--)
2N/A *p++ = '0';
2N/A while (ndigits > nzeroes)
2N/A {
2N/A --ndigits;
2N/A *p++ = digits[ndigits];
2N/A }
2N/A }
2N/A }
2N/A else
2N/A {
2N/A /* Exponential notation. */
2N/A *p++ = digits[--ndigits];
2N/A if ((flags & FLAG_ALT) || ndigits > nzeroes)
2N/A {
2N/A *p++ = decimal_point_char ();
2N/A while (ndigits > nzeroes)
2N/A {
2N/A --ndigits;
2N/A *p++ = digits[ndigits];
2N/A }
2N/A }
2N/A *p++ = dp->conversion - 'G' + 'E'; /* 'e' or 'E' */
2N/A# if WIDE_CHAR_VERSION
2N/A {
2N/A static const wchar_t decimal_format[] =
2N/A /* Produce the same number of exponent digits
2N/A as the native printf implementation. */
2N/A# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
2N/A { '%', '+', '.', '3', 'd', '\0' };
2N/A# else
2N/A { '%', '+', '.', '2', 'd', '\0' };
2N/A# endif
2N/A SNPRINTF (p, 6 + 1, decimal_format, exponent);
2N/A }
2N/A while (*p != '\0')
2N/A p++;
2N/A# else
2N/A {
2N/A static const char decimal_format[] =
2N/A /* Produce the same number of exponent digits
2N/A as the native printf implementation. */
2N/A# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
2N/A "%+.3d";
2N/A# else
2N/A "%+.2d";
2N/A# endif
2N/A if (sizeof (DCHAR_T) == 1)
2N/A {
2N/A sprintf ((char *) p, decimal_format, exponent);
2N/A while (*p != '\0')
2N/A p++;
2N/A }
2N/A else
2N/A {
2N/A char expbuf[6 + 1];
2N/A const char *ep;
2N/A sprintf (expbuf, decimal_format, exponent);
2N/A for (ep = expbuf; (*p = *ep) != '\0'; ep++)
2N/A p++;
2N/A }
2N/A }
2N/A# endif
2N/A }
2N/A
2N/A free (digits);
2N/A }
2N/A }
2N/A else
2N/A abort ();
2N/A# else
2N/A /* arg is finite. */
2N/A if (!(arg == 0.0))
2N/A abort ();
2N/A
2N/A pad_ptr = p;
2N/A
2N/A if (dp->conversion == 'f' || dp->conversion == 'F')
2N/A {
2N/A *p++ = '0';
2N/A if ((flags & FLAG_ALT) || precision > 0)
2N/A {
2N/A *p++ = decimal_point_char ();
2N/A for (; precision > 0; precision--)
2N/A *p++ = '0';
2N/A }
2N/A }
2N/A else if (dp->conversion == 'e' || dp->conversion == 'E')
2N/A {
2N/A *p++ = '0';
2N/A if ((flags & FLAG_ALT) || precision > 0)
2N/A {
2N/A *p++ = decimal_point_char ();
2N/A for (; precision > 0; precision--)
2N/A *p++ = '0';
2N/A }
2N/A *p++ = dp->conversion; /* 'e' or 'E' */
2N/A *p++ = '+';
2N/A /* Produce the same number of exponent digits as
2N/A the native printf implementation. */
2N/A# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
2N/A *p++ = '0';
2N/A# endif
2N/A *p++ = '0';
2N/A *p++ = '0';
2N/A }
2N/A else if (dp->conversion == 'g' || dp->conversion == 'G')
2N/A {
2N/A *p++ = '0';
2N/A if (flags & FLAG_ALT)
2N/A {
2N/A size_t ndigits =
2N/A (precision > 0 ? precision - 1 : 0);
2N/A *p++ = decimal_point_char ();
2N/A for (; ndigits > 0; --ndigits)
2N/A *p++ = '0';
2N/A }
2N/A }
2N/A else
2N/A abort ();
2N/A# endif
2N/A }
2N/A }
2N/A }
2N/A# endif
2N/A
2N/A /* The generated string now extends from tmp to p, with the
2N/A zero padding insertion point being at pad_ptr. */
2N/A if (has_width && p - tmp < width)
2N/A {
2N/A size_t pad = width - (p - tmp);
2N/A DCHAR_T *end = p + pad;
2N/A
2N/A if (flags & FLAG_LEFT)
2N/A {
2N/A /* Pad with spaces on the right. */
2N/A for (; pad > 0; pad--)
2N/A *p++ = ' ';
2N/A }
2N/A else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
2N/A {
2N/A /* Pad with zeroes. */
2N/A DCHAR_T *q = end;
2N/A
2N/A while (p > pad_ptr)
2N/A *--q = *--p;
2N/A for (; pad > 0; pad--)
2N/A *p++ = '0';
2N/A }
2N/A else
2N/A {
2N/A /* Pad with spaces on the left. */
2N/A DCHAR_T *q = end;
2N/A
2N/A while (p > tmp)
2N/A *--q = *--p;
2N/A for (; pad > 0; pad--)
2N/A *p++ = ' ';
2N/A }
2N/A
2N/A p = end;
2N/A }
2N/A
2N/A {
2N/A size_t count = p - tmp;
2N/A
2N/A if (count >= tmp_length)
2N/A /* tmp_length was incorrectly calculated - fix the
2N/A code above! */
2N/A abort ();
2N/A
2N/A /* Make room for the result. */
2N/A if (count >= allocated - length)
2N/A {
2N/A size_t n = xsum (length, count);
2N/A
2N/A ENSURE_ALLOCATION (n);
2N/A }
2N/A
2N/A /* Append the result. */
2N/A memcpy (result + length, tmp, count * sizeof (DCHAR_T));
2N/A if (tmp != tmpbuf)
2N/A free (tmp);
2N/A length += count;
2N/A }
2N/A }
2N/A#endif
2N/A else
2N/A {
2N/A arg_type type = a.arg[dp->arg_index].type;
2N/A int flags = dp->flags;
2N/A#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
2N/A int has_width;
2N/A size_t width;
2N/A#endif
2N/A#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || NEED_PRINTF_UNBOUNDED_PRECISION
2N/A int has_precision;
2N/A size_t precision;
2N/A#endif
2N/A#if NEED_PRINTF_UNBOUNDED_PRECISION
2N/A int prec_ourselves;
2N/A#else
2N/A# define prec_ourselves 0
2N/A#endif
2N/A#if NEED_PRINTF_FLAG_LEFTADJUST
2N/A# define pad_ourselves 1
2N/A#elif !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
2N/A int pad_ourselves;
2N/A#else
2N/A# define pad_ourselves 0
2N/A#endif
2N/A TCHAR_T *fbp;
2N/A unsigned int prefix_count;
2N/A int prefixes[2] IF_LINT (= { 0 });
2N/A#if !USE_SNPRINTF
2N/A size_t tmp_length;
2N/A TCHAR_T tmpbuf[700];
2N/A TCHAR_T *tmp;
2N/A#endif
2N/A
2N/A#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
2N/A has_width = 0;
2N/A width = 0;
2N/A if (dp->width_start != dp->width_end)
2N/A {
2N/A if (dp->width_arg_index != ARG_NONE)
2N/A {
2N/A int arg;
2N/A
2N/A if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
2N/A abort ();
2N/A arg = a.arg[dp->width_arg_index].a.a_int;
2N/A if (arg < 0)
2N/A {
2N/A /* "A negative field width is taken as a '-' flag
2N/A followed by a positive field width." */
2N/A flags |= FLAG_LEFT;
2N/A width = (unsigned int) (-arg);
2N/A }
2N/A else
2N/A width = arg;
2N/A }
2N/A else
2N/A {
2N/A const FCHAR_T *digitp = dp->width_start;
2N/A
2N/A do
2N/A width = xsum (xtimes (width, 10), *digitp++ - '0');
2N/A while (digitp != dp->width_end);
2N/A }
2N/A has_width = 1;
2N/A }
2N/A#endif
2N/A
2N/A#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || NEED_PRINTF_UNBOUNDED_PRECISION
2N/A has_precision = 0;
2N/A precision = 6;
2N/A if (dp->precision_start != dp->precision_end)
2N/A {
2N/A if (dp->precision_arg_index != ARG_NONE)
2N/A {
2N/A int arg;
2N/A
2N/A if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
2N/A abort ();
2N/A arg = a.arg[dp->precision_arg_index].a.a_int;
2N/A /* "A negative precision is taken as if the precision
2N/A were omitted." */
2N/A if (arg >= 0)
2N/A {
2N/A precision = arg;
2N/A has_precision = 1;
2N/A }
2N/A }
2N/A else
2N/A {
2N/A const FCHAR_T *digitp = dp->precision_start + 1;
2N/A
2N/A precision = 0;
2N/A while (digitp != dp->precision_end)
2N/A precision = xsum (xtimes (precision, 10), *digitp++ - '0');
2N/A has_precision = 1;
2N/A }
2N/A }
2N/A#endif
2N/A
2N/A /* Decide whether to handle the precision ourselves. */
2N/A#if NEED_PRINTF_UNBOUNDED_PRECISION
2N/A switch (dp->conversion)
2N/A {
2N/A case 'd': case 'i': case 'u':
2N/A case 'o':
2N/A case 'x': case 'X': case 'p':
2N/A prec_ourselves = has_precision && (precision > 0);
2N/A break;
2N/A default:
2N/A prec_ourselves = 0;
2N/A break;
2N/A }
2N/A#endif
2N/A
2N/A /* Decide whether to perform the padding ourselves. */
2N/A#if !NEED_PRINTF_FLAG_LEFTADJUST && (!DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION)
2N/A switch (dp->conversion)
2N/A {
2N/A# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO
2N/A /* If we need conversion from TCHAR_T[] to DCHAR_T[], we need
2N/A to perform the padding after this conversion. Functions
2N/A with unistdio extensions perform the padding based on
2N/A character count rather than element count. */
2N/A case 'c': case 's':
2N/A# endif
2N/A# if NEED_PRINTF_FLAG_ZERO
2N/A case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
2N/A case 'a': case 'A':
2N/A# endif
2N/A pad_ourselves = 1;
2N/A break;
2N/A default:
2N/A pad_ourselves = prec_ourselves;
2N/A break;
2N/A }
2N/A#endif
2N/A
2N/A#if !USE_SNPRINTF
2N/A /* Allocate a temporary buffer of sufficient size for calling
2N/A sprintf. */
2N/A tmp_length =
2N/A MAX_ROOM_NEEDED (&a, dp->arg_index, dp->conversion, type,
2N/A flags, width, has_precision, precision,
2N/A pad_ourselves);
2N/A
2N/A if (tmp_length <= sizeof (tmpbuf) / sizeof (TCHAR_T))
2N/A tmp = tmpbuf;
2N/A else
2N/A {
2N/A size_t tmp_memsize = xtimes (tmp_length, sizeof (TCHAR_T));
2N/A
2N/A if (size_overflow_p (tmp_memsize))
2N/A /* Overflow, would lead to out of memory. */
2N/A goto out_of_memory;
2N/A tmp = (TCHAR_T *) malloc (tmp_memsize);
2N/A if (tmp == NULL)
2N/A /* Out of memory. */
2N/A goto out_of_memory;
2N/A }
2N/A#endif
2N/A
2N/A /* Construct the format string for calling snprintf or
2N/A sprintf. */
2N/A fbp = buf;
2N/A *fbp++ = '%';
2N/A#if NEED_PRINTF_FLAG_GROUPING
2N/A /* The underlying implementation doesn't support the ' flag.
2N/A Produce no grouping characters in this case; this is
2N/A acceptable because the grouping is locale dependent. */
2N/A#else
2N/A if (flags & FLAG_GROUP)
2N/A *fbp++ = '\'';
2N/A#endif
2N/A if (flags & FLAG_LEFT)
2N/A *fbp++ = '-';
2N/A if (flags & FLAG_SHOWSIGN)
2N/A *fbp++ = '+';
2N/A if (flags & FLAG_SPACE)
2N/A *fbp++ = ' ';
2N/A if (flags & FLAG_ALT)
2N/A *fbp++ = '#';
2N/A if (!pad_ourselves)
2N/A {
2N/A if (flags & FLAG_ZERO)
2N/A *fbp++ = '0';
2N/A if (dp->width_start != dp->width_end)
2N/A {
2N/A size_t n = dp->width_end - dp->width_start;
2N/A /* The width specification is known to consist only
2N/A of standard ASCII characters. */
2N/A if (sizeof (FCHAR_T) == sizeof (TCHAR_T))
2N/A {
2N/A memcpy (fbp, dp->width_start, n * sizeof (TCHAR_T));
2N/A fbp += n;
2N/A }
2N/A else
2N/A {
2N/A const FCHAR_T *mp = dp->width_start;
2N/A do
2N/A *fbp++ = (unsigned char) *mp++;
2N/A while (--n > 0);
2N/A }
2N/A }
2N/A }
2N/A if (!prec_ourselves)
2N/A {
2N/A if (dp->precision_start != dp->precision_end)
2N/A {
2N/A size_t n = dp->precision_end - dp->precision_start;
2N/A /* The precision specification is known to consist only
2N/A of standard ASCII characters. */
2N/A if (sizeof (FCHAR_T) == sizeof (TCHAR_T))
2N/A {
2N/A memcpy (fbp, dp->precision_start, n * sizeof (TCHAR_T));
2N/A fbp += n;
2N/A }
2N/A else
2N/A {
2N/A const FCHAR_T *mp = dp->precision_start;
2N/A do
2N/A *fbp++ = (unsigned char) *mp++;
2N/A while (--n > 0);
2N/A }
2N/A }
2N/A }
2N/A
2N/A switch (type)
2N/A {
2N/A#if HAVE_LONG_LONG_INT
2N/A case TYPE_LONGLONGINT:
2N/A case TYPE_ULONGLONGINT:
2N/A# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
2N/A *fbp++ = 'I';
2N/A *fbp++ = '6';
2N/A *fbp++ = '4';
2N/A break;
2N/A# else
2N/A *fbp++ = 'l';
2N/A /*FALLTHROUGH*/
2N/A# endif
2N/A#endif
2N/A case TYPE_LONGINT:
2N/A case TYPE_ULONGINT:
2N/A#if HAVE_WINT_T
2N/A case TYPE_WIDE_CHAR:
2N/A#endif
2N/A#if HAVE_WCHAR_T
2N/A case TYPE_WIDE_STRING:
2N/A#endif
2N/A *fbp++ = 'l';
2N/A break;
2N/A case TYPE_LONGDOUBLE:
2N/A *fbp++ = 'L';
2N/A break;
2N/A default:
2N/A break;
2N/A }
2N/A#if NEED_PRINTF_DIRECTIVE_F
2N/A if (dp->conversion == 'F')
2N/A *fbp = 'f';
2N/A else
2N/A#endif
2N/A *fbp = dp->conversion;
2N/A#if USE_SNPRINTF
2N/A# if !(__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3) || ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__))
2N/A fbp[1] = '%';
2N/A fbp[2] = 'n';
2N/A fbp[3] = '\0';
2N/A# else
2N/A /* On glibc2 systems from glibc >= 2.3 - probably also older
2N/A ones - we know that snprintf's returns value conforms to
2N/A ISO C 99: the gl_SNPRINTF_DIRECTIVE_N test passes.
2N/A Therefore we can avoid using %n in this situation.
2N/A On glibc2 systems from 2004-10-18 or newer, the use of %n
2N/A in format strings in writable memory may crash the program
2N/A (if compiled with _FORTIFY_SOURCE=2), so we should avoid it
2N/A in this situation. */
2N/A /* On native Win32 systems (such as mingw), we can avoid using
2N/A %n because:
2N/A - Although the gl_SNPRINTF_TRUNCATION_C99 test fails,
2N/A snprintf does not write more than the specified number
2N/A of bytes. (snprintf (buf, 3, "%d %d", 4567, 89) writes
2N/A '4', '5', '6' into buf, not '4', '5', '\0'.)
2N/A - Although the gl_SNPRINTF_RETVAL_C99 test fails, snprintf
2N/A allows us to recognize the case of an insufficient
2N/A buffer size: it returns -1 in this case.
2N/A On native Win32 systems (such as mingw) where the OS is
2N/A Windows Vista, the use of %n in format strings by default
2N/A crashes the program. See
2N/A <http://gcc.gnu.org/ml/gcc/2007-06/msg00122.html> and
2N/A <http://msdn2.microsoft.com/en-us/library/ms175782(VS.80).aspx>
2N/A So we should avoid %n in this situation. */
2N/A fbp[1] = '\0';
2N/A# endif
2N/A#else
2N/A fbp[1] = '\0';
2N/A#endif
2N/A
2N/A /* Construct the arguments for calling snprintf or sprintf. */
2N/A prefix_count = 0;
2N/A if (!pad_ourselves && dp->width_arg_index != ARG_NONE)
2N/A {
2N/A if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
2N/A abort ();
2N/A prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int;
2N/A }
2N/A if (!prec_ourselves && dp->precision_arg_index != ARG_NONE)
2N/A {
2N/A if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
2N/A abort ();
2N/A prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int;
2N/A }
2N/A
2N/A#if USE_SNPRINTF
2N/A /* The SNPRINTF result is appended after result[0..length].
2N/A The latter is an array of DCHAR_T; SNPRINTF appends an
2N/A array of TCHAR_T to it. This is possible because
2N/A sizeof (TCHAR_T) divides sizeof (DCHAR_T) and
2N/A alignof (TCHAR_T) <= alignof (DCHAR_T). */
2N/A# define TCHARS_PER_DCHAR (sizeof (DCHAR_T) / sizeof (TCHAR_T))
2N/A /* Ensure that maxlen below will be >= 2. Needed on BeOS,
2N/A where an snprintf() with maxlen==1 acts like sprintf(). */
2N/A ENSURE_ALLOCATION (xsum (length,
2N/A (2 + TCHARS_PER_DCHAR - 1)
2N/A / TCHARS_PER_DCHAR));
2N/A /* Prepare checking whether snprintf returns the count
2N/A via %n. */
2N/A *(TCHAR_T *) (result + length) = '\0';
2N/A#endif
2N/A
2N/A for (;;)
2N/A {
2N/A int count = -1;
2N/A
2N/A#if USE_SNPRINTF
2N/A int retcount = 0;
2N/A size_t maxlen = allocated - length;
2N/A /* SNPRINTF can fail if its second argument is
2N/A > INT_MAX. */
2N/A if (maxlen > INT_MAX / TCHARS_PER_DCHAR)
2N/A maxlen = INT_MAX / TCHARS_PER_DCHAR;
2N/A maxlen = maxlen * TCHARS_PER_DCHAR;
2N/A# define SNPRINTF_BUF(arg) \
2N/A switch (prefix_count) \
2N/A { \
2N/A case 0: \
2N/A retcount = SNPRINTF ((TCHAR_T *) (result + length), \
2N/A maxlen, buf, \
2N/A arg, &count); \
2N/A break; \
2N/A case 1: \
2N/A retcount = SNPRINTF ((TCHAR_T *) (result + length), \
2N/A maxlen, buf, \
2N/A prefixes[0], arg, &count); \
2N/A break; \
2N/A case 2: \
2N/A retcount = SNPRINTF ((TCHAR_T *) (result + length), \
2N/A maxlen, buf, \
2N/A prefixes[0], prefixes[1], arg, \
2N/A &count); \
2N/A break; \
2N/A default: \
2N/A abort (); \
2N/A }
2N/A#else
2N/A# define SNPRINTF_BUF(arg) \
2N/A switch (prefix_count) \
2N/A { \
2N/A case 0: \
2N/A count = sprintf (tmp, buf, arg); \
2N/A break; \
2N/A case 1: \
2N/A count = sprintf (tmp, buf, prefixes[0], arg); \
2N/A break; \
2N/A case 2: \
2N/A count = sprintf (tmp, buf, prefixes[0], prefixes[1],\
2N/A arg); \
2N/A break; \
2N/A default: \
2N/A abort (); \
2N/A }
2N/A#endif
2N/A
2N/A errno = 0;
2N/A switch (type)
2N/A {
2N/A case TYPE_SCHAR:
2N/A {
2N/A int arg = a.arg[dp->arg_index].a.a_schar;
2N/A SNPRINTF_BUF (arg);
2N/A }
2N/A break;
2N/A case TYPE_UCHAR:
2N/A {
2N/A unsigned int arg = a.arg[dp->arg_index].a.a_uchar;
2N/A SNPRINTF_BUF (arg);
2N/A }
2N/A break;
2N/A case TYPE_SHORT:
2N/A {
2N/A int arg = a.arg[dp->arg_index].a.a_short;
2N/A SNPRINTF_BUF (arg);
2N/A }
2N/A break;
2N/A case TYPE_USHORT:
2N/A {
2N/A unsigned int arg = a.arg[dp->arg_index].a.a_ushort;
2N/A SNPRINTF_BUF (arg);
2N/A }
2N/A break;
2N/A case TYPE_INT:
2N/A {
2N/A int arg = a.arg[dp->arg_index].a.a_int;
2N/A SNPRINTF_BUF (arg);
2N/A }
2N/A break;
2N/A case TYPE_UINT:
2N/A {
2N/A unsigned int arg = a.arg[dp->arg_index].a.a_uint;
2N/A SNPRINTF_BUF (arg);
2N/A }
2N/A break;
2N/A case TYPE_LONGINT:
2N/A {
2N/A long int arg = a.arg[dp->arg_index].a.a_longint;
2N/A SNPRINTF_BUF (arg);
2N/A }
2N/A break;
2N/A case TYPE_ULONGINT:
2N/A {
2N/A unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint;
2N/A SNPRINTF_BUF (arg);
2N/A }
2N/A break;
2N/A#if HAVE_LONG_LONG_INT
2N/A case TYPE_LONGLONGINT:
2N/A {
2N/A long long int arg = a.arg[dp->arg_index].a.a_longlongint;
2N/A SNPRINTF_BUF (arg);
2N/A }
2N/A break;
2N/A case TYPE_ULONGLONGINT:
2N/A {
2N/A unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint;
2N/A SNPRINTF_BUF (arg);
2N/A }
2N/A break;
2N/A#endif
2N/A case TYPE_DOUBLE:
2N/A {
2N/A double arg = a.arg[dp->arg_index].a.a_double;
2N/A SNPRINTF_BUF (arg);
2N/A }
2N/A break;
2N/A case TYPE_LONGDOUBLE:
2N/A {
2N/A long double arg = a.arg[dp->arg_index].a.a_longdouble;
2N/A SNPRINTF_BUF (arg);
2N/A }
2N/A break;
2N/A case TYPE_CHAR:
2N/A {
2N/A int arg = a.arg[dp->arg_index].a.a_char;
2N/A SNPRINTF_BUF (arg);
2N/A }
2N/A break;
2N/A#if HAVE_WINT_T
2N/A case TYPE_WIDE_CHAR:
2N/A {
2N/A wint_t arg = a.arg[dp->arg_index].a.a_wide_char;
2N/A SNPRINTF_BUF (arg);
2N/A }
2N/A break;
2N/A#endif
2N/A case TYPE_STRING:
2N/A {
2N/A const char *arg = a.arg[dp->arg_index].a.a_string;
2N/A SNPRINTF_BUF (arg);
2N/A }
2N/A break;
2N/A#if HAVE_WCHAR_T
2N/A case TYPE_WIDE_STRING:
2N/A {
2N/A const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
2N/A SNPRINTF_BUF (arg);
2N/A }
2N/A break;
2N/A#endif
2N/A case TYPE_POINTER:
2N/A {
2N/A void *arg = a.arg[dp->arg_index].a.a_pointer;
2N/A SNPRINTF_BUF (arg);
2N/A }
2N/A break;
2N/A default:
2N/A abort ();
2N/A }
2N/A
2N/A#if USE_SNPRINTF
2N/A /* Portability: Not all implementations of snprintf()
2N/A are ISO C 99 compliant. Determine the number of
2N/A bytes that snprintf() has produced or would have
2N/A produced. */
2N/A if (count >= 0)
2N/A {
2N/A /* Verify that snprintf() has NUL-terminated its
2N/A result. */
2N/A if (count < maxlen
2N/A && ((TCHAR_T *) (result + length)) [count] != '\0')
2N/A abort ();
2N/A /* Portability hack. */
2N/A if (retcount > count)
2N/A count = retcount;
2N/A }
2N/A else
2N/A {
2N/A /* snprintf() doesn't understand the '%n'
2N/A directive. */
2N/A if (fbp[1] != '\0')
2N/A {
2N/A /* Don't use the '%n' directive; instead, look
2N/A at the snprintf() return value. */
2N/A fbp[1] = '\0';
2N/A continue;
2N/A }
2N/A else
2N/A {
2N/A /* Look at the snprintf() return value. */
2N/A if (retcount < 0)
2N/A {
2N/A# if !HAVE_SNPRINTF_RETVAL_C99
2N/A /* HP-UX 10.20 snprintf() is doubly deficient:
2N/A It doesn't understand the '%n' directive,
2N/A *and* it returns -1 (rather than the length
2N/A that would have been required) when the
2N/A buffer is too small.
2N/A But a failure at this point can also come
2N/A from other reasons than a too small buffer,
2N/A such as an invalid wide string argument to
2N/A the %ls directive, or possibly an invalid
2N/A floating-point argument. */
2N/A size_t tmp_length =
2N/A MAX_ROOM_NEEDED (&a, dp->arg_index,
2N/A dp->conversion, type, flags,
2N/A width, has_precision,
2N/A precision, pad_ourselves);
2N/A
2N/A if (maxlen < tmp_length)
2N/A {
2N/A /* Make more room. But try to do through
2N/A this reallocation only once. */
2N/A size_t bigger_need =
2N/A xsum (length,
2N/A xsum (tmp_length,
2N/A TCHARS_PER_DCHAR - 1)
2N/A / TCHARS_PER_DCHAR);
2N/A /* And always grow proportionally.
2N/A (There may be several arguments, each
2N/A needing a little more room than the
2N/A previous one.) */
2N/A size_t bigger_need2 =
2N/A xsum (xtimes (allocated, 2), 12);
2N/A if (bigger_need < bigger_need2)
2N/A bigger_need = bigger_need2;
2N/A ENSURE_ALLOCATION (bigger_need);
2N/A continue;
2N/A }
2N/A# endif
2N/A }
2N/A else
2N/A count = retcount;
2N/A }
2N/A }
2N/A#endif
2N/A
2N/A /* Attempt to handle failure. */
2N/A if (count < 0)
2N/A {
2N/A /* SNPRINTF or sprintf failed. Save and use the errno
2N/A that it has set, if any. */
2N/A int saved_errno = errno;
2N/A
2N/A if (!(result == resultbuf || result == NULL))
2N/A free (result);
2N/A if (buf_malloced != NULL)
2N/A free (buf_malloced);
2N/A CLEANUP ();
2N/A errno =
2N/A (saved_errno != 0
2N/A ? saved_errno
2N/A : (dp->conversion == 'c' || dp->conversion == 's'
2N/A ? EILSEQ
2N/A : EINVAL));
2N/A return NULL;
2N/A }
2N/A
2N/A#if USE_SNPRINTF
2N/A /* Handle overflow of the allocated buffer.
2N/A If such an overflow occurs, a C99 compliant snprintf()
2N/A returns a count >= maxlen. However, a non-compliant
2N/A snprintf() function returns only count = maxlen - 1. To
2N/A cover both cases, test whether count >= maxlen - 1. */
2N/A if ((unsigned int) count + 1 >= maxlen)
2N/A {
2N/A /* If maxlen already has attained its allowed maximum,
2N/A allocating more memory will not increase maxlen.
2N/A Instead of looping, bail out. */
2N/A if (maxlen == INT_MAX / TCHARS_PER_DCHAR)
2N/A goto overflow;
2N/A else
2N/A {
2N/A /* Need at least (count + 1) * sizeof (TCHAR_T)
2N/A bytes. (The +1 is for the trailing NUL.)
2N/A But ask for (count + 2) * sizeof (TCHAR_T)
2N/A bytes, so that in the next round, we likely get
2N/A maxlen > (unsigned int) count + 1
2N/A and so we don't get here again.
2N/A And allocate proportionally, to avoid looping
2N/A eternally if snprintf() reports a too small
2N/A count. */
2N/A size_t n =
2N/A xmax (xsum (length,
2N/A ((unsigned int) count + 2
2N/A + TCHARS_PER_DCHAR - 1)
2N/A / TCHARS_PER_DCHAR),
2N/A xtimes (allocated, 2));
2N/A
2N/A ENSURE_ALLOCATION (n);
2N/A continue;
2N/A }
2N/A }
2N/A#endif
2N/A
2N/A#if NEED_PRINTF_UNBOUNDED_PRECISION
2N/A if (prec_ourselves)
2N/A {
2N/A /* Handle the precision. */
2N/A TCHAR_T *prec_ptr =
2N/A# if USE_SNPRINTF
2N/A (TCHAR_T *) (result + length);
2N/A# else
2N/A tmp;
2N/A# endif
2N/A size_t prefix_count;
2N/A size_t move;
2N/A
2N/A prefix_count = 0;
2N/A /* Put the additional zeroes after the sign. */
2N/A if (count >= 1
2N/A && (*prec_ptr == '-' || *prec_ptr == '+'
2N/A || *prec_ptr == ' '))
2N/A prefix_count = 1;
2N/A /* Put the additional zeroes after the 0x prefix if
2N/A (flags & FLAG_ALT) || (dp->conversion == 'p'). */
2N/A else if (count >= 2
2N/A && prec_ptr[0] == '0'
2N/A && (prec_ptr[1] == 'x' || prec_ptr[1] == 'X'))
2N/A prefix_count = 2;
2N/A
2N/A move = count - prefix_count;
2N/A if (precision > move)
2N/A {
2N/A /* Insert zeroes. */
2N/A size_t insert = precision - move;
2N/A TCHAR_T *prec_end;
2N/A
2N/A# if USE_SNPRINTF
2N/A size_t n =
2N/A xsum (length,
2N/A (count + insert + TCHARS_PER_DCHAR - 1)
2N/A / TCHARS_PER_DCHAR);
2N/A length += (count + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR;
2N/A ENSURE_ALLOCATION (n);
2N/A length -= (count + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR;
2N/A prec_ptr = (TCHAR_T *) (result + length);
2N/A# endif
2N/A
2N/A prec_end = prec_ptr + count;
2N/A prec_ptr += prefix_count;
2N/A
2N/A while (prec_end > prec_ptr)
2N/A {
2N/A prec_end--;
2N/A prec_end[insert] = prec_end[0];
2N/A }
2N/A
2N/A prec_end += insert;
2N/A do
2N/A *--prec_end = '0';
2N/A while (prec_end > prec_ptr);
2N/A
2N/A count += insert;
2N/A }
2N/A }
2N/A#endif
2N/A
2N/A#if !USE_SNPRINTF
2N/A if (count >= tmp_length)
2N/A /* tmp_length was incorrectly calculated - fix the
2N/A code above! */
2N/A abort ();
2N/A#endif
2N/A
2N/A#if !DCHAR_IS_TCHAR
2N/A /* Convert from TCHAR_T[] to DCHAR_T[]. */
2N/A if (dp->conversion == 'c' || dp->conversion == 's')
2N/A {
2N/A /* type = TYPE_CHAR or TYPE_WIDE_CHAR or TYPE_STRING
2N/A TYPE_WIDE_STRING.
2N/A The result string is not certainly ASCII. */
2N/A const TCHAR_T *tmpsrc;
2N/A DCHAR_T *tmpdst;
2N/A size_t tmpdst_len;
2N/A /* This code assumes that TCHAR_T is 'char'. */
2N/A typedef int TCHAR_T_verify
2N/A [2 * (sizeof (TCHAR_T) == 1) - 1];
2N/A# if USE_SNPRINTF
2N/A tmpsrc = (TCHAR_T *) (result + length);
2N/A# else
2N/A tmpsrc = tmp;
2N/A# endif
2N/A tmpdst =
2N/A DCHAR_CONV_FROM_ENCODING (locale_charset (),
2N/A iconveh_question_mark,
2N/A tmpsrc, count,
2N/A NULL,
2N/A NULL, &tmpdst_len);
2N/A if (tmpdst == NULL)
2N/A {
2N/A int saved_errno = errno;
2N/A if (!(result == resultbuf || result == NULL))
2N/A free (result);
2N/A if (buf_malloced != NULL)
2N/A free (buf_malloced);
2N/A CLEANUP ();
2N/A errno = saved_errno;
2N/A return NULL;
2N/A }
2N/A ENSURE_ALLOCATION (xsum (length, tmpdst_len));
2N/A DCHAR_CPY (result + length, tmpdst, tmpdst_len);
2N/A free (tmpdst);
2N/A count = tmpdst_len;
2N/A }
2N/A else
2N/A {
2N/A /* The result string is ASCII.
2N/A Simple 1:1 conversion. */
2N/A# if USE_SNPRINTF
2N/A /* If sizeof (DCHAR_T) == sizeof (TCHAR_T), it's a
2N/A no-op conversion, in-place on the array starting
2N/A at (result + length). */
2N/A if (sizeof (DCHAR_T) != sizeof (TCHAR_T))
2N/A# endif
2N/A {
2N/A const TCHAR_T *tmpsrc;
2N/A DCHAR_T *tmpdst;
2N/A size_t n;
2N/A
2N/A# if USE_SNPRINTF
2N/A if (result == resultbuf)
2N/A {
2N/A tmpsrc = (TCHAR_T *) (result + length);
2N/A /* ENSURE_ALLOCATION will not move tmpsrc
2N/A (because it's part of resultbuf). */
2N/A ENSURE_ALLOCATION (xsum (length, count));
2N/A }
2N/A else
2N/A {
2N/A /* ENSURE_ALLOCATION will move the array
2N/A (because it uses realloc(). */
2N/A ENSURE_ALLOCATION (xsum (length, count));
2N/A tmpsrc = (TCHAR_T *) (result + length);
2N/A }
2N/A# else
2N/A tmpsrc = tmp;
2N/A ENSURE_ALLOCATION (xsum (length, count));
2N/A# endif
2N/A tmpdst = result + length;
2N/A /* Copy backwards, because of overlapping. */
2N/A tmpsrc += count;
2N/A tmpdst += count;
2N/A for (n = count; n > 0; n--)
2N/A *--tmpdst = (unsigned char) *--tmpsrc;
2N/A }
2N/A }
2N/A#endif
2N/A
2N/A#if DCHAR_IS_TCHAR && !USE_SNPRINTF
2N/A /* Make room for the result. */
2N/A if (count > allocated - length)
2N/A {
2N/A /* Need at least count elements. But allocate
2N/A proportionally. */
2N/A size_t n =
2N/A xmax (xsum (length, count), xtimes (allocated, 2));
2N/A
2N/A ENSURE_ALLOCATION (n);
2N/A }
2N/A#endif
2N/A
2N/A /* Here count <= allocated - length. */
2N/A
2N/A /* Perform padding. */
2N/A#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
2N/A if (pad_ourselves && has_width)
2N/A {
2N/A size_t w;
2N/A# if ENABLE_UNISTDIO
2N/A /* Outside POSIX, it's preferrable to compare the width
2N/A against the number of _characters_ of the converted
2N/A value. */
2N/A w = DCHAR_MBSNLEN (result + length, count);
2N/A# else
2N/A /* The width is compared against the number of _bytes_
2N/A of the converted value, says POSIX. */
2N/A w = count;
2N/A# endif
2N/A if (w < width)
2N/A {
2N/A size_t pad = width - w;
2N/A
2N/A /* Make room for the result. */
2N/A if (xsum (count, pad) > allocated - length)
2N/A {
2N/A /* Need at least count + pad elements. But
2N/A allocate proportionally. */
2N/A size_t n =
2N/A xmax (xsum3 (length, count, pad),
2N/A xtimes (allocated, 2));
2N/A
2N/A# if USE_SNPRINTF
2N/A length += count;
2N/A ENSURE_ALLOCATION (n);
2N/A length -= count;
2N/A# else
2N/A ENSURE_ALLOCATION (n);
2N/A# endif
2N/A }
2N/A /* Here count + pad <= allocated - length. */
2N/A
2N/A {
2N/A# if !DCHAR_IS_TCHAR || USE_SNPRINTF
2N/A DCHAR_T * const rp = result + length;
2N/A# else
2N/A DCHAR_T * const rp = tmp;
2N/A# endif
2N/A DCHAR_T *p = rp + count;
2N/A DCHAR_T *end = p + pad;
2N/A DCHAR_T *pad_ptr;
2N/A# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO
2N/A if (dp->conversion == 'c'
2N/A || dp->conversion == 's')
2N/A /* No zero-padding for string directives. */
2N/A pad_ptr = NULL;
2N/A else
2N/A# endif
2N/A {
2N/A pad_ptr = (*rp == '-' ? rp + 1 : rp);
2N/A /* No zero-padding of "inf" and "nan". */
2N/A if ((*pad_ptr >= 'A' && *pad_ptr <= 'Z')
2N/A || (*pad_ptr >= 'a' && *pad_ptr <= 'z'))
2N/A pad_ptr = NULL;
2N/A }
2N/A /* The generated string now extends from rp to p,
2N/A with the zero padding insertion point being at
2N/A pad_ptr. */
2N/A
2N/A count = count + pad; /* = end - rp */
2N/A
2N/A if (flags & FLAG_LEFT)
2N/A {
2N/A /* Pad with spaces on the right. */
2N/A for (; pad > 0; pad--)
2N/A *p++ = ' ';
2N/A }
2N/A else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
2N/A {
2N/A /* Pad with zeroes. */
2N/A DCHAR_T *q = end;
2N/A
2N/A while (p > pad_ptr)
2N/A *--q = *--p;
2N/A for (; pad > 0; pad--)
2N/A *p++ = '0';
2N/A }
2N/A else
2N/A {
2N/A /* Pad with spaces on the left. */
2N/A DCHAR_T *q = end;
2N/A
2N/A while (p > rp)
2N/A *--q = *--p;
2N/A for (; pad > 0; pad--)
2N/A *p++ = ' ';
2N/A }
2N/A }
2N/A }
2N/A }
2N/A#endif
2N/A
2N/A /* Here still count <= allocated - length. */
2N/A
2N/A#if !DCHAR_IS_TCHAR || USE_SNPRINTF
2N/A /* The snprintf() result did fit. */
2N/A#else
2N/A /* Append the sprintf() result. */
2N/A memcpy (result + length, tmp, count * sizeof (DCHAR_T));
2N/A#endif
2N/A#if !USE_SNPRINTF
2N/A if (tmp != tmpbuf)
2N/A free (tmp);
2N/A#endif
2N/A
2N/A#if NEED_PRINTF_DIRECTIVE_F
2N/A if (dp->conversion == 'F')
2N/A {
2N/A /* Convert the %f result to upper case for %F. */
2N/A DCHAR_T *rp = result + length;
2N/A size_t rc;
2N/A for (rc = count; rc > 0; rc--, rp++)
2N/A if (*rp >= 'a' && *rp <= 'z')
2N/A *rp = *rp - 'a' + 'A';
2N/A }
2N/A#endif
2N/A
2N/A length += count;
2N/A break;
2N/A }
2N/A#undef pad_ourselves
2N/A#undef prec_ourselves
2N/A }
2N/A }
2N/A }
2N/A
2N/A /* Add the final NUL. */
2N/A ENSURE_ALLOCATION (xsum (length, 1));
2N/A result[length] = '\0';
2N/A
2N/A if (result != resultbuf && length + 1 < allocated)
2N/A {
2N/A /* Shrink the allocated memory if possible. */
2N/A DCHAR_T *memory;
2N/A
2N/A memory = (DCHAR_T *) realloc (result, (length + 1) * sizeof (DCHAR_T));
2N/A if (memory != NULL)
2N/A result = memory;
2N/A }
2N/A
2N/A if (buf_malloced != NULL)
2N/A free (buf_malloced);
2N/A CLEANUP ();
2N/A *lengthp = length;
2N/A /* Note that we can produce a big string of a length > INT_MAX. POSIX
2N/A says that snprintf() fails with errno = EOVERFLOW in this case, but
2N/A that's only because snprintf() returns an 'int'. This function does
2N/A not have this limitation. */
2N/A return result;
2N/A
2N/A#if USE_SNPRINTF
2N/A overflow:
2N/A if (!(result == resultbuf || result == NULL))
2N/A free (result);
2N/A if (buf_malloced != NULL)
2N/A free (buf_malloced);
2N/A CLEANUP ();
2N/A errno = EOVERFLOW;
2N/A return NULL;
2N/A#endif
2N/A
2N/A out_of_memory:
2N/A if (!(result == resultbuf || result == NULL))
2N/A free (result);
2N/A if (buf_malloced != NULL)
2N/A free (buf_malloced);
2N/A out_of_memory_1:
2N/A CLEANUP ();
2N/A errno = ENOMEM;
2N/A return NULL;
2N/A }
2N/A}
2N/A
2N/A#undef MAX_ROOM_NEEDED
2N/A#undef TCHARS_PER_DCHAR
2N/A#undef SNPRINTF
2N/A#undef USE_SNPRINTF
2N/A#undef DCHAR_SET
2N/A#undef DCHAR_CPY
2N/A#undef PRINTF_PARSE
2N/A#undef DIRECTIVES
2N/A#undef DIRECTIVE
2N/A#undef DCHAR_IS_TCHAR
2N/A#undef TCHAR_T
2N/A#undef DCHAR_T
2N/A#undef FCHAR_T
2N/A#undef VASNPRINTF