Blame stdio-common/printf_fp.c

Packit Service 82fcde
/* Floating point output for `printf'.
Packit Service 82fcde
   Copyright (C) 1995-2018 Free Software Foundation, Inc.
Packit Service 82fcde
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
   Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
/* The gmp headers need some configuration frobs.  */
Packit Service 82fcde
#define HAVE_ALLOCA 1
Packit Service 82fcde
Packit Service 82fcde
#include <array_length.h>
Packit Service 82fcde
#include <libioP.h>
Packit Service 82fcde
#include <alloca.h>
Packit Service 82fcde
#include <ctype.h>
Packit Service 82fcde
#include <float.h>
Packit Service 82fcde
#include <gmp-mparam.h>
Packit Service 82fcde
#include <gmp.h>
Packit Service 82fcde
#include <ieee754.h>
Packit Service 82fcde
#include <stdlib/gmp-impl.h>
Packit Service 82fcde
#include <stdlib/longlong.h>
Packit Service 82fcde
#include <stdlib/fpioconst.h>
Packit Service 82fcde
#include <locale/localeinfo.h>
Packit Service 82fcde
#include <limits.h>
Packit Service 82fcde
#include <math.h>
Packit Service 82fcde
#include <printf.h>
Packit Service 82fcde
#include <string.h>
Packit Service 82fcde
#include <unistd.h>
Packit Service 82fcde
#include <stdlib.h>
Packit Service 82fcde
#include <wchar.h>
Packit Service 82fcde
#include <stdbool.h>
Packit Service 82fcde
#include <rounding-mode.h>
Packit Service 82fcde
Packit Service 82fcde
#ifdef COMPILE_WPRINTF
Packit Service 82fcde
# define CHAR_T        wchar_t
Packit Service 82fcde
#else
Packit Service 82fcde
# define CHAR_T        char
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
#include "_i18n_number.h"
Packit Service 82fcde
Packit Service 82fcde
#ifndef NDEBUG
Packit Service 82fcde
# define NDEBUG			/* Undefine this for debugging assertions.  */
Packit Service 82fcde
#endif
Packit Service 82fcde
#include <assert.h>
Packit Service 82fcde
Packit Service 82fcde
#define PUT(f, s, n) _IO_sputn (f, s, n)
Packit Service 82fcde
#define PAD(f, c, n) (wide ? _IO_wpadn (f, c, n) : _IO_padn (f, c, n))
Packit Service 82fcde
#undef putc
Packit Service 82fcde
#define putc(c, f) (wide \
Packit Service 82fcde
		    ? (int)_IO_putwc_unlocked (c, f) : _IO_putc_unlocked (c, f))
Packit Service 82fcde
Packit Service 82fcde

Packit Service 82fcde
/* Macros for doing the actual output.  */
Packit Service 82fcde
Packit Service 82fcde
#define outchar(ch)							      \
Packit Service 82fcde
  do									      \
Packit Service 82fcde
    {									      \
Packit Service 82fcde
      const int outc = (ch);						      \
Packit Service 82fcde
      if (putc (outc, fp) == EOF)					      \
Packit Service 82fcde
	{								      \
Packit Service 82fcde
	  if (buffer_malloced)						      \
Packit Service 82fcde
	    free (wbuffer);						      \
Packit Service 82fcde
	  return -1;							      \
Packit Service 82fcde
	}								      \
Packit Service 82fcde
      ++done;								      \
Packit Service 82fcde
    } while (0)
Packit Service 82fcde
Packit Service 82fcde
#define PRINT(ptr, wptr, len)						      \
Packit Service 82fcde
  do									      \
Packit Service 82fcde
    {									      \
Packit Service 82fcde
      size_t outlen = (len);						      \
Packit Service 82fcde
      if (len > 20)							      \
Packit Service 82fcde
	{								      \
Packit Service 82fcde
	  if (PUT (fp, wide ? (const char *) wptr : ptr, outlen) != outlen)   \
Packit Service 82fcde
	    {								      \
Packit Service 82fcde
	      if (buffer_malloced)					      \
Packit Service 82fcde
		free (wbuffer);						      \
Packit Service 82fcde
	      return -1;						      \
Packit Service 82fcde
	    }								      \
Packit Service 82fcde
	  ptr += outlen;						      \
Packit Service 82fcde
	  done += outlen;						      \
Packit Service 82fcde
	}								      \
Packit Service 82fcde
      else								      \
Packit Service 82fcde
	{								      \
Packit Service 82fcde
	  if (wide)							      \
Packit Service 82fcde
	    while (outlen-- > 0)					      \
Packit Service 82fcde
	      outchar (*wptr++);					      \
Packit Service 82fcde
	  else								      \
Packit Service 82fcde
	    while (outlen-- > 0)					      \
Packit Service 82fcde
	      outchar (*ptr++);						      \
Packit Service 82fcde
	}								      \
Packit Service 82fcde
    } while (0)
Packit Service 82fcde
Packit Service 82fcde
#define PADN(ch, len)							      \
Packit Service 82fcde
  do									      \
Packit Service 82fcde
    {									      \
Packit Service 82fcde
      if (PAD (fp, ch, len) != len)					      \
Packit Service 82fcde
	{								      \
Packit Service 82fcde
	  if (buffer_malloced)						      \
Packit Service 82fcde
	    free (wbuffer);						      \
Packit Service 82fcde
	  return -1;							      \
Packit Service 82fcde
	}								      \
Packit Service 82fcde
      done += len;							      \
Packit Service 82fcde
    }									      \
Packit Service 82fcde
  while (0)
Packit Service 82fcde

Packit Service 82fcde
/* We use the GNU MP library to handle large numbers.
Packit Service 82fcde
Packit Service 82fcde
   An MP variable occupies a varying number of entries in its array.  We keep
Packit Service 82fcde
   track of this number for efficiency reasons.  Otherwise we would always
Packit Service 82fcde
   have to process the whole array.  */
Packit Service 82fcde
#define MPN_VAR(name) mp_limb_t *name; mp_size_t name##size
Packit Service 82fcde
Packit Service 82fcde
#define MPN_ASSIGN(dst,src)						      \
Packit Service 82fcde
  memcpy (dst, src, (dst##size = src##size) * sizeof (mp_limb_t))
Packit Service 82fcde
#define MPN_GE(u,v) \
Packit Service 82fcde
  (u##size > v##size || (u##size == v##size && __mpn_cmp (u, v, u##size) >= 0))
Packit Service 82fcde
Packit Service 82fcde
extern mp_size_t __mpn_extract_double (mp_ptr res_ptr, mp_size_t size,
Packit Service 82fcde
				       int *expt, int *is_neg,
Packit Service 82fcde
				       double value);
Packit Service 82fcde
extern mp_size_t __mpn_extract_long_double (mp_ptr res_ptr, mp_size_t size,
Packit Service 82fcde
					    int *expt, int *is_neg,
Packit Service 82fcde
					    long double value);
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
static wchar_t *group_number (wchar_t *buf, wchar_t *bufend,
Packit Service 82fcde
			      unsigned int intdig_no, const char *grouping,
Packit Service 82fcde
			      wchar_t thousands_sep, int ngroups);
Packit Service 82fcde
Packit Service 82fcde
struct hack_digit_param
Packit Service 82fcde
{
Packit Service 82fcde
  /* Sign of the exponent.  */
Packit Service 82fcde
  int expsign;
Packit Service 82fcde
  /* The type of output format that will be used: 'e'/'E' or 'f'.  */
Packit Service 82fcde
  int type;
Packit Service 82fcde
  /* and the exponent.	*/
Packit Service 82fcde
  int exponent;
Packit Service 82fcde
  /* The fraction of the floting-point value in question  */
Packit Service 82fcde
  MPN_VAR(frac);
Packit Service 82fcde
  /* Scaling factor.  */
Packit Service 82fcde
  MPN_VAR(scale);
Packit Service 82fcde
  /* Temporary bignum value.  */
Packit Service 82fcde
  MPN_VAR(tmp);
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
static wchar_t
Packit Service 82fcde
hack_digit (struct hack_digit_param *p)
Packit Service 82fcde
{
Packit Service 82fcde
  mp_limb_t hi;
Packit Service 82fcde
Packit Service 82fcde
  if (p->expsign != 0 && p->type == 'f' && p->exponent-- > 0)
Packit Service 82fcde
    hi = 0;
Packit Service 82fcde
  else if (p->scalesize == 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      hi = p->frac[p->fracsize - 1];
Packit Service 82fcde
      p->frac[p->fracsize - 1] = __mpn_mul_1 (p->frac, p->frac,
Packit Service 82fcde
	p->fracsize - 1, 10);
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
      if (p->fracsize < p->scalesize)
Packit Service 82fcde
	hi = 0;
Packit Service 82fcde
      else
Packit Service 82fcde
	{
Packit Service 82fcde
	  hi = mpn_divmod (p->tmp, p->frac, p->fracsize,
Packit Service 82fcde
	    p->scale, p->scalesize);
Packit Service 82fcde
	  p->tmp[p->fracsize - p->scalesize] = hi;
Packit Service 82fcde
	  hi = p->tmp[0];
Packit Service 82fcde
Packit Service 82fcde
	  p->fracsize = p->scalesize;
Packit Service 82fcde
	  while (p->fracsize != 0 && p->frac[p->fracsize - 1] == 0)
Packit Service 82fcde
	    --p->fracsize;
Packit Service 82fcde
	  if (p->fracsize == 0)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      /* We're not prepared for an mpn variable with zero
Packit Service 82fcde
		 limbs.  */
Packit Service 82fcde
	      p->fracsize = 1;
Packit Service 82fcde
	      return L'0' + hi;
Packit Service 82fcde
	    }
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      mp_limb_t _cy = __mpn_mul_1 (p->frac, p->frac, p->fracsize, 10);
Packit Service 82fcde
      if (_cy != 0)
Packit Service 82fcde
	p->frac[p->fracsize++] = _cy;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  return L'0' + hi;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
int
Packit Service 82fcde
__printf_fp_l (FILE *fp, locale_t loc,
Packit Service 82fcde
	       const struct printf_info *info,
Packit Service 82fcde
	       const void *const *args)
Packit Service 82fcde
{
Packit Service 82fcde
  /* The floating-point value to output.  */
Packit Service 82fcde
  union
Packit Service 82fcde
    {
Packit Service 82fcde
      double dbl;
Packit Service 82fcde
      long double ldbl;
Packit Service 82fcde
#if __HAVE_DISTINCT_FLOAT128
Packit Service 82fcde
      _Float128 f128;
Packit Service 82fcde
#endif
Packit Service 82fcde
    }
Packit Service 82fcde
  fpnum;
Packit Service 82fcde
Packit Service 82fcde
  /* Locale-dependent representation of decimal point.	*/
Packit Service 82fcde
  const char *decimal;
Packit Service 82fcde
  wchar_t decimalwc;
Packit Service 82fcde
Packit Service 82fcde
  /* Locale-dependent thousands separator and grouping specification.  */
Packit Service 82fcde
  const char *thousands_sep = NULL;
Packit Service 82fcde
  wchar_t thousands_sepwc = 0;
Packit Service 82fcde
  const char *grouping;
Packit Service 82fcde
Packit Service 82fcde
  /* "NaN" or "Inf" for the special cases.  */
Packit Service 82fcde
  const char *special = NULL;
Packit Service 82fcde
  const wchar_t *wspecial = NULL;
Packit Service 82fcde
Packit Service 82fcde
  /* When _Float128 is enabled in the library and ABI-distinct from long
Packit Service 82fcde
     double, we need mp_limbs enough for any of them.  */
Packit Service 82fcde
#if __HAVE_DISTINCT_FLOAT128
Packit Service 82fcde
# define GREATER_MANT_DIG FLT128_MANT_DIG
Packit Service 82fcde
#else
Packit Service 82fcde
# define GREATER_MANT_DIG LDBL_MANT_DIG
Packit Service 82fcde
#endif
Packit Service 82fcde
  /* We need just a few limbs for the input before shifting to the right
Packit Service 82fcde
     position.	*/
Packit Service 82fcde
  mp_limb_t fp_input[(GREATER_MANT_DIG + BITS_PER_MP_LIMB - 1)
Packit Service 82fcde
		     / BITS_PER_MP_LIMB];
Packit Service 82fcde
  /* We need to shift the contents of fp_input by this amount of bits.	*/
Packit Service 82fcde
  int to_shift = 0;
Packit Service 82fcde
Packit Service 82fcde
  struct hack_digit_param p;
Packit Service 82fcde
  /* Sign of float number.  */
Packit Service 82fcde
  int is_neg = 0;
Packit Service 82fcde
Packit Service 82fcde
  /* Counter for number of written characters.	*/
Packit Service 82fcde
  int done = 0;
Packit Service 82fcde
Packit Service 82fcde
  /* General helper (carry limb).  */
Packit Service 82fcde
  mp_limb_t cy;
Packit Service 82fcde
Packit Service 82fcde
  /* Nonzero if this is output on a wide character stream.  */
Packit Service 82fcde
  int wide = info->wide;
Packit Service 82fcde
Packit Service 82fcde
  /* Buffer in which we produce the output.  */
Packit Service 82fcde
  wchar_t *wbuffer = NULL;
Packit Service 82fcde
  /* Flag whether wbuffer is malloc'ed or not.  */
Packit Service 82fcde
  int buffer_malloced = 0;
Packit Service 82fcde
Packit Service 82fcde
  p.expsign = 0;
Packit Service 82fcde
Packit Service 82fcde
  /* Figure out the decimal point character.  */
Packit Service 82fcde
  if (info->extra == 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      decimal = _nl_lookup (loc, LC_NUMERIC, DECIMAL_POINT);
Packit Service 82fcde
      decimalwc = _nl_lookup_word
Packit Service 82fcde
	(loc, LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC);
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
      decimal = _nl_lookup (loc, LC_MONETARY, MON_DECIMAL_POINT);
Packit Service 82fcde
      if (*decimal == '\0')
Packit Service 82fcde
	decimal = _nl_lookup (loc, LC_NUMERIC, DECIMAL_POINT);
Packit Service 82fcde
      decimalwc = _nl_lookup_word (loc, LC_MONETARY,
Packit Service 82fcde
				    _NL_MONETARY_DECIMAL_POINT_WC);
Packit Service 82fcde
      if (decimalwc == L'\0')
Packit Service 82fcde
	decimalwc = _nl_lookup_word (loc, LC_NUMERIC,
Packit Service 82fcde
				      _NL_NUMERIC_DECIMAL_POINT_WC);
Packit Service 82fcde
    }
Packit Service 82fcde
  /* The decimal point character must not be zero.  */
Packit Service 82fcde
  assert (*decimal != '\0');
Packit Service 82fcde
  assert (decimalwc != L'\0');
Packit Service 82fcde
Packit Service 82fcde
  if (info->group)
Packit Service 82fcde
    {
Packit Service 82fcde
      if (info->extra == 0)
Packit Service 82fcde
	grouping = _nl_lookup (loc, LC_NUMERIC, GROUPING);
Packit Service 82fcde
      else
Packit Service 82fcde
	grouping = _nl_lookup (loc, LC_MONETARY, MON_GROUPING);
Packit Service 82fcde
Packit Service 82fcde
      if (*grouping <= 0 || *grouping == CHAR_MAX)
Packit Service 82fcde
	grouping = NULL;
Packit Service 82fcde
      else
Packit Service 82fcde
	{
Packit Service 82fcde
	  /* Figure out the thousands separator character.  */
Packit Service 82fcde
	  if (wide)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      if (info->extra == 0)
Packit Service 82fcde
		thousands_sepwc = _nl_lookup_word
Packit Service 82fcde
		  (loc, LC_NUMERIC, _NL_NUMERIC_THOUSANDS_SEP_WC);
Packit Service 82fcde
	      else
Packit Service 82fcde
		thousands_sepwc =
Packit Service 82fcde
		  _nl_lookup_word (loc, LC_MONETARY,
Packit Service 82fcde
				    _NL_MONETARY_THOUSANDS_SEP_WC);
Packit Service 82fcde
	    }
Packit Service 82fcde
	  else
Packit Service 82fcde
	    {
Packit Service 82fcde
	      if (info->extra == 0)
Packit Service 82fcde
		thousands_sep = _nl_lookup (loc, LC_NUMERIC, THOUSANDS_SEP);
Packit Service 82fcde
	      else
Packit Service 82fcde
		thousands_sep = _nl_lookup
Packit Service 82fcde
		  (loc, LC_MONETARY, MON_THOUSANDS_SEP);
Packit Service 82fcde
	    }
Packit Service 82fcde
Packit Service 82fcde
	  if ((wide && thousands_sepwc == L'\0')
Packit Service 82fcde
	      || (! wide && *thousands_sep == '\0'))
Packit Service 82fcde
	    grouping = NULL;
Packit Service 82fcde
	  else if (thousands_sepwc == L'\0')
Packit Service 82fcde
	    /* If we are printing multibyte characters and there is a
Packit Service 82fcde
	       multibyte representation for the thousands separator,
Packit Service 82fcde
	       we must ensure the wide character thousands separator
Packit Service 82fcde
	       is available, even if it is fake.  */
Packit Service 82fcde
	    thousands_sepwc = 0xfffffffe;
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    grouping = NULL;
Packit Service 82fcde
Packit Service 82fcde
#define PRINTF_FP_FETCH(FLOAT, VAR, SUFFIX, MANT_DIG)			\
Packit Service 82fcde
  {									\
Packit Service 82fcde
    (VAR) = *(const FLOAT *) args[0];					\
Packit Service 82fcde
									\
Packit Service 82fcde
    /* Check for special values: not a number or infinity.  */		\
Packit Service 82fcde
    if (isnan (VAR))							\
Packit Service 82fcde
      {									\
Packit Service 82fcde
	is_neg = signbit (VAR);						\
Packit Service 82fcde
	if (isupper (info->spec))					\
Packit Service 82fcde
	  {								\
Packit Service 82fcde
	    special = "NAN";						\
Packit Service 82fcde
	    wspecial = L"NAN";						\
Packit Service 82fcde
	  }								\
Packit Service 82fcde
	else								\
Packit Service 82fcde
	  {								\
Packit Service 82fcde
	    special = "nan";						\
Packit Service 82fcde
	    wspecial = L"nan";						\
Packit Service 82fcde
	  }								\
Packit Service 82fcde
      }									\
Packit Service 82fcde
    else if (isinf (VAR))						\
Packit Service 82fcde
      {									\
Packit Service 82fcde
	is_neg = signbit (VAR);						\
Packit Service 82fcde
	if (isupper (info->spec))					\
Packit Service 82fcde
	  {								\
Packit Service 82fcde
	    special = "INF";						\
Packit Service 82fcde
	    wspecial = L"INF";						\
Packit Service 82fcde
	  }								\
Packit Service 82fcde
	else								\
Packit Service 82fcde
	  {								\
Packit Service 82fcde
	    special = "inf";						\
Packit Service 82fcde
	    wspecial = L"inf";						\
Packit Service 82fcde
	  }								\
Packit Service 82fcde
      }									\
Packit Service 82fcde
    else								\
Packit Service 82fcde
      {									\
Packit Service 82fcde
	p.fracsize = __mpn_extract_##SUFFIX				\
Packit Service 82fcde
		     (fp_input, array_length (fp_input),		\
Packit Service 82fcde
		      &p.exponent, &is_neg, VAR);			\
Packit Service 82fcde
	to_shift = 1 + p.fracsize * BITS_PER_MP_LIMB - MANT_DIG;	\
Packit Service 82fcde
      }									\
Packit Service 82fcde
  }
Packit Service 82fcde
Packit Service 82fcde
  /* Fetch the argument value.	*/
Packit Service 82fcde
#if __HAVE_DISTINCT_FLOAT128
Packit Service 82fcde
  if (info->is_binary128)
Packit Service 82fcde
    PRINTF_FP_FETCH (_Float128, fpnum.f128, float128, FLT128_MANT_DIG)
Packit Service 82fcde
  else
Packit Service 82fcde
#endif
Packit Service 82fcde
#ifndef __NO_LONG_DOUBLE_MATH
Packit Service 82fcde
  if (info->is_long_double && sizeof (long double) > sizeof (double))
Packit Service 82fcde
    PRINTF_FP_FETCH (long double, fpnum.ldbl, long_double, LDBL_MANT_DIG)
Packit Service 82fcde
  else
Packit Service 82fcde
#endif
Packit Service 82fcde
    PRINTF_FP_FETCH (double, fpnum.dbl, double, DBL_MANT_DIG)
Packit Service 82fcde
Packit Service 82fcde
#undef PRINTF_FP_FETCH
Packit Service 82fcde
Packit Service 82fcde
  if (special)
Packit Service 82fcde
    {
Packit Service 82fcde
      int width = info->width;
Packit Service 82fcde
Packit Service 82fcde
      if (is_neg || info->showsign || info->space)
Packit Service 82fcde
	--width;
Packit Service 82fcde
      width -= 3;
Packit Service 82fcde
Packit Service 82fcde
      if (!info->left && width > 0)
Packit Service 82fcde
	PADN (' ', width);
Packit Service 82fcde
Packit Service 82fcde
      if (is_neg)
Packit Service 82fcde
	outchar ('-');
Packit Service 82fcde
      else if (info->showsign)
Packit Service 82fcde
	outchar ('+');
Packit Service 82fcde
      else if (info->space)
Packit Service 82fcde
	outchar (' ');
Packit Service 82fcde
Packit Service 82fcde
      PRINT (special, wspecial, 3);
Packit Service 82fcde
Packit Service 82fcde
      if (info->left && width > 0)
Packit Service 82fcde
	PADN (' ', width);
Packit Service 82fcde
Packit Service 82fcde
      return done;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
  /* We need three multiprecision variables.  Now that we have the p.exponent
Packit Service 82fcde
     of the number we can allocate the needed memory.  It would be more
Packit Service 82fcde
     efficient to use variables of the fixed maximum size but because this
Packit Service 82fcde
     would be really big it could lead to memory problems.  */
Packit Service 82fcde
  {
Packit Service 82fcde
    mp_size_t bignum_size = ((abs (p.exponent) + BITS_PER_MP_LIMB - 1)
Packit Service 82fcde
			     / BITS_PER_MP_LIMB
Packit Service 82fcde
			     + (GREATER_MANT_DIG / BITS_PER_MP_LIMB > 2
Packit Service 82fcde
				? 8 : 4))
Packit Service 82fcde
			    * sizeof (mp_limb_t);
Packit Service 82fcde
    p.frac = (mp_limb_t *) alloca (bignum_size);
Packit Service 82fcde
    p.tmp = (mp_limb_t *) alloca (bignum_size);
Packit Service 82fcde
    p.scale = (mp_limb_t *) alloca (bignum_size);
Packit Service 82fcde
  }
Packit Service 82fcde
Packit Service 82fcde
  /* We now have to distinguish between numbers with positive and negative
Packit Service 82fcde
     exponents because the method used for the one is not applicable/efficient
Packit Service 82fcde
     for the other.  */
Packit Service 82fcde
  p.scalesize = 0;
Packit Service 82fcde
  if (p.exponent > 2)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* |FP| >= 8.0.  */
Packit Service 82fcde
      int scaleexpo = 0;
Packit Service 82fcde
      int explog;
Packit Service 82fcde
#if __HAVE_DISTINCT_FLOAT128
Packit Service 82fcde
      if (info->is_binary128)
Packit Service 82fcde
	explog = FLT128_MAX_10_EXP_LOG;
Packit Service 82fcde
      else
Packit Service 82fcde
	explog = LDBL_MAX_10_EXP_LOG;
Packit Service 82fcde
#else
Packit Service 82fcde
      explog = LDBL_MAX_10_EXP_LOG;
Packit Service 82fcde
#endif
Packit Service 82fcde
      int exp10 = 0;
Packit Service 82fcde
      const struct mp_power *powers = &_fpioconst_pow10[explog + 1];
Packit Service 82fcde
      int cnt_h, cnt_l, i;
Packit Service 82fcde
Packit Service 82fcde
      if ((p.exponent + to_shift) % BITS_PER_MP_LIMB == 0)
Packit Service 82fcde
	{
Packit Service 82fcde
	  MPN_COPY_DECR (p.frac + (p.exponent + to_shift) / BITS_PER_MP_LIMB,
Packit Service 82fcde
			 fp_input, p.fracsize);
Packit Service 82fcde
	  p.fracsize += (p.exponent + to_shift) / BITS_PER_MP_LIMB;
Packit Service 82fcde
	}
Packit Service 82fcde
      else
Packit Service 82fcde
	{
Packit Service 82fcde
	  cy = __mpn_lshift (p.frac +
Packit Service 82fcde
			     (p.exponent + to_shift) / BITS_PER_MP_LIMB,
Packit Service 82fcde
			     fp_input, p.fracsize,
Packit Service 82fcde
			     (p.exponent + to_shift) % BITS_PER_MP_LIMB);
Packit Service 82fcde
	  p.fracsize += (p.exponent + to_shift) / BITS_PER_MP_LIMB;
Packit Service 82fcde
	  if (cy)
Packit Service 82fcde
	    p.frac[p.fracsize++] = cy;
Packit Service 82fcde
	}
Packit Service 82fcde
      MPN_ZERO (p.frac, (p.exponent + to_shift) / BITS_PER_MP_LIMB);
Packit Service 82fcde
Packit Service 82fcde
      assert (powers > &_fpioconst_pow10[0]);
Packit Service 82fcde
      do
Packit Service 82fcde
	{
Packit Service 82fcde
	  --powers;
Packit Service 82fcde
Packit Service 82fcde
	  /* The number of the product of two binary numbers with n and m
Packit Service 82fcde
	     bits respectively has m+n or m+n-1 bits.	*/
Packit Service 82fcde
	  if (p.exponent >= scaleexpo + powers->p_expo - 1)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      if (p.scalesize == 0)
Packit Service 82fcde
		{
Packit Service 82fcde
#if __HAVE_DISTINCT_FLOAT128
Packit Service 82fcde
		  if ((FLT128_MANT_DIG
Packit Service 82fcde
			    > _FPIO_CONST_OFFSET * BITS_PER_MP_LIMB)
Packit Service 82fcde
			   && info->is_binary128)
Packit Service 82fcde
		    {
Packit Service 82fcde
#define _FLT128_FPIO_CONST_SHIFT \
Packit Service 82fcde
  (((FLT128_MANT_DIG + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB) \
Packit Service 82fcde
   - _FPIO_CONST_OFFSET)
Packit Service 82fcde
		      /* 64bit const offset is not enough for
Packit Service 82fcde
			 IEEE 854 quad long double (_Float128).  */
Packit Service 82fcde
		      p.tmpsize = powers->arraysize + _FLT128_FPIO_CONST_SHIFT;
Packit Service 82fcde
		      memcpy (p.tmp + _FLT128_FPIO_CONST_SHIFT,
Packit Service 82fcde
			      &__tens[powers->arrayoff],
Packit Service 82fcde
			      p.tmpsize * sizeof (mp_limb_t));
Packit Service 82fcde
		      MPN_ZERO (p.tmp, _FLT128_FPIO_CONST_SHIFT);
Packit Service 82fcde
		      /* Adjust p.exponent, as scaleexpo will be this much
Packit Service 82fcde
			 bigger too.  */
Packit Service 82fcde
		      p.exponent += _FLT128_FPIO_CONST_SHIFT * BITS_PER_MP_LIMB;
Packit Service 82fcde
		    }
Packit Service 82fcde
		  else
Packit Service 82fcde
#endif /* __HAVE_DISTINCT_FLOAT128 */
Packit Service 82fcde
#ifndef __NO_LONG_DOUBLE_MATH
Packit Service 82fcde
		  if (LDBL_MANT_DIG > _FPIO_CONST_OFFSET * BITS_PER_MP_LIMB
Packit Service 82fcde
		      && info->is_long_double)
Packit Service 82fcde
		    {
Packit Service 82fcde
#define _FPIO_CONST_SHIFT \
Packit Service 82fcde
  (((LDBL_MANT_DIG + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB) \
Packit Service 82fcde
   - _FPIO_CONST_OFFSET)
Packit Service 82fcde
		      /* 64bit const offset is not enough for
Packit Service 82fcde
			 IEEE quad long double.  */
Packit Service 82fcde
		      p.tmpsize = powers->arraysize + _FPIO_CONST_SHIFT;
Packit Service 82fcde
		      memcpy (p.tmp + _FPIO_CONST_SHIFT,
Packit Service 82fcde
			      &__tens[powers->arrayoff],
Packit Service 82fcde
			      p.tmpsize * sizeof (mp_limb_t));
Packit Service 82fcde
		      MPN_ZERO (p.tmp, _FPIO_CONST_SHIFT);
Packit Service 82fcde
		      /* Adjust p.exponent, as scaleexpo will be this much
Packit Service 82fcde
			 bigger too.  */
Packit Service 82fcde
		      p.exponent += _FPIO_CONST_SHIFT * BITS_PER_MP_LIMB;
Packit Service 82fcde
		    }
Packit Service 82fcde
		  else
Packit Service 82fcde
#endif
Packit Service 82fcde
		    {
Packit Service 82fcde
		      p.tmpsize = powers->arraysize;
Packit Service 82fcde
		      memcpy (p.tmp, &__tens[powers->arrayoff],
Packit Service 82fcde
			      p.tmpsize * sizeof (mp_limb_t));
Packit Service 82fcde
		    }
Packit Service 82fcde
		}
Packit Service 82fcde
	      else
Packit Service 82fcde
		{
Packit Service 82fcde
		  cy = __mpn_mul (p.tmp, p.scale, p.scalesize,
Packit Service 82fcde
				  &__tens[powers->arrayoff
Packit Service 82fcde
					 + _FPIO_CONST_OFFSET],
Packit Service 82fcde
				  powers->arraysize - _FPIO_CONST_OFFSET);
Packit Service 82fcde
		  p.tmpsize = p.scalesize +
Packit Service 82fcde
		    powers->arraysize - _FPIO_CONST_OFFSET;
Packit Service 82fcde
		  if (cy == 0)
Packit Service 82fcde
		    --p.tmpsize;
Packit Service 82fcde
		}
Packit Service 82fcde
Packit Service 82fcde
	      if (MPN_GE (p.frac, p.tmp))
Packit Service 82fcde
		{
Packit Service 82fcde
		  int cnt;
Packit Service 82fcde
		  MPN_ASSIGN (p.scale, p.tmp);
Packit Service 82fcde
		  count_leading_zeros (cnt, p.scale[p.scalesize - 1]);
Packit Service 82fcde
		  scaleexpo = (p.scalesize - 2) * BITS_PER_MP_LIMB - cnt - 1;
Packit Service 82fcde
		  exp10 |= 1 << explog;
Packit Service 82fcde
		}
Packit Service 82fcde
	    }
Packit Service 82fcde
	  --explog;
Packit Service 82fcde
	}
Packit Service 82fcde
      while (powers > &_fpioconst_pow10[0]);
Packit Service 82fcde
      p.exponent = exp10;
Packit Service 82fcde
Packit Service 82fcde
      /* Optimize number representations.  We want to represent the numbers
Packit Service 82fcde
	 with the lowest number of bytes possible without losing any
Packit Service 82fcde
	 bytes. Also the highest bit in the scaling factor has to be set
Packit Service 82fcde
	 (this is a requirement of the MPN division routines).  */
Packit Service 82fcde
      if (p.scalesize > 0)
Packit Service 82fcde
	{
Packit Service 82fcde
	  /* Determine minimum number of zero bits at the end of
Packit Service 82fcde
	     both numbers.  */
Packit Service 82fcde
	  for (i = 0; p.scale[i] == 0 && p.frac[i] == 0; i++)
Packit Service 82fcde
	    ;
Packit Service 82fcde
Packit Service 82fcde
	  /* Determine number of bits the scaling factor is misplaced.	*/
Packit Service 82fcde
	  count_leading_zeros (cnt_h, p.scale[p.scalesize - 1]);
Packit Service 82fcde
Packit Service 82fcde
	  if (cnt_h == 0)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      /* The highest bit of the scaling factor is already set.	So
Packit Service 82fcde
		 we only have to remove the trailing empty limbs.  */
Packit Service 82fcde
	      if (i > 0)
Packit Service 82fcde
		{
Packit Service 82fcde
		  MPN_COPY_INCR (p.scale, p.scale + i, p.scalesize - i);
Packit Service 82fcde
		  p.scalesize -= i;
Packit Service 82fcde
		  MPN_COPY_INCR (p.frac, p.frac + i, p.fracsize - i);
Packit Service 82fcde
		  p.fracsize -= i;
Packit Service 82fcde
		}
Packit Service 82fcde
	    }
Packit Service 82fcde
	  else
Packit Service 82fcde
	    {
Packit Service 82fcde
	      if (p.scale[i] != 0)
Packit Service 82fcde
		{
Packit Service 82fcde
		  count_trailing_zeros (cnt_l, p.scale[i]);
Packit Service 82fcde
		  if (p.frac[i] != 0)
Packit Service 82fcde
		    {
Packit Service 82fcde
		      int cnt_l2;
Packit Service 82fcde
		      count_trailing_zeros (cnt_l2, p.frac[i]);
Packit Service 82fcde
		      if (cnt_l2 < cnt_l)
Packit Service 82fcde
			cnt_l = cnt_l2;
Packit Service 82fcde
		    }
Packit Service 82fcde
		}
Packit Service 82fcde
	      else
Packit Service 82fcde
		count_trailing_zeros (cnt_l, p.frac[i]);
Packit Service 82fcde
Packit Service 82fcde
	      /* Now shift the numbers to their optimal position.  */
Packit Service 82fcde
	      if (i == 0 && BITS_PER_MP_LIMB - cnt_h > cnt_l)
Packit Service 82fcde
		{
Packit Service 82fcde
		  /* We cannot save any memory.	 So just roll both numbers
Packit Service 82fcde
		     so that the scaling factor has its highest bit set.  */
Packit Service 82fcde
Packit Service 82fcde
		  (void) __mpn_lshift (p.scale, p.scale, p.scalesize, cnt_h);
Packit Service 82fcde
		  cy = __mpn_lshift (p.frac, p.frac, p.fracsize, cnt_h);
Packit Service 82fcde
		  if (cy != 0)
Packit Service 82fcde
		    p.frac[p.fracsize++] = cy;
Packit Service 82fcde
		}
Packit Service 82fcde
	      else if (BITS_PER_MP_LIMB - cnt_h <= cnt_l)
Packit Service 82fcde
		{
Packit Service 82fcde
		  /* We can save memory by removing the trailing zero limbs
Packit Service 82fcde
		     and by packing the non-zero limbs which gain another
Packit Service 82fcde
		     free one. */
Packit Service 82fcde
Packit Service 82fcde
		  (void) __mpn_rshift (p.scale, p.scale + i, p.scalesize - i,
Packit Service 82fcde
				       BITS_PER_MP_LIMB - cnt_h);
Packit Service 82fcde
		  p.scalesize -= i + 1;
Packit Service 82fcde
		  (void) __mpn_rshift (p.frac, p.frac + i, p.fracsize - i,
Packit Service 82fcde
				       BITS_PER_MP_LIMB - cnt_h);
Packit Service 82fcde
		  p.fracsize -= p.frac[p.fracsize - i - 1] == 0 ? i + 1 : i;
Packit Service 82fcde
		}
Packit Service 82fcde
	      else
Packit Service 82fcde
		{
Packit Service 82fcde
		  /* We can only save the memory of the limbs which are zero.
Packit Service 82fcde
		     The non-zero parts occupy the same number of limbs.  */
Packit Service 82fcde
Packit Service 82fcde
		  (void) __mpn_rshift (p.scale, p.scale + (i - 1),
Packit Service 82fcde
				       p.scalesize - (i - 1),
Packit Service 82fcde
				       BITS_PER_MP_LIMB - cnt_h);
Packit Service 82fcde
		  p.scalesize -= i;
Packit Service 82fcde
		  (void) __mpn_rshift (p.frac, p.frac + (i - 1),
Packit Service 82fcde
				       p.fracsize - (i - 1),
Packit Service 82fcde
				       BITS_PER_MP_LIMB - cnt_h);
Packit Service 82fcde
		  p.fracsize -=
Packit Service 82fcde
		    p.frac[p.fracsize - (i - 1) - 1] == 0 ? i : i - 1;
Packit Service 82fcde
		}
Packit Service 82fcde
	    }
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
  else if (p.exponent < 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* |FP| < 1.0.  */
Packit Service 82fcde
      int exp10 = 0;
Packit Service 82fcde
      int explog;
Packit Service 82fcde
#if __HAVE_DISTINCT_FLOAT128
Packit Service 82fcde
      if (info->is_binary128)
Packit Service 82fcde
	explog = FLT128_MAX_10_EXP_LOG;
Packit Service 82fcde
      else
Packit Service 82fcde
	explog = LDBL_MAX_10_EXP_LOG;
Packit Service 82fcde
#else
Packit Service 82fcde
      explog = LDBL_MAX_10_EXP_LOG;
Packit Service 82fcde
#endif
Packit Service 82fcde
      const struct mp_power *powers = &_fpioconst_pow10[explog + 1];
Packit Service 82fcde
Packit Service 82fcde
      /* Now shift the input value to its right place.	*/
Packit Service 82fcde
      cy = __mpn_lshift (p.frac, fp_input, p.fracsize, to_shift);
Packit Service 82fcde
      p.frac[p.fracsize++] = cy;
Packit Service 82fcde
      assert (cy == 1 || (p.frac[p.fracsize - 2] == 0 && p.frac[0] == 0));
Packit Service 82fcde
Packit Service 82fcde
      p.expsign = 1;
Packit Service 82fcde
      p.exponent = -p.exponent;
Packit Service 82fcde
Packit Service 82fcde
      assert (powers != &_fpioconst_pow10[0]);
Packit Service 82fcde
      do
Packit Service 82fcde
	{
Packit Service 82fcde
	  --powers;
Packit Service 82fcde
Packit Service 82fcde
	  if (p.exponent >= powers->m_expo)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      int i, incr, cnt_h, cnt_l;
Packit Service 82fcde
	      mp_limb_t topval[2];
Packit Service 82fcde
Packit Service 82fcde
	      /* The __mpn_mul function expects the first argument to be
Packit Service 82fcde
		 bigger than the second.  */
Packit Service 82fcde
	      if (p.fracsize < powers->arraysize - _FPIO_CONST_OFFSET)
Packit Service 82fcde
		cy = __mpn_mul (p.tmp, &__tens[powers->arrayoff
Packit Service 82fcde
					    + _FPIO_CONST_OFFSET],
Packit Service 82fcde
				powers->arraysize - _FPIO_CONST_OFFSET,
Packit Service 82fcde
				p.frac, p.fracsize);
Packit Service 82fcde
	      else
Packit Service 82fcde
		cy = __mpn_mul (p.tmp, p.frac, p.fracsize,
Packit Service 82fcde
				&__tens[powers->arrayoff + _FPIO_CONST_OFFSET],
Packit Service 82fcde
				powers->arraysize - _FPIO_CONST_OFFSET);
Packit Service 82fcde
	      p.tmpsize = p.fracsize + powers->arraysize - _FPIO_CONST_OFFSET;
Packit Service 82fcde
	      if (cy == 0)
Packit Service 82fcde
		--p.tmpsize;
Packit Service 82fcde
Packit Service 82fcde
	      count_leading_zeros (cnt_h, p.tmp[p.tmpsize - 1]);
Packit Service 82fcde
	      incr = (p.tmpsize - p.fracsize) * BITS_PER_MP_LIMB
Packit Service 82fcde
		     + BITS_PER_MP_LIMB - 1 - cnt_h;
Packit Service 82fcde
Packit Service 82fcde
	      assert (incr <= powers->p_expo);
Packit Service 82fcde
Packit Service 82fcde
	      /* If we increased the p.exponent by exactly 3 we have to test
Packit Service 82fcde
		 for overflow.	This is done by comparing with 10 shifted
Packit Service 82fcde
		 to the right position.	 */
Packit Service 82fcde
	      if (incr == p.exponent + 3)
Packit Service 82fcde
		{
Packit Service 82fcde
		  if (cnt_h <= BITS_PER_MP_LIMB - 4)
Packit Service 82fcde
		    {
Packit Service 82fcde
		      topval[0] = 0;
Packit Service 82fcde
		      topval[1]
Packit Service 82fcde
			= ((mp_limb_t) 10) << (BITS_PER_MP_LIMB - 4 - cnt_h);
Packit Service 82fcde
		    }
Packit Service 82fcde
		  else
Packit Service 82fcde
		    {
Packit Service 82fcde
		      topval[0] = ((mp_limb_t) 10) << (BITS_PER_MP_LIMB - 4);
Packit Service 82fcde
		      topval[1] = 0;
Packit Service 82fcde
		      (void) __mpn_lshift (topval, topval, 2,
Packit Service 82fcde
					   BITS_PER_MP_LIMB - cnt_h);
Packit Service 82fcde
		    }
Packit Service 82fcde
		}
Packit Service 82fcde
Packit Service 82fcde
	      /* We have to be careful when multiplying the last factor.
Packit Service 82fcde
		 If the result is greater than 1.0 be have to test it
Packit Service 82fcde
		 against 10.0.  If it is greater or equal to 10.0 the
Packit Service 82fcde
		 multiplication was not valid.  This is because we cannot
Packit Service 82fcde
		 determine the number of bits in the result in advance.  */
Packit Service 82fcde
	      if (incr < p.exponent + 3
Packit Service 82fcde
		  || (incr == p.exponent + 3 &&
Packit Service 82fcde
		      (p.tmp[p.tmpsize - 1] < topval[1]
Packit Service 82fcde
		       || (p.tmp[p.tmpsize - 1] == topval[1]
Packit Service 82fcde
			   && p.tmp[p.tmpsize - 2] < topval[0]))))
Packit Service 82fcde
		{
Packit Service 82fcde
		  /* The factor is right.  Adapt binary and decimal
Packit Service 82fcde
		     exponents.	 */
Packit Service 82fcde
		  p.exponent -= incr;
Packit Service 82fcde
		  exp10 |= 1 << explog;
Packit Service 82fcde
Packit Service 82fcde
		  /* If this factor yields a number greater or equal to
Packit Service 82fcde
		     1.0, we must not shift the non-fractional digits down. */
Packit Service 82fcde
		  if (p.exponent < 0)
Packit Service 82fcde
		    cnt_h += -p.exponent;
Packit Service 82fcde
Packit Service 82fcde
		  /* Now we optimize the number representation.	 */
Packit Service 82fcde
		  for (i = 0; p.tmp[i] == 0; ++i);
Packit Service 82fcde
		  if (cnt_h == BITS_PER_MP_LIMB - 1)
Packit Service 82fcde
		    {
Packit Service 82fcde
		      MPN_COPY (p.frac, p.tmp + i, p.tmpsize - i);
Packit Service 82fcde
		      p.fracsize = p.tmpsize - i;
Packit Service 82fcde
		    }
Packit Service 82fcde
		  else
Packit Service 82fcde
		    {
Packit Service 82fcde
		      count_trailing_zeros (cnt_l, p.tmp[i]);
Packit Service 82fcde
Packit Service 82fcde
		      /* Now shift the numbers to their optimal position.  */
Packit Service 82fcde
		      if (i == 0 && BITS_PER_MP_LIMB - 1 - cnt_h > cnt_l)
Packit Service 82fcde
			{
Packit Service 82fcde
			  /* We cannot save any memory.	 Just roll the
Packit Service 82fcde
			     number so that the leading digit is in a
Packit Service 82fcde
			     separate limb.  */
Packit Service 82fcde
Packit Service 82fcde
			  cy = __mpn_lshift (p.frac, p.tmp, p.tmpsize,
Packit Service 82fcde
			    cnt_h + 1);
Packit Service 82fcde
			  p.fracsize = p.tmpsize + 1;
Packit Service 82fcde
			  p.frac[p.fracsize - 1] = cy;
Packit Service 82fcde
			}
Packit Service 82fcde
		      else if (BITS_PER_MP_LIMB - 1 - cnt_h <= cnt_l)
Packit Service 82fcde
			{
Packit Service 82fcde
			  (void) __mpn_rshift (p.frac, p.tmp + i, p.tmpsize - i,
Packit Service 82fcde
					       BITS_PER_MP_LIMB - 1 - cnt_h);
Packit Service 82fcde
			  p.fracsize = p.tmpsize - i;
Packit Service 82fcde
			}
Packit Service 82fcde
		      else
Packit Service 82fcde
			{
Packit Service 82fcde
			  /* We can only save the memory of the limbs which
Packit Service 82fcde
			     are zero.	The non-zero parts occupy the same
Packit Service 82fcde
			     number of limbs.  */
Packit Service 82fcde
Packit Service 82fcde
			  (void) __mpn_rshift (p.frac, p.tmp + (i - 1),
Packit Service 82fcde
					       p.tmpsize - (i - 1),
Packit Service 82fcde
					       BITS_PER_MP_LIMB - 1 - cnt_h);
Packit Service 82fcde
			  p.fracsize = p.tmpsize - (i - 1);
Packit Service 82fcde
			}
Packit Service 82fcde
		    }
Packit Service 82fcde
		}
Packit Service 82fcde
	    }
Packit Service 82fcde
	  --explog;
Packit Service 82fcde
	}
Packit Service 82fcde
      while (powers != &_fpioconst_pow10[1] && p.exponent > 0);
Packit Service 82fcde
      /* All factors but 10^-1 are tested now.	*/
Packit Service 82fcde
      if (p.exponent > 0)
Packit Service 82fcde
	{
Packit Service 82fcde
	  int cnt_l;
Packit Service 82fcde
Packit Service 82fcde
	  cy = __mpn_mul_1 (p.tmp, p.frac, p.fracsize, 10);
Packit Service 82fcde
	  p.tmpsize = p.fracsize;
Packit Service 82fcde
	  assert (cy == 0 || p.tmp[p.tmpsize - 1] < 20);
Packit Service 82fcde
Packit Service 82fcde
	  count_trailing_zeros (cnt_l, p.tmp[0]);
Packit Service 82fcde
	  if (cnt_l < MIN (4, p.exponent))
Packit Service 82fcde
	    {
Packit Service 82fcde
	      cy = __mpn_lshift (p.frac, p.tmp, p.tmpsize,
Packit Service 82fcde
				 BITS_PER_MP_LIMB - MIN (4, p.exponent));
Packit Service 82fcde
	      if (cy != 0)
Packit Service 82fcde
		p.frac[p.tmpsize++] = cy;
Packit Service 82fcde
	    }
Packit Service 82fcde
	  else
Packit Service 82fcde
	    (void) __mpn_rshift (p.frac, p.tmp, p.tmpsize, MIN (4, p.exponent));
Packit Service 82fcde
	  p.fracsize = p.tmpsize;
Packit Service 82fcde
	  exp10 |= 1;
Packit Service 82fcde
	  assert (p.frac[p.fracsize - 1] < 10);
Packit Service 82fcde
	}
Packit Service 82fcde
      p.exponent = exp10;
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
      /* This is a special case.  We don't need a factor because the
Packit Service 82fcde
	 numbers are in the range of 1.0 <= |fp| < 8.0.  We simply
Packit Service 82fcde
	 shift it to the right place and divide it by 1.0 to get the
Packit Service 82fcde
	 leading digit.	 (Of course this division is not really made.)	*/
Packit Service 82fcde
      assert (0 <= p.exponent && p.exponent < 3 &&
Packit Service 82fcde
	      p.exponent + to_shift < BITS_PER_MP_LIMB);
Packit Service 82fcde
Packit Service 82fcde
      /* Now shift the input value to its right place.	*/
Packit Service 82fcde
      cy = __mpn_lshift (p.frac, fp_input, p.fracsize, (p.exponent + to_shift));
Packit Service 82fcde
      p.frac[p.fracsize++] = cy;
Packit Service 82fcde
      p.exponent = 0;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  {
Packit Service 82fcde
    int width = info->width;
Packit Service 82fcde
    wchar_t *wstartp, *wcp;
Packit Service 82fcde
    size_t chars_needed;
Packit Service 82fcde
    int expscale;
Packit Service 82fcde
    int intdig_max, intdig_no = 0;
Packit Service 82fcde
    int fracdig_min;
Packit Service 82fcde
    int fracdig_max;
Packit Service 82fcde
    int dig_max;
Packit Service 82fcde
    int significant;
Packit Service 82fcde
    int ngroups = 0;
Packit Service 82fcde
    char spec = _tolower (info->spec);
Packit Service 82fcde
Packit Service 82fcde
    if (spec == 'e')
Packit Service 82fcde
      {
Packit Service 82fcde
	p.type = info->spec;
Packit Service 82fcde
	intdig_max = 1;
Packit Service 82fcde
	fracdig_min = fracdig_max = info->prec < 0 ? 6 : info->prec;
Packit Service 82fcde
	chars_needed = 1 + 1 + (size_t) fracdig_max + 1 + 1 + 4;
Packit Service 82fcde
	/*	       d   .	 ddd	     e	 +-  ddd  */
Packit Service 82fcde
	dig_max = INT_MAX;		/* Unlimited.  */
Packit Service 82fcde
	significant = 1;		/* Does not matter here.  */
Packit Service 82fcde
      }
Packit Service 82fcde
    else if (spec == 'f')
Packit Service 82fcde
      {
Packit Service 82fcde
	p.type = 'f';
Packit Service 82fcde
	fracdig_min = fracdig_max = info->prec < 0 ? 6 : info->prec;
Packit Service 82fcde
	dig_max = INT_MAX;		/* Unlimited.  */
Packit Service 82fcde
	significant = 1;		/* Does not matter here.  */
Packit Service 82fcde
	if (p.expsign == 0)
Packit Service 82fcde
	  {
Packit Service 82fcde
	    intdig_max = p.exponent + 1;
Packit Service 82fcde
	    /* This can be really big!	*/  /* XXX Maybe malloc if too big? */
Packit Service 82fcde
	    chars_needed = (size_t) p.exponent + 1 + 1 + (size_t) fracdig_max;
Packit Service 82fcde
	  }
Packit Service 82fcde
	else
Packit Service 82fcde
	  {
Packit Service 82fcde
	    intdig_max = 1;
Packit Service 82fcde
	    chars_needed = 1 + 1 + (size_t) fracdig_max;
Packit Service 82fcde
	  }
Packit Service 82fcde
      }
Packit Service 82fcde
    else
Packit Service 82fcde
      {
Packit Service 82fcde
	dig_max = info->prec < 0 ? 6 : (info->prec == 0 ? 1 : info->prec);
Packit Service 82fcde
	if ((p.expsign == 0 && p.exponent >= dig_max)
Packit Service 82fcde
	    || (p.expsign != 0 && p.exponent > 4))
Packit Service 82fcde
	  {
Packit Service 82fcde
	    if ('g' - 'G' == 'e' - 'E')
Packit Service 82fcde
	      p.type = 'E' + (info->spec - 'G');
Packit Service 82fcde
	    else
Packit Service 82fcde
	      p.type = isupper (info->spec) ? 'E' : 'e';
Packit Service 82fcde
	    fracdig_max = dig_max - 1;
Packit Service 82fcde
	    intdig_max = 1;
Packit Service 82fcde
	    chars_needed = 1 + 1 + (size_t) fracdig_max + 1 + 1 + 4;
Packit Service 82fcde
	  }
Packit Service 82fcde
	else
Packit Service 82fcde
	  {
Packit Service 82fcde
	    p.type = 'f';
Packit Service 82fcde
	    intdig_max = p.expsign == 0 ? p.exponent + 1 : 0;
Packit Service 82fcde
	    fracdig_max = dig_max - intdig_max;
Packit Service 82fcde
	    /* We need space for the significant digits and perhaps
Packit Service 82fcde
	       for leading zeros when < 1.0.  The number of leading
Packit Service 82fcde
	       zeros can be as many as would be required for
Packit Service 82fcde
	       exponential notation with a negative two-digit
Packit Service 82fcde
	       p.exponent, which is 4.  */
Packit Service 82fcde
	    chars_needed = (size_t) dig_max + 1 + 4;
Packit Service 82fcde
	  }
Packit Service 82fcde
	fracdig_min = info->alt ? fracdig_max : 0;
Packit Service 82fcde
	significant = 0;		/* We count significant digits.	 */
Packit Service 82fcde
      }
Packit Service 82fcde
Packit Service 82fcde
    if (grouping)
Packit Service 82fcde
      {
Packit Service 82fcde
	/* Guess the number of groups we will make, and thus how
Packit Service 82fcde
	   many spaces we need for separator characters.  */
Packit Service 82fcde
	ngroups = __guess_grouping (intdig_max, grouping);
Packit Service 82fcde
	/* Allocate one more character in case rounding increases the
Packit Service 82fcde
	   number of groups.  */
Packit Service 82fcde
	chars_needed += ngroups + 1;
Packit Service 82fcde
      }
Packit Service 82fcde
Packit Service 82fcde
    /* Allocate buffer for output.  We need two more because while rounding
Packit Service 82fcde
       it is possible that we need two more characters in front of all the
Packit Service 82fcde
       other output.  If the amount of memory we have to allocate is too
Packit Service 82fcde
       large use `malloc' instead of `alloca'.  */
Packit Service 82fcde
    if (__builtin_expect (chars_needed >= (size_t) -1 / sizeof (wchar_t) - 2
Packit Service 82fcde
			  || chars_needed < fracdig_max, 0))
Packit Service 82fcde
      {
Packit Service 82fcde
	/* Some overflow occurred.  */
Packit Service 82fcde
	__set_errno (ERANGE);
Packit Service 82fcde
	return -1;
Packit Service 82fcde
      }
Packit Service 82fcde
    size_t wbuffer_to_alloc = (2 + chars_needed) * sizeof (wchar_t);
Packit Service 82fcde
    buffer_malloced = ! __libc_use_alloca (wbuffer_to_alloc);
Packit Service 82fcde
    if (__builtin_expect (buffer_malloced, 0))
Packit Service 82fcde
      {
Packit Service 82fcde
	wbuffer = (wchar_t *) malloc (wbuffer_to_alloc);
Packit Service 82fcde
	if (wbuffer == NULL)
Packit Service 82fcde
	  /* Signal an error to the caller.  */
Packit Service 82fcde
	  return -1;
Packit Service 82fcde
      }
Packit Service 82fcde
    else
Packit Service 82fcde
      wbuffer = (wchar_t *) alloca (wbuffer_to_alloc);
Packit Service 82fcde
    wcp = wstartp = wbuffer + 2;	/* Let room for rounding.  */
Packit Service 82fcde
Packit Service 82fcde
    /* Do the real work: put digits in allocated buffer.  */
Packit Service 82fcde
    if (p.expsign == 0 || p.type != 'f')
Packit Service 82fcde
      {
Packit Service 82fcde
	assert (p.expsign == 0 || intdig_max == 1);
Packit Service 82fcde
	while (intdig_no < intdig_max)
Packit Service 82fcde
	  {
Packit Service 82fcde
	    ++intdig_no;
Packit Service 82fcde
	    *wcp++ = hack_digit (&p);
Packit Service 82fcde
	  }
Packit Service 82fcde
	significant = 1;
Packit Service 82fcde
	if (info->alt
Packit Service 82fcde
	    || fracdig_min > 0
Packit Service 82fcde
	    || (fracdig_max > 0 && (p.fracsize > 1 || p.frac[0] != 0)))
Packit Service 82fcde
	  *wcp++ = decimalwc;
Packit Service 82fcde
      }
Packit Service 82fcde
    else
Packit Service 82fcde
      {
Packit Service 82fcde
	/* |fp| < 1.0 and the selected p.type is 'f', so put "0."
Packit Service 82fcde
	   in the buffer.  */
Packit Service 82fcde
	*wcp++ = L'0';
Packit Service 82fcde
	--p.exponent;
Packit Service 82fcde
	*wcp++ = decimalwc;
Packit Service 82fcde
      }
Packit Service 82fcde
Packit Service 82fcde
    /* Generate the needed number of fractional digits.	 */
Packit Service 82fcde
    int fracdig_no = 0;
Packit Service 82fcde
    int added_zeros = 0;
Packit Service 82fcde
    while (fracdig_no < fracdig_min + added_zeros
Packit Service 82fcde
	   || (fracdig_no < fracdig_max && (p.fracsize > 1 || p.frac[0] != 0)))
Packit Service 82fcde
      {
Packit Service 82fcde
	++fracdig_no;
Packit Service 82fcde
	*wcp = hack_digit (&p);
Packit Service 82fcde
	if (*wcp++ != L'0')
Packit Service 82fcde
	  significant = 1;
Packit Service 82fcde
	else if (significant == 0)
Packit Service 82fcde
	  {
Packit Service 82fcde
	    ++fracdig_max;
Packit Service 82fcde
	    if (fracdig_min > 0)
Packit Service 82fcde
	      ++added_zeros;
Packit Service 82fcde
	  }
Packit Service 82fcde
      }
Packit Service 82fcde
Packit Service 82fcde
    /* Do rounding.  */
Packit Service 82fcde
    wchar_t last_digit = wcp[-1] != decimalwc ? wcp[-1] : wcp[-2];
Packit Service 82fcde
    wchar_t next_digit = hack_digit (&p);
Packit Service 82fcde
    bool more_bits;
Packit Service 82fcde
    if (next_digit != L'0' && next_digit != L'5')
Packit Service 82fcde
      more_bits = true;
Packit Service 82fcde
    else if (p.fracsize == 1 && p.frac[0] == 0)
Packit Service 82fcde
      /* Rest of the number is zero.  */
Packit Service 82fcde
      more_bits = false;
Packit Service 82fcde
    else if (p.scalesize == 0)
Packit Service 82fcde
      {
Packit Service 82fcde
	/* Here we have to see whether all limbs are zero since no
Packit Service 82fcde
	   normalization happened.  */
Packit Service 82fcde
	size_t lcnt = p.fracsize;
Packit Service 82fcde
	while (lcnt >= 1 && p.frac[lcnt - 1] == 0)
Packit Service 82fcde
	  --lcnt;
Packit Service 82fcde
	more_bits = lcnt > 0;
Packit Service 82fcde
      }
Packit Service 82fcde
    else
Packit Service 82fcde
      more_bits = true;
Packit Service 82fcde
    int rounding_mode = get_rounding_mode ();
Packit Service 82fcde
    if (round_away (is_neg, (last_digit - L'0') & 1, next_digit >= L'5',
Packit Service 82fcde
		    more_bits, rounding_mode))
Packit Service 82fcde
      {
Packit Service 82fcde
	wchar_t *wtp = wcp;
Packit Service 82fcde
Packit Service 82fcde
	if (fracdig_no > 0)
Packit Service 82fcde
	  {
Packit Service 82fcde
	    /* Process fractional digits.  Terminate if not rounded or
Packit Service 82fcde
	       radix character is reached.  */
Packit Service 82fcde
	    int removed = 0;
Packit Service 82fcde
	    while (*--wtp != decimalwc && *wtp == L'9')
Packit Service 82fcde
	      {
Packit Service 82fcde
		*wtp = L'0';
Packit Service 82fcde
		++removed;
Packit Service 82fcde
	      }
Packit Service 82fcde
	    if (removed == fracdig_min && added_zeros > 0)
Packit Service 82fcde
	      --added_zeros;
Packit Service 82fcde
	    if (*wtp != decimalwc)
Packit Service 82fcde
	      /* Round up.  */
Packit Service 82fcde
	      (*wtp)++;
Packit Service 82fcde
	    else if (__builtin_expect (spec == 'g' && p.type == 'f' && info->alt
Packit Service 82fcde
				       && wtp == wstartp + 1
Packit Service 82fcde
				       && wstartp[0] == L'0',
Packit Service 82fcde
				       0))
Packit Service 82fcde
	      /* This is a special case: the rounded number is 1.0,
Packit Service 82fcde
		 the format is 'g' or 'G', and the alternative format
Packit Service 82fcde
		 is selected.  This means the result must be "1.".  */
Packit Service 82fcde
	      --added_zeros;
Packit Service 82fcde
	  }
Packit Service 82fcde
Packit Service 82fcde
	if (fracdig_no == 0 || *wtp == decimalwc)
Packit Service 82fcde
	  {
Packit Service 82fcde
	    /* Round the integer digits.  */
Packit Service 82fcde
	    if (*(wtp - 1) == decimalwc)
Packit Service 82fcde
	      --wtp;
Packit Service 82fcde
Packit Service 82fcde
	    while (--wtp >= wstartp && *wtp == L'9')
Packit Service 82fcde
	      *wtp = L'0';
Packit Service 82fcde
Packit Service 82fcde
	    if (wtp >= wstartp)
Packit Service 82fcde
	      /* Round up.  */
Packit Service 82fcde
	      (*wtp)++;
Packit Service 82fcde
	    else
Packit Service 82fcde
	      /* It is more critical.  All digits were 9's.  */
Packit Service 82fcde
	      {
Packit Service 82fcde
		if (p.type != 'f')
Packit Service 82fcde
		  {
Packit Service 82fcde
		    *wstartp = '1';
Packit Service 82fcde
		    p.exponent += p.expsign == 0 ? 1 : -1;
Packit Service 82fcde
Packit Service 82fcde
		    /* The above p.exponent adjustment could lead to 1.0e-00,
Packit Service 82fcde
		       e.g. for 0.999999999.  Make sure p.exponent 0 always
Packit Service 82fcde
		       uses + sign.  */
Packit Service 82fcde
		    if (p.exponent == 0)
Packit Service 82fcde
		      p.expsign = 0;
Packit Service 82fcde
		  }
Packit Service 82fcde
		else if (intdig_no == dig_max)
Packit Service 82fcde
		  {
Packit Service 82fcde
		    /* This is the case where for p.type %g the number fits
Packit Service 82fcde
		       really in the range for %f output but after rounding
Packit Service 82fcde
		       the number of digits is too big.	 */
Packit Service 82fcde
		    *--wstartp = decimalwc;
Packit Service 82fcde
		    *--wstartp = L'1';
Packit Service 82fcde
Packit Service 82fcde
		    if (info->alt || fracdig_no > 0)
Packit Service 82fcde
		      {
Packit Service 82fcde
			/* Overwrite the old radix character.  */
Packit Service 82fcde
			wstartp[intdig_no + 2] = L'0';
Packit Service 82fcde
			++fracdig_no;
Packit Service 82fcde
		      }
Packit Service 82fcde
Packit Service 82fcde
		    fracdig_no += intdig_no;
Packit Service 82fcde
		    intdig_no = 1;
Packit Service 82fcde
		    fracdig_max = intdig_max - intdig_no;
Packit Service 82fcde
		    ++p.exponent;
Packit Service 82fcde
		    /* Now we must print the p.exponent.	*/
Packit Service 82fcde
		    p.type = isupper (info->spec) ? 'E' : 'e';
Packit Service 82fcde
		  }
Packit Service 82fcde
		else
Packit Service 82fcde
		  {
Packit Service 82fcde
		    /* We can simply add another another digit before the
Packit Service 82fcde
		       radix.  */
Packit Service 82fcde
		    *--wstartp = L'1';
Packit Service 82fcde
		    ++intdig_no;
Packit Service 82fcde
		  }
Packit Service 82fcde
Packit Service 82fcde
		/* While rounding the number of digits can change.
Packit Service 82fcde
		   If the number now exceeds the limits remove some
Packit Service 82fcde
		   fractional digits.  */
Packit Service 82fcde
		if (intdig_no + fracdig_no > dig_max)
Packit Service 82fcde
		  {
Packit Service 82fcde
		    wcp -= intdig_no + fracdig_no - dig_max;
Packit Service 82fcde
		    fracdig_no -= intdig_no + fracdig_no - dig_max;
Packit Service 82fcde
		  }
Packit Service 82fcde
	      }
Packit Service 82fcde
	  }
Packit Service 82fcde
      }
Packit Service 82fcde
Packit Service 82fcde
    /* Now remove unnecessary '0' at the end of the string.  */
Packit Service 82fcde
    while (fracdig_no > fracdig_min + added_zeros && *(wcp - 1) == L'0')
Packit Service 82fcde
      {
Packit Service 82fcde
	--wcp;
Packit Service 82fcde
	--fracdig_no;
Packit Service 82fcde
      }
Packit Service 82fcde
    /* If we eliminate all fractional digits we perhaps also can remove
Packit Service 82fcde
       the radix character.  */
Packit Service 82fcde
    if (fracdig_no == 0 && !info->alt && *(wcp - 1) == decimalwc)
Packit Service 82fcde
      --wcp;
Packit Service 82fcde
Packit Service 82fcde
    if (grouping)
Packit Service 82fcde
      {
Packit Service 82fcde
	/* Rounding might have changed the number of groups.  We allocated
Packit Service 82fcde
	   enough memory but we need here the correct number of groups.  */
Packit Service 82fcde
	if (intdig_no != intdig_max)
Packit Service 82fcde
	  ngroups = __guess_grouping (intdig_no, grouping);
Packit Service 82fcde
Packit Service 82fcde
	/* Add in separator characters, overwriting the same buffer.  */
Packit Service 82fcde
	wcp = group_number (wstartp, wcp, intdig_no, grouping, thousands_sepwc,
Packit Service 82fcde
			    ngroups);
Packit Service 82fcde
      }
Packit Service 82fcde
Packit Service 82fcde
    /* Write the p.exponent if it is needed.  */
Packit Service 82fcde
    if (p.type != 'f')
Packit Service 82fcde
      {
Packit Service 82fcde
	if (__glibc_unlikely (p.expsign != 0 && p.exponent == 4 && spec == 'g'))
Packit Service 82fcde
	  {
Packit Service 82fcde
	    /* This is another special case.  The p.exponent of the number is
Packit Service 82fcde
	       really smaller than -4, which requires the 'e'/'E' format.
Packit Service 82fcde
	       But after rounding the number has an p.exponent of -4.  */
Packit Service 82fcde
	    assert (wcp >= wstartp + 1);
Packit Service 82fcde
	    assert (wstartp[0] == L'1');
Packit Service 82fcde
	    __wmemcpy (wstartp, L"0.0001", 6);
Packit Service 82fcde
	    wstartp[1] = decimalwc;
Packit Service 82fcde
	    if (wcp >= wstartp + 2)
Packit Service 82fcde
	      {
Packit Service 82fcde
		__wmemset (wstartp + 6, L'0', wcp - (wstartp + 2));
Packit Service 82fcde
		wcp += 4;
Packit Service 82fcde
	      }
Packit Service 82fcde
	    else
Packit Service 82fcde
	      wcp += 5;
Packit Service 82fcde
	  }
Packit Service 82fcde
	else
Packit Service 82fcde
	  {
Packit Service 82fcde
	    *wcp++ = (wchar_t) p.type;
Packit Service 82fcde
	    *wcp++ = p.expsign ? L'-' : L'+';
Packit Service 82fcde
Packit Service 82fcde
	    /* Find the magnitude of the p.exponent.	*/
Packit Service 82fcde
	    expscale = 10;
Packit Service 82fcde
	    while (expscale <= p.exponent)
Packit Service 82fcde
	      expscale *= 10;
Packit Service 82fcde
Packit Service 82fcde
	    if (p.exponent < 10)
Packit Service 82fcde
	      /* Exponent always has at least two digits.  */
Packit Service 82fcde
	      *wcp++ = L'0';
Packit Service 82fcde
	    else
Packit Service 82fcde
	      do
Packit Service 82fcde
		{
Packit Service 82fcde
		  expscale /= 10;
Packit Service 82fcde
		  *wcp++ = L'0' + (p.exponent / expscale);
Packit Service 82fcde
		  p.exponent %= expscale;
Packit Service 82fcde
		}
Packit Service 82fcde
	      while (expscale > 10);
Packit Service 82fcde
	    *wcp++ = L'0' + p.exponent;
Packit Service 82fcde
	  }
Packit Service 82fcde
      }
Packit Service 82fcde
Packit Service 82fcde
    /* Compute number of characters which must be filled with the padding
Packit Service 82fcde
       character.  */
Packit Service 82fcde
    if (is_neg || info->showsign || info->space)
Packit Service 82fcde
      --width;
Packit Service 82fcde
    width -= wcp - wstartp;
Packit Service 82fcde
Packit Service 82fcde
    if (!info->left && info->pad != '0' && width > 0)
Packit Service 82fcde
      PADN (info->pad, width);
Packit Service 82fcde
Packit Service 82fcde
    if (is_neg)
Packit Service 82fcde
      outchar ('-');
Packit Service 82fcde
    else if (info->showsign)
Packit Service 82fcde
      outchar ('+');
Packit Service 82fcde
    else if (info->space)
Packit Service 82fcde
      outchar (' ');
Packit Service 82fcde
Packit Service 82fcde
    if (!info->left && info->pad == '0' && width > 0)
Packit Service 82fcde
      PADN ('0', width);
Packit Service 82fcde
Packit Service 82fcde
    {
Packit Service 82fcde
      char *buffer = NULL;
Packit Service 82fcde
      char *buffer_end = NULL;
Packit Service 82fcde
      char *cp = NULL;
Packit Service 82fcde
      char *tmpptr;
Packit Service 82fcde
Packit Service 82fcde
      if (! wide)
Packit Service 82fcde
	{
Packit Service 82fcde
	  /* Create the single byte string.  */
Packit Service 82fcde
	  size_t decimal_len;
Packit Service 82fcde
	  size_t thousands_sep_len;
Packit Service 82fcde
	  wchar_t *copywc;
Packit Service 82fcde
	  size_t factor;
Packit Service 82fcde
	  if (info->i18n)
Packit Service 82fcde
	    factor = _nl_lookup_word (loc, LC_CTYPE, _NL_CTYPE_MB_CUR_MAX);
Packit Service 82fcde
	  else
Packit Service 82fcde
	    factor = 1;
Packit Service 82fcde
Packit Service 82fcde
	  decimal_len = strlen (decimal);
Packit Service 82fcde
Packit Service 82fcde
	  if (thousands_sep == NULL)
Packit Service 82fcde
	    thousands_sep_len = 0;
Packit Service 82fcde
	  else
Packit Service 82fcde
	    thousands_sep_len = strlen (thousands_sep);
Packit Service 82fcde
Packit Service 82fcde
	  size_t nbuffer = (2 + chars_needed * factor + decimal_len
Packit Service 82fcde
			    + ngroups * thousands_sep_len);
Packit Service 82fcde
	  if (__glibc_unlikely (buffer_malloced))
Packit Service 82fcde
	    {
Packit Service 82fcde
	      buffer = (char *) malloc (nbuffer);
Packit Service 82fcde
	      if (buffer == NULL)
Packit Service 82fcde
		{
Packit Service 82fcde
		  /* Signal an error to the caller.  */
Packit Service 82fcde
		  free (wbuffer);
Packit Service 82fcde
		  return -1;
Packit Service 82fcde
		}
Packit Service 82fcde
	    }
Packit Service 82fcde
	  else
Packit Service 82fcde
	    buffer = (char *) alloca (nbuffer);
Packit Service 82fcde
	  buffer_end = buffer + nbuffer;
Packit Service 82fcde
Packit Service 82fcde
	  /* Now copy the wide character string.  Since the character
Packit Service 82fcde
	     (except for the decimal point and thousands separator) must
Packit Service 82fcde
	     be coming from the ASCII range we can esily convert the
Packit Service 82fcde
	     string without mapping tables.  */
Packit Service 82fcde
	  for (cp = buffer, copywc = wstartp; copywc < wcp; ++copywc)
Packit Service 82fcde
	    if (*copywc == decimalwc)
Packit Service 82fcde
	      cp = (char *) __mempcpy (cp, decimal, decimal_len);
Packit Service 82fcde
	    else if (*copywc == thousands_sepwc)
Packit Service 82fcde
	      cp = (char *) __mempcpy (cp, thousands_sep, thousands_sep_len);
Packit Service 82fcde
	    else
Packit Service 82fcde
	      *cp++ = (char) *copywc;
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      tmpptr = buffer;
Packit Service 82fcde
      if (__glibc_unlikely (info->i18n))
Packit Service 82fcde
	{
Packit Service 82fcde
#ifdef COMPILE_WPRINTF
Packit Service 82fcde
	  wstartp = _i18n_number_rewrite (wstartp, wcp,
Packit Service 82fcde
					  wbuffer + wbuffer_to_alloc);
Packit Service 82fcde
	  wcp = wbuffer + wbuffer_to_alloc;
Packit Service 82fcde
	  assert ((uintptr_t) wbuffer <= (uintptr_t) wstartp);
Packit Service 82fcde
	  assert ((uintptr_t) wstartp
Packit Service 82fcde
		  < (uintptr_t) wbuffer + wbuffer_to_alloc);
Packit Service 82fcde
#else
Packit Service 82fcde
	  tmpptr = _i18n_number_rewrite (tmpptr, cp, buffer_end);
Packit Service 82fcde
	  cp = buffer_end;
Packit Service 82fcde
	  assert ((uintptr_t) buffer <= (uintptr_t) tmpptr);
Packit Service 82fcde
	  assert ((uintptr_t) tmpptr < (uintptr_t) buffer_end);
Packit Service 82fcde
#endif
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      PRINT (tmpptr, wstartp, wide ? wcp - wstartp : cp - tmpptr);
Packit Service 82fcde
Packit Service 82fcde
      /* Free the memory if necessary.  */
Packit Service 82fcde
      if (__glibc_unlikely (buffer_malloced))
Packit Service 82fcde
	{
Packit Service 82fcde
	  free (buffer);
Packit Service 82fcde
	  free (wbuffer);
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
    if (info->left && width > 0)
Packit Service 82fcde
      PADN (info->pad, width);
Packit Service 82fcde
  }
Packit Service 82fcde
  return done;
Packit Service 82fcde
}
Packit Service 82fcde
libc_hidden_def (__printf_fp_l)
Packit Service 82fcde
Packit Service 82fcde
int
Packit Service 82fcde
___printf_fp (FILE *fp, const struct printf_info *info,
Packit Service 82fcde
	      const void *const *args)
Packit Service 82fcde
{
Packit Service 82fcde
  return __printf_fp_l (fp, _NL_CURRENT_LOCALE, info, args);
Packit Service 82fcde
}
Packit Service 82fcde
ldbl_hidden_def (___printf_fp, __printf_fp)
Packit Service 82fcde
ldbl_strong_alias (___printf_fp, __printf_fp)
Packit Service 82fcde
Packit Service 82fcde

Packit Service 82fcde
/* Return the number of extra grouping characters that will be inserted
Packit Service 82fcde
   into a number with INTDIG_MAX integer digits.  */
Packit Service 82fcde
Packit Service 82fcde
unsigned int
Packit Service 82fcde
__guess_grouping (unsigned int intdig_max, const char *grouping)
Packit Service 82fcde
{
Packit Service 82fcde
  unsigned int groups;
Packit Service 82fcde
Packit Service 82fcde
  /* We treat all negative values like CHAR_MAX.  */
Packit Service 82fcde
Packit Service 82fcde
  if (*grouping == CHAR_MAX || *grouping <= 0)
Packit Service 82fcde
    /* No grouping should be done.  */
Packit Service 82fcde
    return 0;
Packit Service 82fcde
Packit Service 82fcde
  groups = 0;
Packit Service 82fcde
  while (intdig_max > (unsigned int) *grouping)
Packit Service 82fcde
    {
Packit Service 82fcde
      ++groups;
Packit Service 82fcde
      intdig_max -= *grouping++;
Packit Service 82fcde
Packit Service 82fcde
      if (*grouping == CHAR_MAX
Packit Service 82fcde
#if CHAR_MIN < 0
Packit Service 82fcde
	  || *grouping < 0
Packit Service 82fcde
#endif
Packit Service 82fcde
	  )
Packit Service 82fcde
	/* No more grouping should be done.  */
Packit Service 82fcde
	break;
Packit Service 82fcde
      else if (*grouping == 0)
Packit Service 82fcde
	{
Packit Service 82fcde
	  /* Same grouping repeats.  */
Packit Service 82fcde
	  groups += (intdig_max - 1) / grouping[-1];
Packit Service 82fcde
	  break;
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  return groups;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Group the INTDIG_NO integer digits of the number in [BUF,BUFEND).
Packit Service 82fcde
   There is guaranteed enough space past BUFEND to extend it.
Packit Service 82fcde
   Return the new end of buffer.  */
Packit Service 82fcde
Packit Service 82fcde
static wchar_t *
Packit Service 82fcde
group_number (wchar_t *buf, wchar_t *bufend, unsigned int intdig_no,
Packit Service 82fcde
	      const char *grouping, wchar_t thousands_sep, int ngroups)
Packit Service 82fcde
{
Packit Service 82fcde
  wchar_t *p;
Packit Service 82fcde
Packit Service 82fcde
  if (ngroups == 0)
Packit Service 82fcde
    return bufend;
Packit Service 82fcde
Packit Service 82fcde
  /* Move the fractional part down.  */
Packit Service 82fcde
  __wmemmove (buf + intdig_no + ngroups, buf + intdig_no,
Packit Service 82fcde
	      bufend - (buf + intdig_no));
Packit Service 82fcde
Packit Service 82fcde
  p = buf + intdig_no + ngroups - 1;
Packit Service 82fcde
  do
Packit Service 82fcde
    {
Packit Service 82fcde
      unsigned int len = *grouping++;
Packit Service 82fcde
      do
Packit Service 82fcde
	*p-- = buf[--intdig_no];
Packit Service 82fcde
      while (--len > 0);
Packit Service 82fcde
      *p-- = thousands_sep;
Packit Service 82fcde
Packit Service 82fcde
      if (*grouping == CHAR_MAX
Packit Service 82fcde
#if CHAR_MIN < 0
Packit Service 82fcde
	  || *grouping < 0
Packit Service 82fcde
#endif
Packit Service 82fcde
	  )
Packit Service 82fcde
	/* No more grouping should be done.  */
Packit Service 82fcde
	break;
Packit Service 82fcde
      else if (*grouping == 0)
Packit Service 82fcde
	/* Same grouping repeats.  */
Packit Service 82fcde
	--grouping;
Packit Service 82fcde
    } while (intdig_no > (unsigned int) *grouping);
Packit Service 82fcde
Packit Service 82fcde
  /* Copy the remaining ungrouped digits.  */
Packit Service 82fcde
  do
Packit Service 82fcde
    *p-- = buf[--intdig_no];
Packit Service 82fcde
  while (p > buf);
Packit Service 82fcde
Packit Service 82fcde
  return bufend + ngroups;
Packit Service 82fcde
}