105436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* vsprintf with automatic memory allocation.
205436638acc7c010349a69c3395f1a57c642dc62Ying Wang   Copyright (C) 1999, 2002-2012 Free Software Foundation, Inc.
305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
405436638acc7c010349a69c3395f1a57c642dc62Ying Wang   This program is free software; you can redistribute it and/or modify
505436638acc7c010349a69c3395f1a57c642dc62Ying Wang   it under the terms of the GNU General Public License as published by
605436638acc7c010349a69c3395f1a57c642dc62Ying Wang   the Free Software Foundation; either version 3, or (at your option)
705436638acc7c010349a69c3395f1a57c642dc62Ying Wang   any later version.
805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
905436638acc7c010349a69c3395f1a57c642dc62Ying Wang   This program is distributed in the hope that it will be useful,
1005436638acc7c010349a69c3395f1a57c642dc62Ying Wang   but WITHOUT ANY WARRANTY; without even the implied warranty of
1105436638acc7c010349a69c3395f1a57c642dc62Ying Wang   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1205436638acc7c010349a69c3395f1a57c642dc62Ying Wang   GNU General Public License for more details.
1305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
1405436638acc7c010349a69c3395f1a57c642dc62Ying Wang   You should have received a copy of the GNU General Public License along
1505436638acc7c010349a69c3395f1a57c642dc62Ying Wang   with this program; if not, see <http://www.gnu.org/licenses/>.  */
1605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
1705436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* This file can be parametrized with the following macros:
1805436638acc7c010349a69c3395f1a57c642dc62Ying Wang     VASNPRINTF         The name of the function being defined.
1905436638acc7c010349a69c3395f1a57c642dc62Ying Wang     FCHAR_T            The element type of the format string.
2005436638acc7c010349a69c3395f1a57c642dc62Ying Wang     DCHAR_T            The element type of the destination (result) string.
2105436638acc7c010349a69c3395f1a57c642dc62Ying Wang     FCHAR_T_ONLY_ASCII Set to 1 to enable verification that all characters
2205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        in the format string are ASCII. MUST be set if
2305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        FCHAR_T and DCHAR_T are not the same type.
2405436638acc7c010349a69c3395f1a57c642dc62Ying Wang     DIRECTIVE          Structure denoting a format directive.
2505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        Depends on FCHAR_T.
2605436638acc7c010349a69c3395f1a57c642dc62Ying Wang     DIRECTIVES         Structure denoting the set of format directives of a
2705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        format string.  Depends on FCHAR_T.
2805436638acc7c010349a69c3395f1a57c642dc62Ying Wang     PRINTF_PARSE       Function that parses a format string.
2905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        Depends on FCHAR_T.
3005436638acc7c010349a69c3395f1a57c642dc62Ying Wang     DCHAR_CPY          memcpy like function for DCHAR_T[] arrays.
3105436638acc7c010349a69c3395f1a57c642dc62Ying Wang     DCHAR_SET          memset like function for DCHAR_T[] arrays.
3205436638acc7c010349a69c3395f1a57c642dc62Ying Wang     DCHAR_MBSNLEN      mbsnlen like function for DCHAR_T[] arrays.
3305436638acc7c010349a69c3395f1a57c642dc62Ying Wang     SNPRINTF           The system's snprintf (or similar) function.
3405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        This may be either snprintf or swprintf.
3505436638acc7c010349a69c3395f1a57c642dc62Ying Wang     TCHAR_T            The element type of the argument and result string
3605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        of the said SNPRINTF function.  This may be either
3705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        char or wchar_t.  The code exploits that
3805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        sizeof (TCHAR_T) | sizeof (DCHAR_T) and
3905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        alignof (TCHAR_T) <= alignof (DCHAR_T).
4005436638acc7c010349a69c3395f1a57c642dc62Ying Wang     DCHAR_IS_TCHAR     Set to 1 if DCHAR_T and TCHAR_T are the same type.
4105436638acc7c010349a69c3395f1a57c642dc62Ying Wang     DCHAR_CONV_FROM_ENCODING A function to convert from char[] to DCHAR[].
4205436638acc7c010349a69c3395f1a57c642dc62Ying Wang     DCHAR_IS_UINT8_T   Set to 1 if DCHAR_T is uint8_t.
4305436638acc7c010349a69c3395f1a57c642dc62Ying Wang     DCHAR_IS_UINT16_T  Set to 1 if DCHAR_T is uint16_t.
4405436638acc7c010349a69c3395f1a57c642dc62Ying Wang     DCHAR_IS_UINT32_T  Set to 1 if DCHAR_T is uint32_t.  */
4505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
4605436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Tell glibc's <stdio.h> to provide a prototype for snprintf().
4705436638acc7c010349a69c3395f1a57c642dc62Ying Wang   This must come before <config.h> because <config.h> may include
4805436638acc7c010349a69c3395f1a57c642dc62Ying Wang   <features.h>, and once <features.h> has been included, it's too late.  */
4905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#ifndef _GNU_SOURCE
5005436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define _GNU_SOURCE    1
5105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
5205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
5305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#ifndef VASNPRINTF
5405436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include <config.h>
5505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
5605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#ifndef IN_LIBINTL
5705436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include <alloca.h>
5805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
5905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
6005436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Specification.  */
6105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#ifndef VASNPRINTF
6205436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if WIDE_CHAR_VERSION
6305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  include "vasnwprintf.h"
6405436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else
6505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  include "vasnprintf.h"
6605436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
6705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
6805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
6905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <locale.h>     /* localeconv() */
7005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <stdio.h>      /* snprintf(), sprintf() */
7105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <stdlib.h>     /* abort(), malloc(), realloc(), free() */
7205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <string.h>     /* memcpy(), strlen() */
7305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <errno.h>      /* errno */
7405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <limits.h>     /* CHAR_BIT */
7505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <float.h>      /* DBL_MAX_EXP, LDBL_MAX_EXP */
7605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if HAVE_NL_LANGINFO
7705436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include <langinfo.h>
7805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
7905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#ifndef VASNPRINTF
8005436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if WIDE_CHAR_VERSION
8105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  include "wprintf-parse.h"
8205436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else
8305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  include "printf-parse.h"
8405436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
8505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
8605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
8705436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Checked size_t computations.  */
8805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include "xsize.h"
8905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
9005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include "verify.h"
9105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
9205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if (NEED_PRINTF_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL
9305436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include <math.h>
9405436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include "float+.h"
9505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
9605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
9705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if (NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL
9805436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include <math.h>
9905436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include "isnand-nolibm.h"
10005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
10105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
10205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE) && !defined IN_LIBINTL
10305436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include <math.h>
10405436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include "isnanl-nolibm.h"
10505436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include "fpucw.h"
10605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
10705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
10805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL
10905436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include <math.h>
11005436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include "isnand-nolibm.h"
11105436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include "printf-frexp.h"
11205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
11305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
11405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL
11505436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include <math.h>
11605436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include "isnanl-nolibm.h"
11705436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include "printf-frexpl.h"
11805436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include "fpucw.h"
11905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
12005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
12105436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Default parameters.  */
12205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#ifndef VASNPRINTF
12305436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if WIDE_CHAR_VERSION
12405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  define VASNPRINTF vasnwprintf
12505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  define FCHAR_T wchar_t
12605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  define DCHAR_T wchar_t
12705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  define TCHAR_T wchar_t
12805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  define DCHAR_IS_TCHAR 1
12905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  define DIRECTIVE wchar_t_directive
13005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  define DIRECTIVES wchar_t_directives
13105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  define PRINTF_PARSE wprintf_parse
13205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  define DCHAR_CPY wmemcpy
13305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  define DCHAR_SET wmemset
13405436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else
13505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  define VASNPRINTF vasnprintf
13605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  define FCHAR_T char
13705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  define DCHAR_T char
13805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  define TCHAR_T char
13905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  define DCHAR_IS_TCHAR 1
14005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  define DIRECTIVE char_directive
14105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  define DIRECTIVES char_directives
14205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  define PRINTF_PARSE printf_parse
14305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  define DCHAR_CPY memcpy
14405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  define DCHAR_SET memset
14505436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
14605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
14705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if WIDE_CHAR_VERSION
14805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* TCHAR_T is wchar_t.  */
14905436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define USE_SNPRINTF 1
15005436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if HAVE_DECL__SNWPRINTF
15105436638acc7c010349a69c3395f1a57c642dc62Ying Wang   /* On Windows, the function swprintf() has a different signature than
15205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      on Unix; we use the function _snwprintf() or - on mingw - snwprintf()
15305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      instead.  The mingw function snwprintf() has fewer bugs than the
15405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      MSVCRT function _snwprintf(), so prefer that.  */
15505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if defined __MINGW32__
15605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   define SNPRINTF snwprintf
15705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  else
15805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   define SNPRINTF _snwprintf
15905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
16005436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else
16105436638acc7c010349a69c3395f1a57c642dc62Ying Wang   /* Unix.  */
16205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  define SNPRINTF swprintf
16305436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
16405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#else
16505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* TCHAR_T is char.  */
16605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Use snprintf if it exists under the name 'snprintf' or '_snprintf'.
16705436638acc7c010349a69c3395f1a57c642dc62Ying Wang     But don't use it on BeOS, since BeOS snprintf produces no output if the
16805436638acc7c010349a69c3395f1a57c642dc62Ying Wang     size argument is >= 0x3000000.
16905436638acc7c010349a69c3395f1a57c642dc62Ying Wang     Also don't use it on Linux libc5, since there snprintf with size = 1
17005436638acc7c010349a69c3395f1a57c642dc62Ying Wang     writes any output without bounds, like sprintf.  */
17105436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF) && !defined __BEOS__ && !(__GNU_LIBRARY__ == 1)
17205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  define USE_SNPRINTF 1
17305436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else
17405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  define USE_SNPRINTF 0
17505436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
17605436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if HAVE_DECL__SNPRINTF
17705436638acc7c010349a69c3395f1a57c642dc62Ying Wang   /* Windows.  The mingw function snprintf() has fewer bugs than the MSVCRT
17805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      function _snprintf(), so prefer that.  */
17905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if defined __MINGW32__
18005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   define SNPRINTF snprintf
18105436638acc7c010349a69c3395f1a57c642dc62Ying Wang    /* Here we need to call the native snprintf, not rpl_snprintf.  */
18205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   undef snprintf
18305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  else
18405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   define SNPRINTF _snprintf
18505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
18605436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else
18705436638acc7c010349a69c3395f1a57c642dc62Ying Wang   /* Unix.  */
18805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  define SNPRINTF snprintf
18905436638acc7c010349a69c3395f1a57c642dc62Ying Wang   /* Here we need to call the native snprintf, not rpl_snprintf.  */
19005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  undef snprintf
19105436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
19205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
19305436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Here we need to call the native sprintf, not rpl_sprintf.  */
19405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#undef sprintf
19505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
19605436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* GCC >= 4.0 with -Wall emits unjustified "... may be used uninitialized"
19705436638acc7c010349a69c3395f1a57c642dc62Ying Wang   warnings in this file.  Use -Dlint to suppress them.  */
19805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#ifdef lint
19905436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define IF_LINT(Code) Code
20005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#else
20105436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define IF_LINT(Code) /* empty */
20205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
20305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
20405436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Avoid some warnings from "gcc -Wshadow".
20505436638acc7c010349a69c3395f1a57c642dc62Ying Wang   This file doesn't use the exp() and remainder() functions.  */
20605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#undef exp
20705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define exp expo
20805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#undef remainder
20905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define remainder rem
21005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
21105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && !WIDE_CHAR_VERSION
21205436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if (HAVE_STRNLEN && !defined _AIX)
21305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  define local_strnlen strnlen
21405436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else
21505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  ifndef local_strnlen_defined
21605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   define local_strnlen_defined 1
21705436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic size_t
21805436638acc7c010349a69c3395f1a57c642dc62Ying Wanglocal_strnlen (const char *string, size_t maxlen)
21905436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
22005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  const char *end = memchr (string, '\0', maxlen);
22105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return end ? (size_t) (end - string) : maxlen;
22205436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
22305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
22405436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
22505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
22605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
22705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#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
22805436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if HAVE_WCSLEN
22905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  define local_wcslen wcslen
23005436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else
23105436638acc7c010349a69c3395f1a57c642dc62Ying Wang   /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid
23205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      a dependency towards this library, here is a local substitute.
23305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      Define this substitute only once, even if this file is included
23405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      twice in the same compilation unit.  */
23505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  ifndef local_wcslen_defined
23605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   define local_wcslen_defined 1
23705436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic size_t
23805436638acc7c010349a69c3395f1a57c642dc62Ying Wanglocal_wcslen (const wchar_t *s)
23905436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
24005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  const wchar_t *ptr;
24105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
24205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  for (ptr = s; *ptr != (wchar_t) 0; ptr++)
24305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    ;
24405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return ptr - s;
24505436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
24605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
24705436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
24805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
24905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
25005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && HAVE_WCHAR_T && WIDE_CHAR_VERSION
25105436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if HAVE_WCSNLEN
25205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  define local_wcsnlen wcsnlen
25305436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else
25405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  ifndef local_wcsnlen_defined
25505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   define local_wcsnlen_defined 1
25605436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic size_t
25705436638acc7c010349a69c3395f1a57c642dc62Ying Wanglocal_wcsnlen (const wchar_t *s, size_t maxlen)
25805436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
25905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  const wchar_t *ptr;
26005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
26105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  for (ptr = s; maxlen > 0 && *ptr != (wchar_t) 0; ptr++, maxlen--)
26205436638acc7c010349a69c3395f1a57c642dc62Ying Wang    ;
26305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return ptr - s;
26405436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
26505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
26605436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
26705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
26805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
26905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL
27005436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Determine the decimal-point character according to the current locale.  */
27105436638acc7c010349a69c3395f1a57c642dc62Ying Wang# ifndef decimal_point_char_defined
27205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  define decimal_point_char_defined 1
27305436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic char
27405436638acc7c010349a69c3395f1a57c642dc62Ying Wangdecimal_point_char (void)
27505436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
27605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  const char *point;
27705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Determine it in a multithread-safe way.  We know nl_langinfo is
27805436638acc7c010349a69c3395f1a57c642dc62Ying Wang     multithread-safe on glibc systems and Mac OS X systems, but is not required
27905436638acc7c010349a69c3395f1a57c642dc62Ying Wang     to be multithread-safe by POSIX.  sprintf(), however, is multithread-safe.
28005436638acc7c010349a69c3395f1a57c642dc62Ying Wang     localeconv() is rarely multithread-safe.  */
28105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if HAVE_NL_LANGINFO && (__GLIBC__ || defined __UCLIBC__ || (defined __APPLE__ && defined __MACH__))
28205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  point = nl_langinfo (RADIXCHAR);
28305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  elif 1
28405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  char pointbuf[5];
28505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  sprintf (pointbuf, "%#.0f", 1.0);
28605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  point = &pointbuf[1];
28705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  else
28805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  point = localeconv () -> decimal_point;
28905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
29005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* The decimal point is always a single byte: either '.' or ','.  */
29105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return (point[0] != '\0' ? point[0] : '.');
29205436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
29305436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
29405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
29505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
29605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if NEED_PRINTF_INFINITE_DOUBLE && !NEED_PRINTF_DOUBLE && !defined IN_LIBINTL
29705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
29805436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Equivalent to !isfinite(x) || x == 0, but does not require libm.  */
29905436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic int
30005436638acc7c010349a69c3395f1a57c642dc62Ying Wangis_infinite_or_zero (double x)
30105436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
30205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return isnand (x) || x + x == x;
30305436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
30405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
30505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
30605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
30705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if NEED_PRINTF_INFINITE_LONG_DOUBLE && !NEED_PRINTF_LONG_DOUBLE && !defined IN_LIBINTL
30805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
30905436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Equivalent to !isfinite(x) || x == 0, but does not require libm.  */
31005436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic int
31105436638acc7c010349a69c3395f1a57c642dc62Ying Wangis_infinite_or_zerol (long double x)
31205436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
31305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return isnanl (x) || x + x == x;
31405436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
31505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
31605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
31705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
31805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL
31905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
32005436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Converting 'long double' to decimal without rare rounding bugs requires
32105436638acc7c010349a69c3395f1a57c642dc62Ying Wang   real bignums.  We use the naming conventions of GNU gmp, but vastly simpler
32205436638acc7c010349a69c3395f1a57c642dc62Ying Wang   (and slower) algorithms.  */
32305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
32405436638acc7c010349a69c3395f1a57c642dc62Ying Wangtypedef unsigned int mp_limb_t;
32505436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define GMP_LIMB_BITS 32
32605436638acc7c010349a69c3395f1a57c642dc62Ying Wangverify (sizeof (mp_limb_t) * CHAR_BIT == GMP_LIMB_BITS);
32705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
32805436638acc7c010349a69c3395f1a57c642dc62Ying Wangtypedef unsigned long long mp_twolimb_t;
32905436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define GMP_TWOLIMB_BITS 64
33005436638acc7c010349a69c3395f1a57c642dc62Ying Wangverify (sizeof (mp_twolimb_t) * CHAR_BIT == GMP_TWOLIMB_BITS);
33105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
33205436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Representation of a bignum >= 0.  */
33305436638acc7c010349a69c3395f1a57c642dc62Ying Wangtypedef struct
33405436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
33505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  size_t nlimbs;
33605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  mp_limb_t *limbs; /* Bits in little-endian order, allocated with malloc().  */
33705436638acc7c010349a69c3395f1a57c642dc62Ying Wang} mpn_t;
33805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
33905436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Compute the product of two bignums >= 0.
34005436638acc7c010349a69c3395f1a57c642dc62Ying Wang   Return the allocated memory in case of success, NULL in case of memory
34105436638acc7c010349a69c3395f1a57c642dc62Ying Wang   allocation failure.  */
34205436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic void *
34305436638acc7c010349a69c3395f1a57c642dc62Ying Wangmultiply (mpn_t src1, mpn_t src2, mpn_t *dest)
34405436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
34505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  const mp_limb_t *p1;
34605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  const mp_limb_t *p2;
34705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  size_t len1;
34805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  size_t len2;
34905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
35005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (src1.nlimbs <= src2.nlimbs)
35105436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
35205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      len1 = src1.nlimbs;
35305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      p1 = src1.limbs;
35405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      len2 = src2.nlimbs;
35505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      p2 = src2.limbs;
35605436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
35705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  else
35805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
35905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      len1 = src2.nlimbs;
36005436638acc7c010349a69c3395f1a57c642dc62Ying Wang      p1 = src2.limbs;
36105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      len2 = src1.nlimbs;
36205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      p2 = src1.limbs;
36305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
36405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Now 0 <= len1 <= len2.  */
36505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (len1 == 0)
36605436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
36705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      /* src1 or src2 is zero.  */
36805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      dest->nlimbs = 0;
36905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      dest->limbs = (mp_limb_t *) malloc (1);
37005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
37105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  else
37205436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
37305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      /* Here 1 <= len1 <= len2.  */
37405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      size_t dlen;
37505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      mp_limb_t *dp;
37605436638acc7c010349a69c3395f1a57c642dc62Ying Wang      size_t k, i, j;
37705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
37805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      dlen = len1 + len2;
37905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      dp = (mp_limb_t *) malloc (dlen * sizeof (mp_limb_t));
38005436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (dp == NULL)
38105436638acc7c010349a69c3395f1a57c642dc62Ying Wang        return NULL;
38205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      for (k = len2; k > 0; )
38305436638acc7c010349a69c3395f1a57c642dc62Ying Wang        dp[--k] = 0;
38405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      for (i = 0; i < len1; i++)
38505436638acc7c010349a69c3395f1a57c642dc62Ying Wang        {
38605436638acc7c010349a69c3395f1a57c642dc62Ying Wang          mp_limb_t digit1 = p1[i];
38705436638acc7c010349a69c3395f1a57c642dc62Ying Wang          mp_twolimb_t carry = 0;
38805436638acc7c010349a69c3395f1a57c642dc62Ying Wang          for (j = 0; j < len2; j++)
38905436638acc7c010349a69c3395f1a57c642dc62Ying Wang            {
39005436638acc7c010349a69c3395f1a57c642dc62Ying Wang              mp_limb_t digit2 = p2[j];
39105436638acc7c010349a69c3395f1a57c642dc62Ying Wang              carry += (mp_twolimb_t) digit1 * (mp_twolimb_t) digit2;
39205436638acc7c010349a69c3395f1a57c642dc62Ying Wang              carry += dp[i + j];
39305436638acc7c010349a69c3395f1a57c642dc62Ying Wang              dp[i + j] = (mp_limb_t) carry;
39405436638acc7c010349a69c3395f1a57c642dc62Ying Wang              carry = carry >> GMP_LIMB_BITS;
39505436638acc7c010349a69c3395f1a57c642dc62Ying Wang            }
39605436638acc7c010349a69c3395f1a57c642dc62Ying Wang          dp[i + len2] = (mp_limb_t) carry;
39705436638acc7c010349a69c3395f1a57c642dc62Ying Wang        }
39805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      /* Normalise.  */
39905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      while (dlen > 0 && dp[dlen - 1] == 0)
40005436638acc7c010349a69c3395f1a57c642dc62Ying Wang        dlen--;
40105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      dest->nlimbs = dlen;
40205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      dest->limbs = dp;
40305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
40405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return dest->limbs;
40505436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
40605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
40705436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Compute the quotient of a bignum a >= 0 and a bignum b > 0.
40805436638acc7c010349a69c3395f1a57c642dc62Ying Wang   a is written as  a = q * b + r  with 0 <= r < b.  q is the quotient, r
40905436638acc7c010349a69c3395f1a57c642dc62Ying Wang   the remainder.
41005436638acc7c010349a69c3395f1a57c642dc62Ying Wang   Finally, round-to-even is performed: If r > b/2 or if r = b/2 and q is odd,
41105436638acc7c010349a69c3395f1a57c642dc62Ying Wang   q is incremented.
41205436638acc7c010349a69c3395f1a57c642dc62Ying Wang   Return the allocated memory in case of success, NULL in case of memory
41305436638acc7c010349a69c3395f1a57c642dc62Ying Wang   allocation failure.  */
41405436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic void *
41505436638acc7c010349a69c3395f1a57c642dc62Ying Wangdivide (mpn_t a, mpn_t b, mpn_t *q)
41605436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
41705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Algorithm:
41805436638acc7c010349a69c3395f1a57c642dc62Ying Wang     First normalise a and b: a=[a[m-1],...,a[0]], b=[b[n-1],...,b[0]]
41905436638acc7c010349a69c3395f1a57c642dc62Ying Wang     with m>=0 and n>0 (in base beta = 2^GMP_LIMB_BITS).
42005436638acc7c010349a69c3395f1a57c642dc62Ying Wang     If m<n, then q:=0 and r:=a.
42105436638acc7c010349a69c3395f1a57c642dc62Ying Wang     If m>=n=1, perform a single-precision division:
42205436638acc7c010349a69c3395f1a57c642dc62Ying Wang       r:=0, j:=m,
42305436638acc7c010349a69c3395f1a57c642dc62Ying Wang       while j>0 do
42405436638acc7c010349a69c3395f1a57c642dc62Ying Wang         {Here (q[m-1]*beta^(m-1)+...+q[j]*beta^j) * b[0] + r*beta^j =
42505436638acc7c010349a69c3395f1a57c642dc62Ying Wang               = a[m-1]*beta^(m-1)+...+a[j]*beta^j und 0<=r<b[0]<beta}
42605436638acc7c010349a69c3395f1a57c642dc62Ying Wang         j:=j-1, r:=r*beta+a[j], q[j]:=floor(r/b[0]), r:=r-b[0]*q[j].
42705436638acc7c010349a69c3395f1a57c642dc62Ying Wang       Normalise [q[m-1],...,q[0]], yields q.
42805436638acc7c010349a69c3395f1a57c642dc62Ying Wang     If m>=n>1, perform a multiple-precision division:
42905436638acc7c010349a69c3395f1a57c642dc62Ying Wang       We have a/b < beta^(m-n+1).
43005436638acc7c010349a69c3395f1a57c642dc62Ying Wang       s:=intDsize-1-(highest bit in b[n-1]), 0<=s<intDsize.
43105436638acc7c010349a69c3395f1a57c642dc62Ying Wang       Shift a and b left by s bits, copying them. r:=a.
43205436638acc7c010349a69c3395f1a57c642dc62Ying Wang       r=[r[m],...,r[0]], b=[b[n-1],...,b[0]] with b[n-1]>=beta/2.
43305436638acc7c010349a69c3395f1a57c642dc62Ying Wang       For j=m-n,...,0: {Here 0 <= r < b*beta^(j+1).}
43405436638acc7c010349a69c3395f1a57c642dc62Ying Wang         Compute q* :
43505436638acc7c010349a69c3395f1a57c642dc62Ying Wang           q* := floor((r[j+n]*beta+r[j+n-1])/b[n-1]).
43605436638acc7c010349a69c3395f1a57c642dc62Ying Wang           In case of overflow (q* >= beta) set q* := beta-1.
43705436638acc7c010349a69c3395f1a57c642dc62Ying Wang           Compute c2 := ((r[j+n]*beta+r[j+n-1]) - q* * b[n-1])*beta + r[j+n-2]
43805436638acc7c010349a69c3395f1a57c642dc62Ying Wang           and c3 := b[n-2] * q*.
43905436638acc7c010349a69c3395f1a57c642dc62Ying Wang           {We have 0 <= c2 < 2*beta^2, even 0 <= c2 < beta^2 if no overflow
44005436638acc7c010349a69c3395f1a57c642dc62Ying Wang            occurred.  Furthermore 0 <= c3 < beta^2.
44105436638acc7c010349a69c3395f1a57c642dc62Ying Wang            If there was overflow and
44205436638acc7c010349a69c3395f1a57c642dc62Ying Wang            r[j+n]*beta+r[j+n-1] - q* * b[n-1] >= beta, i.e. c2 >= beta^2,
44305436638acc7c010349a69c3395f1a57c642dc62Ying Wang            the next test can be skipped.}
44405436638acc7c010349a69c3395f1a57c642dc62Ying Wang           While c3 > c2, {Here 0 <= c2 < c3 < beta^2}
44505436638acc7c010349a69c3395f1a57c642dc62Ying Wang             Put q* := q* - 1, c2 := c2 + b[n-1]*beta, c3 := c3 - b[n-2].
44605436638acc7c010349a69c3395f1a57c642dc62Ying Wang           If q* > 0:
44705436638acc7c010349a69c3395f1a57c642dc62Ying Wang             Put r := r - b * q* * beta^j. In detail:
44805436638acc7c010349a69c3395f1a57c642dc62Ying Wang               [r[n+j],...,r[j]] := [r[n+j],...,r[j]] - q* * [b[n-1],...,b[0]].
44905436638acc7c010349a69c3395f1a57c642dc62Ying Wang               hence: u:=0, for i:=0 to n-1 do
45005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              u := u + q* * b[i],
45105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              r[j+i]:=r[j+i]-(u mod beta) (+ beta, if carry),
45205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              u:=u div beta (+ 1, if carry in subtraction)
45305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      r[n+j]:=r[n+j]-u.
45405436638acc7c010349a69c3395f1a57c642dc62Ying Wang               {Since always u = (q* * [b[i-1],...,b[0]] div beta^i) + 1
45505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                               < q* + 1 <= beta,
45605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                the carry u does not overflow.}
45705436638acc7c010349a69c3395f1a57c642dc62Ying Wang             If a negative carry occurs, put q* := q* - 1
45805436638acc7c010349a69c3395f1a57c642dc62Ying Wang               and [r[n+j],...,r[j]] := [r[n+j],...,r[j]] + [0,b[n-1],...,b[0]].
45905436638acc7c010349a69c3395f1a57c642dc62Ying Wang         Set q[j] := q*.
46005436638acc7c010349a69c3395f1a57c642dc62Ying Wang       Normalise [q[m-n],..,q[0]]; this yields the quotient q.
46105436638acc7c010349a69c3395f1a57c642dc62Ying Wang       Shift [r[n-1],...,r[0]] right by s bits and normalise; this yields the
46205436638acc7c010349a69c3395f1a57c642dc62Ying Wang       rest r.
46305436638acc7c010349a69c3395f1a57c642dc62Ying Wang       The room for q[j] can be allocated at the memory location of r[n+j].
46405436638acc7c010349a69c3395f1a57c642dc62Ying Wang     Finally, round-to-even:
46505436638acc7c010349a69c3395f1a57c642dc62Ying Wang       Shift r left by 1 bit.
46605436638acc7c010349a69c3395f1a57c642dc62Ying Wang       If r > b or if r = b and q[0] is odd, q := q+1.
46705436638acc7c010349a69c3395f1a57c642dc62Ying Wang   */
46805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  const mp_limb_t *a_ptr = a.limbs;
46905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  size_t a_len = a.nlimbs;
47005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  const mp_limb_t *b_ptr = b.limbs;
47105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  size_t b_len = b.nlimbs;
47205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  mp_limb_t *roomptr;
47305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  mp_limb_t *tmp_roomptr = NULL;
47405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  mp_limb_t *q_ptr;
47505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  size_t q_len;
47605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  mp_limb_t *r_ptr;
47705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  size_t r_len;
47805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
47905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Allocate room for a_len+2 digits.
48005436638acc7c010349a69c3395f1a57c642dc62Ying Wang     (Need a_len+1 digits for the real division and 1 more digit for the
48105436638acc7c010349a69c3395f1a57c642dc62Ying Wang     final rounding of q.)  */
48205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  roomptr = (mp_limb_t *) malloc ((a_len + 2) * sizeof (mp_limb_t));
48305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (roomptr == NULL)
48405436638acc7c010349a69c3395f1a57c642dc62Ying Wang    return NULL;
48505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
48605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Normalise a.  */
48705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  while (a_len > 0 && a_ptr[a_len - 1] == 0)
48805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    a_len--;
48905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
49005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Normalise b.  */
49105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  for (;;)
49205436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
49305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (b_len == 0)
49405436638acc7c010349a69c3395f1a57c642dc62Ying Wang        /* Division by zero.  */
49505436638acc7c010349a69c3395f1a57c642dc62Ying Wang        abort ();
49605436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (b_ptr[b_len - 1] == 0)
49705436638acc7c010349a69c3395f1a57c642dc62Ying Wang        b_len--;
49805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      else
49905436638acc7c010349a69c3395f1a57c642dc62Ying Wang        break;
50005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
50105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
50205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Here m = a_len >= 0 and n = b_len > 0.  */
50305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
50405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (a_len < b_len)
50505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
50605436638acc7c010349a69c3395f1a57c642dc62Ying Wang      /* m<n: trivial case.  q=0, r := copy of a.  */
50705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      r_ptr = roomptr;
50805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      r_len = a_len;
50905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      memcpy (r_ptr, a_ptr, a_len * sizeof (mp_limb_t));
51005436638acc7c010349a69c3395f1a57c642dc62Ying Wang      q_ptr = roomptr + a_len;
51105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      q_len = 0;
51205436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
51305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  else if (b_len == 1)
51405436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
51505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      /* n=1: single precision division.
51605436638acc7c010349a69c3395f1a57c642dc62Ying Wang         beta^(m-1) <= a < beta^m  ==>  beta^(m-2) <= a/b < beta^m  */
51705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      r_ptr = roomptr;
51805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      q_ptr = roomptr + 1;
51905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      {
52005436638acc7c010349a69c3395f1a57c642dc62Ying Wang        mp_limb_t den = b_ptr[0];
52105436638acc7c010349a69c3395f1a57c642dc62Ying Wang        mp_limb_t remainder = 0;
52205436638acc7c010349a69c3395f1a57c642dc62Ying Wang        const mp_limb_t *sourceptr = a_ptr + a_len;
52305436638acc7c010349a69c3395f1a57c642dc62Ying Wang        mp_limb_t *destptr = q_ptr + a_len;
52405436638acc7c010349a69c3395f1a57c642dc62Ying Wang        size_t count;
52505436638acc7c010349a69c3395f1a57c642dc62Ying Wang        for (count = a_len; count > 0; count--)
52605436638acc7c010349a69c3395f1a57c642dc62Ying Wang          {
52705436638acc7c010349a69c3395f1a57c642dc62Ying Wang            mp_twolimb_t num =
52805436638acc7c010349a69c3395f1a57c642dc62Ying Wang              ((mp_twolimb_t) remainder << GMP_LIMB_BITS) | *--sourceptr;
52905436638acc7c010349a69c3395f1a57c642dc62Ying Wang            *--destptr = num / den;
53005436638acc7c010349a69c3395f1a57c642dc62Ying Wang            remainder = num % den;
53105436638acc7c010349a69c3395f1a57c642dc62Ying Wang          }
53205436638acc7c010349a69c3395f1a57c642dc62Ying Wang        /* Normalise and store r.  */
53305436638acc7c010349a69c3395f1a57c642dc62Ying Wang        if (remainder > 0)
53405436638acc7c010349a69c3395f1a57c642dc62Ying Wang          {
53505436638acc7c010349a69c3395f1a57c642dc62Ying Wang            r_ptr[0] = remainder;
53605436638acc7c010349a69c3395f1a57c642dc62Ying Wang            r_len = 1;
53705436638acc7c010349a69c3395f1a57c642dc62Ying Wang          }
53805436638acc7c010349a69c3395f1a57c642dc62Ying Wang        else
53905436638acc7c010349a69c3395f1a57c642dc62Ying Wang          r_len = 0;
54005436638acc7c010349a69c3395f1a57c642dc62Ying Wang        /* Normalise q.  */
54105436638acc7c010349a69c3395f1a57c642dc62Ying Wang        q_len = a_len;
54205436638acc7c010349a69c3395f1a57c642dc62Ying Wang        if (q_ptr[q_len - 1] == 0)
54305436638acc7c010349a69c3395f1a57c642dc62Ying Wang          q_len--;
54405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      }
54505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
54605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  else
54705436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
54805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      /* n>1: multiple precision division.
54905436638acc7c010349a69c3395f1a57c642dc62Ying Wang         beta^(m-1) <= a < beta^m, beta^(n-1) <= b < beta^n  ==>
55005436638acc7c010349a69c3395f1a57c642dc62Ying Wang         beta^(m-n-1) <= a/b < beta^(m-n+1).  */
55105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      /* Determine s.  */
55205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      size_t s;
55305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      {
55405436638acc7c010349a69c3395f1a57c642dc62Ying Wang        mp_limb_t msd = b_ptr[b_len - 1]; /* = b[n-1], > 0 */
55505436638acc7c010349a69c3395f1a57c642dc62Ying Wang        /* Determine s = GMP_LIMB_BITS - integer_length (msd).
55605436638acc7c010349a69c3395f1a57c642dc62Ying Wang           Code copied from gnulib's integer_length.c.  */
55705436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
55805436638acc7c010349a69c3395f1a57c642dc62Ying Wang        s = __builtin_clz (msd);
55905436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else
56005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if defined DBL_EXPBIT0_WORD && defined DBL_EXPBIT0_BIT
56105436638acc7c010349a69c3395f1a57c642dc62Ying Wang        if (GMP_LIMB_BITS <= DBL_MANT_BIT)
56205436638acc7c010349a69c3395f1a57c642dc62Ying Wang          {
56305436638acc7c010349a69c3395f1a57c642dc62Ying Wang            /* Use 'double' operations.
56405436638acc7c010349a69c3395f1a57c642dc62Ying Wang               Assumes an IEEE 754 'double' implementation.  */
56505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   define DBL_EXP_MASK ((DBL_MAX_EXP - DBL_MIN_EXP) | 7)
56605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   define DBL_EXP_BIAS (DBL_EXP_MASK / 2 - 1)
56705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   define NWORDS \
56805436638acc7c010349a69c3395f1a57c642dc62Ying Wang     ((sizeof (double) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
56905436638acc7c010349a69c3395f1a57c642dc62Ying Wang            union { double value; unsigned int word[NWORDS]; } m;
57005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
57105436638acc7c010349a69c3395f1a57c642dc62Ying Wang            /* Use a single integer to floating-point conversion.  */
57205436638acc7c010349a69c3395f1a57c642dc62Ying Wang            m.value = msd;
57305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
57405436638acc7c010349a69c3395f1a57c642dc62Ying Wang            s = GMP_LIMB_BITS
57505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                - (((m.word[DBL_EXPBIT0_WORD] >> DBL_EXPBIT0_BIT) & DBL_EXP_MASK)
57605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   - DBL_EXP_BIAS);
57705436638acc7c010349a69c3395f1a57c642dc62Ying Wang          }
57805436638acc7c010349a69c3395f1a57c642dc62Ying Wang        else
57905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   undef NWORDS
58005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
58105436638acc7c010349a69c3395f1a57c642dc62Ying Wang          {
58205436638acc7c010349a69c3395f1a57c642dc62Ying Wang            s = 31;
58305436638acc7c010349a69c3395f1a57c642dc62Ying Wang            if (msd >= 0x10000)
58405436638acc7c010349a69c3395f1a57c642dc62Ying Wang              {
58505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                msd = msd >> 16;
58605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                s -= 16;
58705436638acc7c010349a69c3395f1a57c642dc62Ying Wang              }
58805436638acc7c010349a69c3395f1a57c642dc62Ying Wang            if (msd >= 0x100)
58905436638acc7c010349a69c3395f1a57c642dc62Ying Wang              {
59005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                msd = msd >> 8;
59105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                s -= 8;
59205436638acc7c010349a69c3395f1a57c642dc62Ying Wang              }
59305436638acc7c010349a69c3395f1a57c642dc62Ying Wang            if (msd >= 0x10)
59405436638acc7c010349a69c3395f1a57c642dc62Ying Wang              {
59505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                msd = msd >> 4;
59605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                s -= 4;
59705436638acc7c010349a69c3395f1a57c642dc62Ying Wang              }
59805436638acc7c010349a69c3395f1a57c642dc62Ying Wang            if (msd >= 0x4)
59905436638acc7c010349a69c3395f1a57c642dc62Ying Wang              {
60005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                msd = msd >> 2;
60105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                s -= 2;
60205436638acc7c010349a69c3395f1a57c642dc62Ying Wang              }
60305436638acc7c010349a69c3395f1a57c642dc62Ying Wang            if (msd >= 0x2)
60405436638acc7c010349a69c3395f1a57c642dc62Ying Wang              {
60505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                msd = msd >> 1;
60605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                s -= 1;
60705436638acc7c010349a69c3395f1a57c642dc62Ying Wang              }
60805436638acc7c010349a69c3395f1a57c642dc62Ying Wang          }
60905436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
61005436638acc7c010349a69c3395f1a57c642dc62Ying Wang      }
61105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      /* 0 <= s < GMP_LIMB_BITS.
61205436638acc7c010349a69c3395f1a57c642dc62Ying Wang         Copy b, shifting it left by s bits.  */
61305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (s > 0)
61405436638acc7c010349a69c3395f1a57c642dc62Ying Wang        {
61505436638acc7c010349a69c3395f1a57c642dc62Ying Wang          tmp_roomptr = (mp_limb_t *) malloc (b_len * sizeof (mp_limb_t));
61605436638acc7c010349a69c3395f1a57c642dc62Ying Wang          if (tmp_roomptr == NULL)
61705436638acc7c010349a69c3395f1a57c642dc62Ying Wang            {
61805436638acc7c010349a69c3395f1a57c642dc62Ying Wang              free (roomptr);
61905436638acc7c010349a69c3395f1a57c642dc62Ying Wang              return NULL;
62005436638acc7c010349a69c3395f1a57c642dc62Ying Wang            }
62105436638acc7c010349a69c3395f1a57c642dc62Ying Wang          {
62205436638acc7c010349a69c3395f1a57c642dc62Ying Wang            const mp_limb_t *sourceptr = b_ptr;
62305436638acc7c010349a69c3395f1a57c642dc62Ying Wang            mp_limb_t *destptr = tmp_roomptr;
62405436638acc7c010349a69c3395f1a57c642dc62Ying Wang            mp_twolimb_t accu = 0;
62505436638acc7c010349a69c3395f1a57c642dc62Ying Wang            size_t count;
62605436638acc7c010349a69c3395f1a57c642dc62Ying Wang            for (count = b_len; count > 0; count--)
62705436638acc7c010349a69c3395f1a57c642dc62Ying Wang              {
62805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                accu += (mp_twolimb_t) *sourceptr++ << s;
62905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                *destptr++ = (mp_limb_t) accu;
63005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                accu = accu >> GMP_LIMB_BITS;
63105436638acc7c010349a69c3395f1a57c642dc62Ying Wang              }
63205436638acc7c010349a69c3395f1a57c642dc62Ying Wang            /* accu must be zero, since that was how s was determined.  */
63305436638acc7c010349a69c3395f1a57c642dc62Ying Wang            if (accu != 0)
63405436638acc7c010349a69c3395f1a57c642dc62Ying Wang              abort ();
63505436638acc7c010349a69c3395f1a57c642dc62Ying Wang          }
63605436638acc7c010349a69c3395f1a57c642dc62Ying Wang          b_ptr = tmp_roomptr;
63705436638acc7c010349a69c3395f1a57c642dc62Ying Wang        }
63805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      /* Copy a, shifting it left by s bits, yields r.
63905436638acc7c010349a69c3395f1a57c642dc62Ying Wang         Memory layout:
64005436638acc7c010349a69c3395f1a57c642dc62Ying Wang         At the beginning: r = roomptr[0..a_len],
64105436638acc7c010349a69c3395f1a57c642dc62Ying Wang         at the end: r = roomptr[0..b_len-1], q = roomptr[b_len..a_len]  */
64205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      r_ptr = roomptr;
64305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (s == 0)
64405436638acc7c010349a69c3395f1a57c642dc62Ying Wang        {
64505436638acc7c010349a69c3395f1a57c642dc62Ying Wang          memcpy (r_ptr, a_ptr, a_len * sizeof (mp_limb_t));
64605436638acc7c010349a69c3395f1a57c642dc62Ying Wang          r_ptr[a_len] = 0;
64705436638acc7c010349a69c3395f1a57c642dc62Ying Wang        }
64805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      else
64905436638acc7c010349a69c3395f1a57c642dc62Ying Wang        {
65005436638acc7c010349a69c3395f1a57c642dc62Ying Wang          const mp_limb_t *sourceptr = a_ptr;
65105436638acc7c010349a69c3395f1a57c642dc62Ying Wang          mp_limb_t *destptr = r_ptr;
65205436638acc7c010349a69c3395f1a57c642dc62Ying Wang          mp_twolimb_t accu = 0;
65305436638acc7c010349a69c3395f1a57c642dc62Ying Wang          size_t count;
65405436638acc7c010349a69c3395f1a57c642dc62Ying Wang          for (count = a_len; count > 0; count--)
65505436638acc7c010349a69c3395f1a57c642dc62Ying Wang            {
65605436638acc7c010349a69c3395f1a57c642dc62Ying Wang              accu += (mp_twolimb_t) *sourceptr++ << s;
65705436638acc7c010349a69c3395f1a57c642dc62Ying Wang              *destptr++ = (mp_limb_t) accu;
65805436638acc7c010349a69c3395f1a57c642dc62Ying Wang              accu = accu >> GMP_LIMB_BITS;
65905436638acc7c010349a69c3395f1a57c642dc62Ying Wang            }
66005436638acc7c010349a69c3395f1a57c642dc62Ying Wang          *destptr++ = (mp_limb_t) accu;
66105436638acc7c010349a69c3395f1a57c642dc62Ying Wang        }
66205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      q_ptr = roomptr + b_len;
66305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      q_len = a_len - b_len + 1; /* q will have m-n+1 limbs */
66405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      {
66505436638acc7c010349a69c3395f1a57c642dc62Ying Wang        size_t j = a_len - b_len; /* m-n */
66605436638acc7c010349a69c3395f1a57c642dc62Ying Wang        mp_limb_t b_msd = b_ptr[b_len - 1]; /* b[n-1] */
66705436638acc7c010349a69c3395f1a57c642dc62Ying Wang        mp_limb_t b_2msd = b_ptr[b_len - 2]; /* b[n-2] */
66805436638acc7c010349a69c3395f1a57c642dc62Ying Wang        mp_twolimb_t b_msdd = /* b[n-1]*beta+b[n-2] */
66905436638acc7c010349a69c3395f1a57c642dc62Ying Wang          ((mp_twolimb_t) b_msd << GMP_LIMB_BITS) | b_2msd;
67005436638acc7c010349a69c3395f1a57c642dc62Ying Wang        /* Division loop, traversed m-n+1 times.
67105436638acc7c010349a69c3395f1a57c642dc62Ying Wang           j counts down, b is unchanged, beta/2 <= b[n-1] < beta.  */
67205436638acc7c010349a69c3395f1a57c642dc62Ying Wang        for (;;)
67305436638acc7c010349a69c3395f1a57c642dc62Ying Wang          {
67405436638acc7c010349a69c3395f1a57c642dc62Ying Wang            mp_limb_t q_star;
67505436638acc7c010349a69c3395f1a57c642dc62Ying Wang            mp_limb_t c1;
67605436638acc7c010349a69c3395f1a57c642dc62Ying Wang            if (r_ptr[j + b_len] < b_msd) /* r[j+n] < b[n-1] ? */
67705436638acc7c010349a69c3395f1a57c642dc62Ying Wang              {
67805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                /* Divide r[j+n]*beta+r[j+n-1] by b[n-1], no overflow.  */
67905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                mp_twolimb_t num =
68005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  ((mp_twolimb_t) r_ptr[j + b_len] << GMP_LIMB_BITS)
68105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  | r_ptr[j + b_len - 1];
68205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                q_star = num / b_msd;
68305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                c1 = num % b_msd;
68405436638acc7c010349a69c3395f1a57c642dc62Ying Wang              }
68505436638acc7c010349a69c3395f1a57c642dc62Ying Wang            else
68605436638acc7c010349a69c3395f1a57c642dc62Ying Wang              {
68705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                /* Overflow, hence r[j+n]*beta+r[j+n-1] >= beta*b[n-1].  */
68805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                q_star = (mp_limb_t)~(mp_limb_t)0; /* q* = beta-1 */
68905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                /* Test whether r[j+n]*beta+r[j+n-1] - (beta-1)*b[n-1] >= beta
69005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   <==> r[j+n]*beta+r[j+n-1] + b[n-1] >= beta*b[n-1]+beta
69105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   <==> b[n-1] < floor((r[j+n]*beta+r[j+n-1]+b[n-1])/beta)
69205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {<= beta !}.
69305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   If yes, jump directly to the subtraction loop.
69405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   (Otherwise, r[j+n]*beta+r[j+n-1] - (beta-1)*b[n-1] < beta
69505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    <==> floor((r[j+n]*beta+r[j+n-1]+b[n-1])/beta) = b[n-1] ) */
69605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (r_ptr[j + b_len] > b_msd
69705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    || (c1 = r_ptr[j + b_len - 1] + b_msd) < b_msd)
69805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  /* r[j+n] >= b[n-1]+1 or
69905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                     r[j+n] = b[n-1] and the addition r[j+n-1]+b[n-1] gives a
70005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                     carry.  */
70105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  goto subtract;
70205436638acc7c010349a69c3395f1a57c642dc62Ying Wang              }
70305436638acc7c010349a69c3395f1a57c642dc62Ying Wang            /* q_star = q*,
70405436638acc7c010349a69c3395f1a57c642dc62Ying Wang               c1 = (r[j+n]*beta+r[j+n-1]) - q* * b[n-1] (>=0, <beta).  */
70505436638acc7c010349a69c3395f1a57c642dc62Ying Wang            {
70605436638acc7c010349a69c3395f1a57c642dc62Ying Wang              mp_twolimb_t c2 = /* c1*beta+r[j+n-2] */
70705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                ((mp_twolimb_t) c1 << GMP_LIMB_BITS) | r_ptr[j + b_len - 2];
70805436638acc7c010349a69c3395f1a57c642dc62Ying Wang              mp_twolimb_t c3 = /* b[n-2] * q* */
70905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                (mp_twolimb_t) b_2msd * (mp_twolimb_t) q_star;
71005436638acc7c010349a69c3395f1a57c642dc62Ying Wang              /* While c2 < c3, increase c2 and decrease c3.
71105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                 Consider c3-c2.  While it is > 0, decrease it by
71205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                 b[n-1]*beta+b[n-2].  Because of b[n-1]*beta+b[n-2] >= beta^2/2
71305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                 this can happen only twice.  */
71405436638acc7c010349a69c3395f1a57c642dc62Ying Wang              if (c3 > c2)
71505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                {
71605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  q_star = q_star - 1; /* q* := q* - 1 */
71705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  if (c3 - c2 > b_msdd)
71805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    q_star = q_star - 1; /* q* := q* - 1 */
71905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                }
72005436638acc7c010349a69c3395f1a57c642dc62Ying Wang            }
72105436638acc7c010349a69c3395f1a57c642dc62Ying Wang            if (q_star > 0)
72205436638acc7c010349a69c3395f1a57c642dc62Ying Wang              subtract:
72305436638acc7c010349a69c3395f1a57c642dc62Ying Wang              {
72405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                /* Subtract r := r - b * q* * beta^j.  */
72505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                mp_limb_t cr;
72605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                {
72705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  const mp_limb_t *sourceptr = b_ptr;
72805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  mp_limb_t *destptr = r_ptr + j;
72905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  mp_twolimb_t carry = 0;
73005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  size_t count;
73105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  for (count = b_len; count > 0; count--)
73205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    {
73305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      /* Here 0 <= carry <= q*.  */
73405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      carry =
73505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        carry
73605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        + (mp_twolimb_t) q_star * (mp_twolimb_t) *sourceptr++
73705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        + (mp_limb_t) ~(*destptr);
73805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      /* Here 0 <= carry <= beta*q* + beta-1.  */
73905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      *destptr++ = ~(mp_limb_t) carry;
74005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      carry = carry >> GMP_LIMB_BITS; /* <= q* */
74105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    }
74205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  cr = (mp_limb_t) carry;
74305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                }
74405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                /* Subtract cr from r_ptr[j + b_len], then forget about
74505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   r_ptr[j + b_len].  */
74605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (cr > r_ptr[j + b_len])
74705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  {
74805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    /* Subtraction gave a carry.  */
74905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    q_star = q_star - 1; /* q* := q* - 1 */
75005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    /* Add b back.  */
75105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    {
75205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      const mp_limb_t *sourceptr = b_ptr;
75305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      mp_limb_t *destptr = r_ptr + j;
75405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      mp_limb_t carry = 0;
75505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      size_t count;
75605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      for (count = b_len; count > 0; count--)
75705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
75805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          mp_limb_t source1 = *sourceptr++;
75905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          mp_limb_t source2 = *destptr;
76005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          *destptr++ = source1 + source2 + carry;
76105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          carry =
76205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            (carry
76305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                             ? source1 >= (mp_limb_t) ~source2
76405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                             : source1 > (mp_limb_t) ~source2);
76505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
76605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    }
76705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    /* Forget about the carry and about r[j+n].  */
76805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  }
76905436638acc7c010349a69c3395f1a57c642dc62Ying Wang              }
77005436638acc7c010349a69c3395f1a57c642dc62Ying Wang            /* q* is determined.  Store it as q[j].  */
77105436638acc7c010349a69c3395f1a57c642dc62Ying Wang            q_ptr[j] = q_star;
77205436638acc7c010349a69c3395f1a57c642dc62Ying Wang            if (j == 0)
77305436638acc7c010349a69c3395f1a57c642dc62Ying Wang              break;
77405436638acc7c010349a69c3395f1a57c642dc62Ying Wang            j--;
77505436638acc7c010349a69c3395f1a57c642dc62Ying Wang          }
77605436638acc7c010349a69c3395f1a57c642dc62Ying Wang      }
77705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      r_len = b_len;
77805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      /* Normalise q.  */
77905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (q_ptr[q_len - 1] == 0)
78005436638acc7c010349a69c3395f1a57c642dc62Ying Wang        q_len--;
78105436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if 0 /* Not needed here, since we need r only to compare it with b/2, and
78205436638acc7c010349a69c3395f1a57c642dc62Ying Wang          b is shifted left by s bits.  */
78305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      /* Shift r right by s bits.  */
78405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (s > 0)
78505436638acc7c010349a69c3395f1a57c642dc62Ying Wang        {
78605436638acc7c010349a69c3395f1a57c642dc62Ying Wang          mp_limb_t ptr = r_ptr + r_len;
78705436638acc7c010349a69c3395f1a57c642dc62Ying Wang          mp_twolimb_t accu = 0;
78805436638acc7c010349a69c3395f1a57c642dc62Ying Wang          size_t count;
78905436638acc7c010349a69c3395f1a57c642dc62Ying Wang          for (count = r_len; count > 0; count--)
79005436638acc7c010349a69c3395f1a57c642dc62Ying Wang            {
79105436638acc7c010349a69c3395f1a57c642dc62Ying Wang              accu = (mp_twolimb_t) (mp_limb_t) accu << GMP_LIMB_BITS;
79205436638acc7c010349a69c3395f1a57c642dc62Ying Wang              accu += (mp_twolimb_t) *--ptr << (GMP_LIMB_BITS - s);
79305436638acc7c010349a69c3395f1a57c642dc62Ying Wang              *ptr = (mp_limb_t) (accu >> GMP_LIMB_BITS);
79405436638acc7c010349a69c3395f1a57c642dc62Ying Wang            }
79505436638acc7c010349a69c3395f1a57c642dc62Ying Wang        }
79605436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
79705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      /* Normalise r.  */
79805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      while (r_len > 0 && r_ptr[r_len - 1] == 0)
79905436638acc7c010349a69c3395f1a57c642dc62Ying Wang        r_len--;
80005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
80105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Compare r << 1 with b.  */
80205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (r_len > b_len)
80305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    goto increment_q;
80405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  {
80505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    size_t i;
80605436638acc7c010349a69c3395f1a57c642dc62Ying Wang    for (i = b_len;;)
80705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      {
80805436638acc7c010349a69c3395f1a57c642dc62Ying Wang        mp_limb_t r_i =
80905436638acc7c010349a69c3395f1a57c642dc62Ying Wang          (i <= r_len && i > 0 ? r_ptr[i - 1] >> (GMP_LIMB_BITS - 1) : 0)
81005436638acc7c010349a69c3395f1a57c642dc62Ying Wang          | (i < r_len ? r_ptr[i] << 1 : 0);
81105436638acc7c010349a69c3395f1a57c642dc62Ying Wang        mp_limb_t b_i = (i < b_len ? b_ptr[i] : 0);
81205436638acc7c010349a69c3395f1a57c642dc62Ying Wang        if (r_i > b_i)
81305436638acc7c010349a69c3395f1a57c642dc62Ying Wang          goto increment_q;
81405436638acc7c010349a69c3395f1a57c642dc62Ying Wang        if (r_i < b_i)
81505436638acc7c010349a69c3395f1a57c642dc62Ying Wang          goto keep_q;
81605436638acc7c010349a69c3395f1a57c642dc62Ying Wang        if (i == 0)
81705436638acc7c010349a69c3395f1a57c642dc62Ying Wang          break;
81805436638acc7c010349a69c3395f1a57c642dc62Ying Wang        i--;
81905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      }
82005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  }
82105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (q_len > 0 && ((q_ptr[0] & 1) != 0))
82205436638acc7c010349a69c3395f1a57c642dc62Ying Wang    /* q is odd.  */
82305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    increment_q:
82405436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
82505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      size_t i;
82605436638acc7c010349a69c3395f1a57c642dc62Ying Wang      for (i = 0; i < q_len; i++)
82705436638acc7c010349a69c3395f1a57c642dc62Ying Wang        if (++(q_ptr[i]) != 0)
82805436638acc7c010349a69c3395f1a57c642dc62Ying Wang          goto keep_q;
82905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      q_ptr[q_len++] = 1;
83005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
83105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  keep_q:
83205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (tmp_roomptr != NULL)
83305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    free (tmp_roomptr);
83405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  q->limbs = q_ptr;
83505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  q->nlimbs = q_len;
83605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return roomptr;
83705436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
83805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
83905436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Convert a bignum a >= 0, multiplied with 10^extra_zeroes, to decimal
84005436638acc7c010349a69c3395f1a57c642dc62Ying Wang   representation.
84105436638acc7c010349a69c3395f1a57c642dc62Ying Wang   Destroys the contents of a.
84205436638acc7c010349a69c3395f1a57c642dc62Ying Wang   Return the allocated memory - containing the decimal digits in low-to-high
84305436638acc7c010349a69c3395f1a57c642dc62Ying Wang   order, terminated with a NUL character - in case of success, NULL in case
84405436638acc7c010349a69c3395f1a57c642dc62Ying Wang   of memory allocation failure.  */
84505436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic char *
84605436638acc7c010349a69c3395f1a57c642dc62Ying Wangconvert_to_decimal (mpn_t a, size_t extra_zeroes)
84705436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
84805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  mp_limb_t *a_ptr = a.limbs;
84905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  size_t a_len = a.nlimbs;
85005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* 0.03345 is slightly larger than log(2)/(9*log(10)).  */
85105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  size_t c_len = 9 * ((size_t)(a_len * (GMP_LIMB_BITS * 0.03345f)) + 1);
85205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  char *c_ptr = (char *) malloc (xsum (c_len, extra_zeroes));
85305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (c_ptr != NULL)
85405436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
85505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      char *d_ptr = c_ptr;
85605436638acc7c010349a69c3395f1a57c642dc62Ying Wang      for (; extra_zeroes > 0; extra_zeroes--)
85705436638acc7c010349a69c3395f1a57c642dc62Ying Wang        *d_ptr++ = '0';
85805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      while (a_len > 0)
85905436638acc7c010349a69c3395f1a57c642dc62Ying Wang        {
86005436638acc7c010349a69c3395f1a57c642dc62Ying Wang          /* Divide a by 10^9, in-place.  */
86105436638acc7c010349a69c3395f1a57c642dc62Ying Wang          mp_limb_t remainder = 0;
86205436638acc7c010349a69c3395f1a57c642dc62Ying Wang          mp_limb_t *ptr = a_ptr + a_len;
86305436638acc7c010349a69c3395f1a57c642dc62Ying Wang          size_t count;
86405436638acc7c010349a69c3395f1a57c642dc62Ying Wang          for (count = a_len; count > 0; count--)
86505436638acc7c010349a69c3395f1a57c642dc62Ying Wang            {
86605436638acc7c010349a69c3395f1a57c642dc62Ying Wang              mp_twolimb_t num =
86705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                ((mp_twolimb_t) remainder << GMP_LIMB_BITS) | *--ptr;
86805436638acc7c010349a69c3395f1a57c642dc62Ying Wang              *ptr = num / 1000000000;
86905436638acc7c010349a69c3395f1a57c642dc62Ying Wang              remainder = num % 1000000000;
87005436638acc7c010349a69c3395f1a57c642dc62Ying Wang            }
87105436638acc7c010349a69c3395f1a57c642dc62Ying Wang          /* Store the remainder as 9 decimal digits.  */
87205436638acc7c010349a69c3395f1a57c642dc62Ying Wang          for (count = 9; count > 0; count--)
87305436638acc7c010349a69c3395f1a57c642dc62Ying Wang            {
87405436638acc7c010349a69c3395f1a57c642dc62Ying Wang              *d_ptr++ = '0' + (remainder % 10);
87505436638acc7c010349a69c3395f1a57c642dc62Ying Wang              remainder = remainder / 10;
87605436638acc7c010349a69c3395f1a57c642dc62Ying Wang            }
87705436638acc7c010349a69c3395f1a57c642dc62Ying Wang          /* Normalize a.  */
87805436638acc7c010349a69c3395f1a57c642dc62Ying Wang          if (a_ptr[a_len - 1] == 0)
87905436638acc7c010349a69c3395f1a57c642dc62Ying Wang            a_len--;
88005436638acc7c010349a69c3395f1a57c642dc62Ying Wang        }
88105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      /* Remove leading zeroes.  */
88205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      while (d_ptr > c_ptr && d_ptr[-1] == '0')
88305436638acc7c010349a69c3395f1a57c642dc62Ying Wang        d_ptr--;
88405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      /* But keep at least one zero.  */
88505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (d_ptr == c_ptr)
88605436638acc7c010349a69c3395f1a57c642dc62Ying Wang        *d_ptr++ = '0';
88705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      /* Terminate the string.  */
88805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      *d_ptr = '\0';
88905436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
89005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return c_ptr;
89105436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
89205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
89305436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if NEED_PRINTF_LONG_DOUBLE
89405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
89505436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Assuming x is finite and >= 0:
89605436638acc7c010349a69c3395f1a57c642dc62Ying Wang   write x as x = 2^e * m, where m is a bignum.
89705436638acc7c010349a69c3395f1a57c642dc62Ying Wang   Return the allocated memory in case of success, NULL in case of memory
89805436638acc7c010349a69c3395f1a57c642dc62Ying Wang   allocation failure.  */
89905436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic void *
90005436638acc7c010349a69c3395f1a57c642dc62Ying Wangdecode_long_double (long double x, int *ep, mpn_t *mp)
90105436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
90205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  mpn_t m;
90305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  int exp;
90405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  long double y;
90505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  size_t i;
90605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
90705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Allocate memory for result.  */
90805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  m.nlimbs = (LDBL_MANT_BIT + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS;
90905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  m.limbs = (mp_limb_t *) malloc (m.nlimbs * sizeof (mp_limb_t));
91005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (m.limbs == NULL)
91105436638acc7c010349a69c3395f1a57c642dc62Ying Wang    return NULL;
91205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Split into exponential part and mantissa.  */
91305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  y = frexpl (x, &exp);
91405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (!(y >= 0.0L && y < 1.0L))
91505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    abort ();
91605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* x = 2^exp * y = 2^(exp - LDBL_MANT_BIT) * (y * 2^LDBL_MANT_BIT), and the
91705436638acc7c010349a69c3395f1a57c642dc62Ying Wang     latter is an integer.  */
91805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Convert the mantissa (y * 2^LDBL_MANT_BIT) to a sequence of limbs.
91905436638acc7c010349a69c3395f1a57c642dc62Ying Wang     I'm not sure whether it's safe to cast a 'long double' value between
92005436638acc7c010349a69c3395f1a57c642dc62Ying Wang     2^31 and 2^32 to 'unsigned int', therefore play safe and cast only
92105436638acc7c010349a69c3395f1a57c642dc62Ying Wang     'long double' values between 0 and 2^16 (to 'unsigned int' or 'int',
92205436638acc7c010349a69c3395f1a57c642dc62Ying Wang     doesn't matter).  */
92305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if (LDBL_MANT_BIT % GMP_LIMB_BITS) != 0
92405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   if (LDBL_MANT_BIT % GMP_LIMB_BITS) > GMP_LIMB_BITS / 2
92505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
92605436638acc7c010349a69c3395f1a57c642dc62Ying Wang      mp_limb_t hi, lo;
92705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      y *= (mp_limb_t) 1 << (LDBL_MANT_BIT % (GMP_LIMB_BITS / 2));
92805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      hi = (int) y;
92905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      y -= hi;
93005436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (!(y >= 0.0L && y < 1.0L))
93105436638acc7c010349a69c3395f1a57c642dc62Ying Wang        abort ();
93205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
93305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      lo = (int) y;
93405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      y -= lo;
93505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (!(y >= 0.0L && y < 1.0L))
93605436638acc7c010349a69c3395f1a57c642dc62Ying Wang        abort ();
93705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      m.limbs[LDBL_MANT_BIT / GMP_LIMB_BITS] = (hi << (GMP_LIMB_BITS / 2)) | lo;
93805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
93905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   else
94005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
94105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      mp_limb_t d;
94205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      y *= (mp_limb_t) 1 << (LDBL_MANT_BIT % GMP_LIMB_BITS);
94305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      d = (int) y;
94405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      y -= d;
94505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (!(y >= 0.0L && y < 1.0L))
94605436638acc7c010349a69c3395f1a57c642dc62Ying Wang        abort ();
94705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      m.limbs[LDBL_MANT_BIT / GMP_LIMB_BITS] = d;
94805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
94905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   endif
95005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
95105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  for (i = LDBL_MANT_BIT / GMP_LIMB_BITS; i > 0; )
95205436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
95305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      mp_limb_t hi, lo;
95405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
95505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      hi = (int) y;
95605436638acc7c010349a69c3395f1a57c642dc62Ying Wang      y -= hi;
95705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (!(y >= 0.0L && y < 1.0L))
95805436638acc7c010349a69c3395f1a57c642dc62Ying Wang        abort ();
95905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
96005436638acc7c010349a69c3395f1a57c642dc62Ying Wang      lo = (int) y;
96105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      y -= lo;
96205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (!(y >= 0.0L && y < 1.0L))
96305436638acc7c010349a69c3395f1a57c642dc62Ying Wang        abort ();
96405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      m.limbs[--i] = (hi << (GMP_LIMB_BITS / 2)) | lo;
96505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
96605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if 0 /* On FreeBSD 6.1/x86, 'long double' numbers sometimes have excess
96705436638acc7c010349a69c3395f1a57c642dc62Ying Wang           precision.  */
96805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (!(y == 0.0L))
96905436638acc7c010349a69c3395f1a57c642dc62Ying Wang    abort ();
97005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
97105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Normalise.  */
97205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  while (m.nlimbs > 0 && m.limbs[m.nlimbs - 1] == 0)
97305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    m.nlimbs--;
97405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  *mp = m;
97505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  *ep = exp - LDBL_MANT_BIT;
97605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return m.limbs;
97705436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
97805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
97905436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
98005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
98105436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if NEED_PRINTF_DOUBLE
98205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
98305436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Assuming x is finite and >= 0:
98405436638acc7c010349a69c3395f1a57c642dc62Ying Wang   write x as x = 2^e * m, where m is a bignum.
98505436638acc7c010349a69c3395f1a57c642dc62Ying Wang   Return the allocated memory in case of success, NULL in case of memory
98605436638acc7c010349a69c3395f1a57c642dc62Ying Wang   allocation failure.  */
98705436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic void *
98805436638acc7c010349a69c3395f1a57c642dc62Ying Wangdecode_double (double x, int *ep, mpn_t *mp)
98905436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
99005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  mpn_t m;
99105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  int exp;
99205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  double y;
99305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  size_t i;
99405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
99505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Allocate memory for result.  */
99605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  m.nlimbs = (DBL_MANT_BIT + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS;
99705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  m.limbs = (mp_limb_t *) malloc (m.nlimbs * sizeof (mp_limb_t));
99805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (m.limbs == NULL)
99905436638acc7c010349a69c3395f1a57c642dc62Ying Wang    return NULL;
100005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Split into exponential part and mantissa.  */
100105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  y = frexp (x, &exp);
100205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (!(y >= 0.0 && y < 1.0))
100305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    abort ();
100405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* x = 2^exp * y = 2^(exp - DBL_MANT_BIT) * (y * 2^DBL_MANT_BIT), and the
100505436638acc7c010349a69c3395f1a57c642dc62Ying Wang     latter is an integer.  */
100605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Convert the mantissa (y * 2^DBL_MANT_BIT) to a sequence of limbs.
100705436638acc7c010349a69c3395f1a57c642dc62Ying Wang     I'm not sure whether it's safe to cast a 'double' value between
100805436638acc7c010349a69c3395f1a57c642dc62Ying Wang     2^31 and 2^32 to 'unsigned int', therefore play safe and cast only
100905436638acc7c010349a69c3395f1a57c642dc62Ying Wang     'double' values between 0 and 2^16 (to 'unsigned int' or 'int',
101005436638acc7c010349a69c3395f1a57c642dc62Ying Wang     doesn't matter).  */
101105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if (DBL_MANT_BIT % GMP_LIMB_BITS) != 0
101205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   if (DBL_MANT_BIT % GMP_LIMB_BITS) > GMP_LIMB_BITS / 2
101305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
101405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      mp_limb_t hi, lo;
101505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      y *= (mp_limb_t) 1 << (DBL_MANT_BIT % (GMP_LIMB_BITS / 2));
101605436638acc7c010349a69c3395f1a57c642dc62Ying Wang      hi = (int) y;
101705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      y -= hi;
101805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (!(y >= 0.0 && y < 1.0))
101905436638acc7c010349a69c3395f1a57c642dc62Ying Wang        abort ();
102005436638acc7c010349a69c3395f1a57c642dc62Ying Wang      y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
102105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      lo = (int) y;
102205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      y -= lo;
102305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (!(y >= 0.0 && y < 1.0))
102405436638acc7c010349a69c3395f1a57c642dc62Ying Wang        abort ();
102505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      m.limbs[DBL_MANT_BIT / GMP_LIMB_BITS] = (hi << (GMP_LIMB_BITS / 2)) | lo;
102605436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
102705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   else
102805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
102905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      mp_limb_t d;
103005436638acc7c010349a69c3395f1a57c642dc62Ying Wang      y *= (mp_limb_t) 1 << (DBL_MANT_BIT % GMP_LIMB_BITS);
103105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      d = (int) y;
103205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      y -= d;
103305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (!(y >= 0.0 && y < 1.0))
103405436638acc7c010349a69c3395f1a57c642dc62Ying Wang        abort ();
103505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      m.limbs[DBL_MANT_BIT / GMP_LIMB_BITS] = d;
103605436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
103705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   endif
103805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
103905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  for (i = DBL_MANT_BIT / GMP_LIMB_BITS; i > 0; )
104005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
104105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      mp_limb_t hi, lo;
104205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
104305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      hi = (int) y;
104405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      y -= hi;
104505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (!(y >= 0.0 && y < 1.0))
104605436638acc7c010349a69c3395f1a57c642dc62Ying Wang        abort ();
104705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
104805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      lo = (int) y;
104905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      y -= lo;
105005436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (!(y >= 0.0 && y < 1.0))
105105436638acc7c010349a69c3395f1a57c642dc62Ying Wang        abort ();
105205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      m.limbs[--i] = (hi << (GMP_LIMB_BITS / 2)) | lo;
105305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
105405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (!(y == 0.0))
105505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    abort ();
105605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Normalise.  */
105705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  while (m.nlimbs > 0 && m.limbs[m.nlimbs - 1] == 0)
105805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    m.nlimbs--;
105905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  *mp = m;
106005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  *ep = exp - DBL_MANT_BIT;
106105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return m.limbs;
106205436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
106305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
106405436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
106505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
106605436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Assuming x = 2^e * m is finite and >= 0, and n is an integer:
106705436638acc7c010349a69c3395f1a57c642dc62Ying Wang   Returns the decimal representation of round (x * 10^n).
106805436638acc7c010349a69c3395f1a57c642dc62Ying Wang   Return the allocated memory - containing the decimal digits in low-to-high
106905436638acc7c010349a69c3395f1a57c642dc62Ying Wang   order, terminated with a NUL character - in case of success, NULL in case
107005436638acc7c010349a69c3395f1a57c642dc62Ying Wang   of memory allocation failure.  */
107105436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic char *
107205436638acc7c010349a69c3395f1a57c642dc62Ying Wangscale10_round_decimal_decoded (int e, mpn_t m, void *memory, int n)
107305436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
107405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  int s;
107505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  size_t extra_zeroes;
107605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  unsigned int abs_n;
107705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  unsigned int abs_s;
107805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  mp_limb_t *pow5_ptr;
107905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  size_t pow5_len;
108005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  unsigned int s_limbs;
108105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  unsigned int s_bits;
108205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  mpn_t pow5;
108305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  mpn_t z;
108405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  void *z_memory;
108505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  char *digits;
108605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
108705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (memory == NULL)
108805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    return NULL;
108905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* x = 2^e * m, hence
109005436638acc7c010349a69c3395f1a57c642dc62Ying Wang     y = round (2^e * 10^n * m) = round (2^(e+n) * 5^n * m)
109105436638acc7c010349a69c3395f1a57c642dc62Ying Wang       = round (2^s * 5^n * m).  */
109205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  s = e + n;
109305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  extra_zeroes = 0;
109405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Factor out a common power of 10 if possible.  */
109505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (s > 0 && n > 0)
109605436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
109705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      extra_zeroes = (s < n ? s : n);
109805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      s -= extra_zeroes;
109905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      n -= extra_zeroes;
110005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
110105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Here y = round (2^s * 5^n * m) * 10^extra_zeroes.
110205436638acc7c010349a69c3395f1a57c642dc62Ying Wang     Before converting to decimal, we need to compute
110305436638acc7c010349a69c3395f1a57c642dc62Ying Wang     z = round (2^s * 5^n * m).  */
110405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Compute 5^|n|, possibly shifted by |s| bits if n and s have the same
110505436638acc7c010349a69c3395f1a57c642dc62Ying Wang     sign.  2.322 is slightly larger than log(5)/log(2).  */
110605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  abs_n = (n >= 0 ? n : -n);
110705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  abs_s = (s >= 0 ? s : -s);
110805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  pow5_ptr = (mp_limb_t *) malloc (((int)(abs_n * (2.322f / GMP_LIMB_BITS)) + 1
110905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    + abs_s / GMP_LIMB_BITS + 1)
111005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                   * sizeof (mp_limb_t));
111105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (pow5_ptr == NULL)
111205436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
111305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      free (memory);
111405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      return NULL;
111505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
111605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Initialize with 1.  */
111705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  pow5_ptr[0] = 1;
111805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  pow5_len = 1;
111905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Multiply with 5^|n|.  */
112005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (abs_n > 0)
112105436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
112205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      static mp_limb_t const small_pow5[13 + 1] =
112305436638acc7c010349a69c3395f1a57c642dc62Ying Wang        {
112405436638acc7c010349a69c3395f1a57c642dc62Ying Wang          1, 5, 25, 125, 625, 3125, 15625, 78125, 390625, 1953125, 9765625,
112505436638acc7c010349a69c3395f1a57c642dc62Ying Wang          48828125, 244140625, 1220703125
112605436638acc7c010349a69c3395f1a57c642dc62Ying Wang        };
112705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      unsigned int n13;
112805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      for (n13 = 0; n13 <= abs_n; n13 += 13)
112905436638acc7c010349a69c3395f1a57c642dc62Ying Wang        {
113005436638acc7c010349a69c3395f1a57c642dc62Ying Wang          mp_limb_t digit1 = small_pow5[n13 + 13 <= abs_n ? 13 : abs_n - n13];
113105436638acc7c010349a69c3395f1a57c642dc62Ying Wang          size_t j;
113205436638acc7c010349a69c3395f1a57c642dc62Ying Wang          mp_twolimb_t carry = 0;
113305436638acc7c010349a69c3395f1a57c642dc62Ying Wang          for (j = 0; j < pow5_len; j++)
113405436638acc7c010349a69c3395f1a57c642dc62Ying Wang            {
113505436638acc7c010349a69c3395f1a57c642dc62Ying Wang              mp_limb_t digit2 = pow5_ptr[j];
113605436638acc7c010349a69c3395f1a57c642dc62Ying Wang              carry += (mp_twolimb_t) digit1 * (mp_twolimb_t) digit2;
113705436638acc7c010349a69c3395f1a57c642dc62Ying Wang              pow5_ptr[j] = (mp_limb_t) carry;
113805436638acc7c010349a69c3395f1a57c642dc62Ying Wang              carry = carry >> GMP_LIMB_BITS;
113905436638acc7c010349a69c3395f1a57c642dc62Ying Wang            }
114005436638acc7c010349a69c3395f1a57c642dc62Ying Wang          if (carry > 0)
114105436638acc7c010349a69c3395f1a57c642dc62Ying Wang            pow5_ptr[pow5_len++] = (mp_limb_t) carry;
114205436638acc7c010349a69c3395f1a57c642dc62Ying Wang        }
114305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
114405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  s_limbs = abs_s / GMP_LIMB_BITS;
114505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  s_bits = abs_s % GMP_LIMB_BITS;
114605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (n >= 0 ? s >= 0 : s <= 0)
114705436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
114805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      /* Multiply with 2^|s|.  */
114905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (s_bits > 0)
115005436638acc7c010349a69c3395f1a57c642dc62Ying Wang        {
115105436638acc7c010349a69c3395f1a57c642dc62Ying Wang          mp_limb_t *ptr = pow5_ptr;
115205436638acc7c010349a69c3395f1a57c642dc62Ying Wang          mp_twolimb_t accu = 0;
115305436638acc7c010349a69c3395f1a57c642dc62Ying Wang          size_t count;
115405436638acc7c010349a69c3395f1a57c642dc62Ying Wang          for (count = pow5_len; count > 0; count--)
115505436638acc7c010349a69c3395f1a57c642dc62Ying Wang            {
115605436638acc7c010349a69c3395f1a57c642dc62Ying Wang              accu += (mp_twolimb_t) *ptr << s_bits;
115705436638acc7c010349a69c3395f1a57c642dc62Ying Wang              *ptr++ = (mp_limb_t) accu;
115805436638acc7c010349a69c3395f1a57c642dc62Ying Wang              accu = accu >> GMP_LIMB_BITS;
115905436638acc7c010349a69c3395f1a57c642dc62Ying Wang            }
116005436638acc7c010349a69c3395f1a57c642dc62Ying Wang          if (accu > 0)
116105436638acc7c010349a69c3395f1a57c642dc62Ying Wang            {
116205436638acc7c010349a69c3395f1a57c642dc62Ying Wang              *ptr = (mp_limb_t) accu;
116305436638acc7c010349a69c3395f1a57c642dc62Ying Wang              pow5_len++;
116405436638acc7c010349a69c3395f1a57c642dc62Ying Wang            }
116505436638acc7c010349a69c3395f1a57c642dc62Ying Wang        }
116605436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (s_limbs > 0)
116705436638acc7c010349a69c3395f1a57c642dc62Ying Wang        {
116805436638acc7c010349a69c3395f1a57c642dc62Ying Wang          size_t count;
116905436638acc7c010349a69c3395f1a57c642dc62Ying Wang          for (count = pow5_len; count > 0;)
117005436638acc7c010349a69c3395f1a57c642dc62Ying Wang            {
117105436638acc7c010349a69c3395f1a57c642dc62Ying Wang              count--;
117205436638acc7c010349a69c3395f1a57c642dc62Ying Wang              pow5_ptr[s_limbs + count] = pow5_ptr[count];
117305436638acc7c010349a69c3395f1a57c642dc62Ying Wang            }
117405436638acc7c010349a69c3395f1a57c642dc62Ying Wang          for (count = s_limbs; count > 0;)
117505436638acc7c010349a69c3395f1a57c642dc62Ying Wang            {
117605436638acc7c010349a69c3395f1a57c642dc62Ying Wang              count--;
117705436638acc7c010349a69c3395f1a57c642dc62Ying Wang              pow5_ptr[count] = 0;
117805436638acc7c010349a69c3395f1a57c642dc62Ying Wang            }
117905436638acc7c010349a69c3395f1a57c642dc62Ying Wang          pow5_len += s_limbs;
118005436638acc7c010349a69c3395f1a57c642dc62Ying Wang        }
118105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      pow5.limbs = pow5_ptr;
118205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      pow5.nlimbs = pow5_len;
118305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (n >= 0)
118405436638acc7c010349a69c3395f1a57c642dc62Ying Wang        {
118505436638acc7c010349a69c3395f1a57c642dc62Ying Wang          /* Multiply m with pow5.  No division needed.  */
118605436638acc7c010349a69c3395f1a57c642dc62Ying Wang          z_memory = multiply (m, pow5, &z);
118705436638acc7c010349a69c3395f1a57c642dc62Ying Wang        }
118805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      else
118905436638acc7c010349a69c3395f1a57c642dc62Ying Wang        {
119005436638acc7c010349a69c3395f1a57c642dc62Ying Wang          /* Divide m by pow5 and round.  */
119105436638acc7c010349a69c3395f1a57c642dc62Ying Wang          z_memory = divide (m, pow5, &z);
119205436638acc7c010349a69c3395f1a57c642dc62Ying Wang        }
119305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
119405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  else
119505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
119605436638acc7c010349a69c3395f1a57c642dc62Ying Wang      pow5.limbs = pow5_ptr;
119705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      pow5.nlimbs = pow5_len;
119805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (n >= 0)
119905436638acc7c010349a69c3395f1a57c642dc62Ying Wang        {
120005436638acc7c010349a69c3395f1a57c642dc62Ying Wang          /* n >= 0, s < 0.
120105436638acc7c010349a69c3395f1a57c642dc62Ying Wang             Multiply m with pow5, then divide by 2^|s|.  */
120205436638acc7c010349a69c3395f1a57c642dc62Ying Wang          mpn_t numerator;
120305436638acc7c010349a69c3395f1a57c642dc62Ying Wang          mpn_t denominator;
120405436638acc7c010349a69c3395f1a57c642dc62Ying Wang          void *tmp_memory;
120505436638acc7c010349a69c3395f1a57c642dc62Ying Wang          tmp_memory = multiply (m, pow5, &numerator);
120605436638acc7c010349a69c3395f1a57c642dc62Ying Wang          if (tmp_memory == NULL)
120705436638acc7c010349a69c3395f1a57c642dc62Ying Wang            {
120805436638acc7c010349a69c3395f1a57c642dc62Ying Wang              free (pow5_ptr);
120905436638acc7c010349a69c3395f1a57c642dc62Ying Wang              free (memory);
121005436638acc7c010349a69c3395f1a57c642dc62Ying Wang              return NULL;
121105436638acc7c010349a69c3395f1a57c642dc62Ying Wang            }
121205436638acc7c010349a69c3395f1a57c642dc62Ying Wang          /* Construct 2^|s|.  */
121305436638acc7c010349a69c3395f1a57c642dc62Ying Wang          {
121405436638acc7c010349a69c3395f1a57c642dc62Ying Wang            mp_limb_t *ptr = pow5_ptr + pow5_len;
121505436638acc7c010349a69c3395f1a57c642dc62Ying Wang            size_t i;
121605436638acc7c010349a69c3395f1a57c642dc62Ying Wang            for (i = 0; i < s_limbs; i++)
121705436638acc7c010349a69c3395f1a57c642dc62Ying Wang              ptr[i] = 0;
121805436638acc7c010349a69c3395f1a57c642dc62Ying Wang            ptr[s_limbs] = (mp_limb_t) 1 << s_bits;
121905436638acc7c010349a69c3395f1a57c642dc62Ying Wang            denominator.limbs = ptr;
122005436638acc7c010349a69c3395f1a57c642dc62Ying Wang            denominator.nlimbs = s_limbs + 1;
122105436638acc7c010349a69c3395f1a57c642dc62Ying Wang          }
122205436638acc7c010349a69c3395f1a57c642dc62Ying Wang          z_memory = divide (numerator, denominator, &z);
122305436638acc7c010349a69c3395f1a57c642dc62Ying Wang          free (tmp_memory);
122405436638acc7c010349a69c3395f1a57c642dc62Ying Wang        }
122505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      else
122605436638acc7c010349a69c3395f1a57c642dc62Ying Wang        {
122705436638acc7c010349a69c3395f1a57c642dc62Ying Wang          /* n < 0, s > 0.
122805436638acc7c010349a69c3395f1a57c642dc62Ying Wang             Multiply m with 2^s, then divide by pow5.  */
122905436638acc7c010349a69c3395f1a57c642dc62Ying Wang          mpn_t numerator;
123005436638acc7c010349a69c3395f1a57c642dc62Ying Wang          mp_limb_t *num_ptr;
123105436638acc7c010349a69c3395f1a57c642dc62Ying Wang          num_ptr = (mp_limb_t *) malloc ((m.nlimbs + s_limbs + 1)
123205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          * sizeof (mp_limb_t));
123305436638acc7c010349a69c3395f1a57c642dc62Ying Wang          if (num_ptr == NULL)
123405436638acc7c010349a69c3395f1a57c642dc62Ying Wang            {
123505436638acc7c010349a69c3395f1a57c642dc62Ying Wang              free (pow5_ptr);
123605436638acc7c010349a69c3395f1a57c642dc62Ying Wang              free (memory);
123705436638acc7c010349a69c3395f1a57c642dc62Ying Wang              return NULL;
123805436638acc7c010349a69c3395f1a57c642dc62Ying Wang            }
123905436638acc7c010349a69c3395f1a57c642dc62Ying Wang          {
124005436638acc7c010349a69c3395f1a57c642dc62Ying Wang            mp_limb_t *destptr = num_ptr;
124105436638acc7c010349a69c3395f1a57c642dc62Ying Wang            {
124205436638acc7c010349a69c3395f1a57c642dc62Ying Wang              size_t i;
124305436638acc7c010349a69c3395f1a57c642dc62Ying Wang              for (i = 0; i < s_limbs; i++)
124405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                *destptr++ = 0;
124505436638acc7c010349a69c3395f1a57c642dc62Ying Wang            }
124605436638acc7c010349a69c3395f1a57c642dc62Ying Wang            if (s_bits > 0)
124705436638acc7c010349a69c3395f1a57c642dc62Ying Wang              {
124805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                const mp_limb_t *sourceptr = m.limbs;
124905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                mp_twolimb_t accu = 0;
125005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                size_t count;
125105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                for (count = m.nlimbs; count > 0; count--)
125205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  {
125305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    accu += (mp_twolimb_t) *sourceptr++ << s_bits;
125405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    *destptr++ = (mp_limb_t) accu;
125505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    accu = accu >> GMP_LIMB_BITS;
125605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  }
125705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (accu > 0)
125805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  *destptr++ = (mp_limb_t) accu;
125905436638acc7c010349a69c3395f1a57c642dc62Ying Wang              }
126005436638acc7c010349a69c3395f1a57c642dc62Ying Wang            else
126105436638acc7c010349a69c3395f1a57c642dc62Ying Wang              {
126205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                const mp_limb_t *sourceptr = m.limbs;
126305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                size_t count;
126405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                for (count = m.nlimbs; count > 0; count--)
126505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  *destptr++ = *sourceptr++;
126605436638acc7c010349a69c3395f1a57c642dc62Ying Wang              }
126705436638acc7c010349a69c3395f1a57c642dc62Ying Wang            numerator.limbs = num_ptr;
126805436638acc7c010349a69c3395f1a57c642dc62Ying Wang            numerator.nlimbs = destptr - num_ptr;
126905436638acc7c010349a69c3395f1a57c642dc62Ying Wang          }
127005436638acc7c010349a69c3395f1a57c642dc62Ying Wang          z_memory = divide (numerator, pow5, &z);
127105436638acc7c010349a69c3395f1a57c642dc62Ying Wang          free (num_ptr);
127205436638acc7c010349a69c3395f1a57c642dc62Ying Wang        }
127305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
127405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  free (pow5_ptr);
127505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  free (memory);
127605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
127705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Here y = round (x * 10^n) = z * 10^extra_zeroes.  */
127805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
127905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (z_memory == NULL)
128005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    return NULL;
128105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  digits = convert_to_decimal (z, extra_zeroes);
128205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  free (z_memory);
128305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return digits;
128405436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
128505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
128605436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if NEED_PRINTF_LONG_DOUBLE
128705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
128805436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Assuming x is finite and >= 0, and n is an integer:
128905436638acc7c010349a69c3395f1a57c642dc62Ying Wang   Returns the decimal representation of round (x * 10^n).
129005436638acc7c010349a69c3395f1a57c642dc62Ying Wang   Return the allocated memory - containing the decimal digits in low-to-high
129105436638acc7c010349a69c3395f1a57c642dc62Ying Wang   order, terminated with a NUL character - in case of success, NULL in case
129205436638acc7c010349a69c3395f1a57c642dc62Ying Wang   of memory allocation failure.  */
129305436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic char *
129405436638acc7c010349a69c3395f1a57c642dc62Ying Wangscale10_round_decimal_long_double (long double x, int n)
129505436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
129605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  int e IF_LINT(= 0);
129705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  mpn_t m;
129805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  void *memory = decode_long_double (x, &e, &m);
129905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return scale10_round_decimal_decoded (e, m, memory, n);
130005436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
130105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
130205436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
130305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
130405436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if NEED_PRINTF_DOUBLE
130505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
130605436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Assuming x is finite and >= 0, and n is an integer:
130705436638acc7c010349a69c3395f1a57c642dc62Ying Wang   Returns the decimal representation of round (x * 10^n).
130805436638acc7c010349a69c3395f1a57c642dc62Ying Wang   Return the allocated memory - containing the decimal digits in low-to-high
130905436638acc7c010349a69c3395f1a57c642dc62Ying Wang   order, terminated with a NUL character - in case of success, NULL in case
131005436638acc7c010349a69c3395f1a57c642dc62Ying Wang   of memory allocation failure.  */
131105436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic char *
131205436638acc7c010349a69c3395f1a57c642dc62Ying Wangscale10_round_decimal_double (double x, int n)
131305436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
131405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  int e IF_LINT(= 0);
131505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  mpn_t m;
131605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  void *memory = decode_double (x, &e, &m);
131705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return scale10_round_decimal_decoded (e, m, memory, n);
131805436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
131905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
132005436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
132105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
132205436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if NEED_PRINTF_LONG_DOUBLE
132305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
132405436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Assuming x is finite and > 0:
132505436638acc7c010349a69c3395f1a57c642dc62Ying Wang   Return an approximation for n with 10^n <= x < 10^(n+1).
132605436638acc7c010349a69c3395f1a57c642dc62Ying Wang   The approximation is usually the right n, but may be off by 1 sometimes.  */
132705436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic int
132805436638acc7c010349a69c3395f1a57c642dc62Ying Wangfloorlog10l (long double x)
132905436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
133005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  int exp;
133105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  long double y;
133205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  double z;
133305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  double l;
133405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
133505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Split into exponential part and mantissa.  */
133605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  y = frexpl (x, &exp);
133705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (!(y >= 0.0L && y < 1.0L))
133805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    abort ();
133905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (y == 0.0L)
134005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    return INT_MIN;
134105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (y < 0.5L)
134205436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
134305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      while (y < (1.0L / (1 << (GMP_LIMB_BITS / 2)) / (1 << (GMP_LIMB_BITS / 2))))
134405436638acc7c010349a69c3395f1a57c642dc62Ying Wang        {
134505436638acc7c010349a69c3395f1a57c642dc62Ying Wang          y *= 1.0L * (1 << (GMP_LIMB_BITS / 2)) * (1 << (GMP_LIMB_BITS / 2));
134605436638acc7c010349a69c3395f1a57c642dc62Ying Wang          exp -= GMP_LIMB_BITS;
134705436638acc7c010349a69c3395f1a57c642dc62Ying Wang        }
134805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (y < (1.0L / (1 << 16)))
134905436638acc7c010349a69c3395f1a57c642dc62Ying Wang        {
135005436638acc7c010349a69c3395f1a57c642dc62Ying Wang          y *= 1.0L * (1 << 16);
135105436638acc7c010349a69c3395f1a57c642dc62Ying Wang          exp -= 16;
135205436638acc7c010349a69c3395f1a57c642dc62Ying Wang        }
135305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (y < (1.0L / (1 << 8)))
135405436638acc7c010349a69c3395f1a57c642dc62Ying Wang        {
135505436638acc7c010349a69c3395f1a57c642dc62Ying Wang          y *= 1.0L * (1 << 8);
135605436638acc7c010349a69c3395f1a57c642dc62Ying Wang          exp -= 8;
135705436638acc7c010349a69c3395f1a57c642dc62Ying Wang        }
135805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (y < (1.0L / (1 << 4)))
135905436638acc7c010349a69c3395f1a57c642dc62Ying Wang        {
136005436638acc7c010349a69c3395f1a57c642dc62Ying Wang          y *= 1.0L * (1 << 4);
136105436638acc7c010349a69c3395f1a57c642dc62Ying Wang          exp -= 4;
136205436638acc7c010349a69c3395f1a57c642dc62Ying Wang        }
136305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (y < (1.0L / (1 << 2)))
136405436638acc7c010349a69c3395f1a57c642dc62Ying Wang        {
136505436638acc7c010349a69c3395f1a57c642dc62Ying Wang          y *= 1.0L * (1 << 2);
136605436638acc7c010349a69c3395f1a57c642dc62Ying Wang          exp -= 2;
136705436638acc7c010349a69c3395f1a57c642dc62Ying Wang        }
136805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (y < (1.0L / (1 << 1)))
136905436638acc7c010349a69c3395f1a57c642dc62Ying Wang        {
137005436638acc7c010349a69c3395f1a57c642dc62Ying Wang          y *= 1.0L * (1 << 1);
137105436638acc7c010349a69c3395f1a57c642dc62Ying Wang          exp -= 1;
137205436638acc7c010349a69c3395f1a57c642dc62Ying Wang        }
137305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
137405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (!(y >= 0.5L && y < 1.0L))
137505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    abort ();
137605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Compute an approximation for l = log2(x) = exp + log2(y).  */
137705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  l = exp;
137805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  z = y;
137905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (z < 0.70710678118654752444)
138005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
138105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      z *= 1.4142135623730950488;
138205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      l -= 0.5;
138305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
138405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (z < 0.8408964152537145431)
138505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
138605436638acc7c010349a69c3395f1a57c642dc62Ying Wang      z *= 1.1892071150027210667;
138705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      l -= 0.25;
138805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
138905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (z < 0.91700404320467123175)
139005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
139105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      z *= 1.0905077326652576592;
139205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      l -= 0.125;
139305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
139405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (z < 0.9576032806985736469)
139505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
139605436638acc7c010349a69c3395f1a57c642dc62Ying Wang      z *= 1.0442737824274138403;
139705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      l -= 0.0625;
139805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
139905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Now 0.95 <= z <= 1.01.  */
140005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  z = 1 - z;
140105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* log2(1-z) = 1/log(2) * (- z - z^2/2 - z^3/3 - z^4/4 - ...)
140205436638acc7c010349a69c3395f1a57c642dc62Ying Wang     Four terms are enough to get an approximation with error < 10^-7.  */
140305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  l -= 1.4426950408889634074 * z * (1.0 + z * (0.5 + z * ((1.0 / 3) + z * 0.25)));
140405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Finally multiply with log(2)/log(10), yields an approximation for
140505436638acc7c010349a69c3395f1a57c642dc62Ying Wang     log10(x).  */
140605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  l *= 0.30102999566398119523;
140705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Round down to the next integer.  */
140805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return (int) l + (l < 0 ? -1 : 0);
140905436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
141005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
141105436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
141205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
141305436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if NEED_PRINTF_DOUBLE
141405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
141505436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Assuming x is finite and > 0:
141605436638acc7c010349a69c3395f1a57c642dc62Ying Wang   Return an approximation for n with 10^n <= x < 10^(n+1).
141705436638acc7c010349a69c3395f1a57c642dc62Ying Wang   The approximation is usually the right n, but may be off by 1 sometimes.  */
141805436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic int
141905436638acc7c010349a69c3395f1a57c642dc62Ying Wangfloorlog10 (double x)
142005436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
142105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  int exp;
142205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  double y;
142305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  double z;
142405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  double l;
142505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
142605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Split into exponential part and mantissa.  */
142705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  y = frexp (x, &exp);
142805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (!(y >= 0.0 && y < 1.0))
142905436638acc7c010349a69c3395f1a57c642dc62Ying Wang    abort ();
143005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (y == 0.0)
143105436638acc7c010349a69c3395f1a57c642dc62Ying Wang    return INT_MIN;
143205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (y < 0.5)
143305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
143405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      while (y < (1.0 / (1 << (GMP_LIMB_BITS / 2)) / (1 << (GMP_LIMB_BITS / 2))))
143505436638acc7c010349a69c3395f1a57c642dc62Ying Wang        {
143605436638acc7c010349a69c3395f1a57c642dc62Ying Wang          y *= 1.0 * (1 << (GMP_LIMB_BITS / 2)) * (1 << (GMP_LIMB_BITS / 2));
143705436638acc7c010349a69c3395f1a57c642dc62Ying Wang          exp -= GMP_LIMB_BITS;
143805436638acc7c010349a69c3395f1a57c642dc62Ying Wang        }
143905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (y < (1.0 / (1 << 16)))
144005436638acc7c010349a69c3395f1a57c642dc62Ying Wang        {
144105436638acc7c010349a69c3395f1a57c642dc62Ying Wang          y *= 1.0 * (1 << 16);
144205436638acc7c010349a69c3395f1a57c642dc62Ying Wang          exp -= 16;
144305436638acc7c010349a69c3395f1a57c642dc62Ying Wang        }
144405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (y < (1.0 / (1 << 8)))
144505436638acc7c010349a69c3395f1a57c642dc62Ying Wang        {
144605436638acc7c010349a69c3395f1a57c642dc62Ying Wang          y *= 1.0 * (1 << 8);
144705436638acc7c010349a69c3395f1a57c642dc62Ying Wang          exp -= 8;
144805436638acc7c010349a69c3395f1a57c642dc62Ying Wang        }
144905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (y < (1.0 / (1 << 4)))
145005436638acc7c010349a69c3395f1a57c642dc62Ying Wang        {
145105436638acc7c010349a69c3395f1a57c642dc62Ying Wang          y *= 1.0 * (1 << 4);
145205436638acc7c010349a69c3395f1a57c642dc62Ying Wang          exp -= 4;
145305436638acc7c010349a69c3395f1a57c642dc62Ying Wang        }
145405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (y < (1.0 / (1 << 2)))
145505436638acc7c010349a69c3395f1a57c642dc62Ying Wang        {
145605436638acc7c010349a69c3395f1a57c642dc62Ying Wang          y *= 1.0 * (1 << 2);
145705436638acc7c010349a69c3395f1a57c642dc62Ying Wang          exp -= 2;
145805436638acc7c010349a69c3395f1a57c642dc62Ying Wang        }
145905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (y < (1.0 / (1 << 1)))
146005436638acc7c010349a69c3395f1a57c642dc62Ying Wang        {
146105436638acc7c010349a69c3395f1a57c642dc62Ying Wang          y *= 1.0 * (1 << 1);
146205436638acc7c010349a69c3395f1a57c642dc62Ying Wang          exp -= 1;
146305436638acc7c010349a69c3395f1a57c642dc62Ying Wang        }
146405436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
146505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (!(y >= 0.5 && y < 1.0))
146605436638acc7c010349a69c3395f1a57c642dc62Ying Wang    abort ();
146705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Compute an approximation for l = log2(x) = exp + log2(y).  */
146805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  l = exp;
146905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  z = y;
147005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (z < 0.70710678118654752444)
147105436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
147205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      z *= 1.4142135623730950488;
147305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      l -= 0.5;
147405436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
147505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (z < 0.8408964152537145431)
147605436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
147705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      z *= 1.1892071150027210667;
147805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      l -= 0.25;
147905436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
148005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (z < 0.91700404320467123175)
148105436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
148205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      z *= 1.0905077326652576592;
148305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      l -= 0.125;
148405436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
148505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (z < 0.9576032806985736469)
148605436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
148705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      z *= 1.0442737824274138403;
148805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      l -= 0.0625;
148905436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
149005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Now 0.95 <= z <= 1.01.  */
149105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  z = 1 - z;
149205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* log2(1-z) = 1/log(2) * (- z - z^2/2 - z^3/3 - z^4/4 - ...)
149305436638acc7c010349a69c3395f1a57c642dc62Ying Wang     Four terms are enough to get an approximation with error < 10^-7.  */
149405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  l -= 1.4426950408889634074 * z * (1.0 + z * (0.5 + z * ((1.0 / 3) + z * 0.25)));
149505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Finally multiply with log(2)/log(10), yields an approximation for
149605436638acc7c010349a69c3395f1a57c642dc62Ying Wang     log10(x).  */
149705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  l *= 0.30102999566398119523;
149805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Round down to the next integer.  */
149905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return (int) l + (l < 0 ? -1 : 0);
150005436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
150105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
150205436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
150305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
150405436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Tests whether a string of digits consists of exactly PRECISION zeroes and
150505436638acc7c010349a69c3395f1a57c642dc62Ying Wang   a single '1' digit.  */
150605436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic int
150705436638acc7c010349a69c3395f1a57c642dc62Ying Wangis_borderline (const char *digits, size_t precision)
150805436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
150905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  for (; precision > 0; precision--, digits++)
151005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    if (*digits != '0')
151105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      return 0;
151205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (*digits != '1')
151305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    return 0;
151405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  digits++;
151505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return *digits == '\0';
151605436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
151705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
151805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
151905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
152005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99
152105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
152205436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Use a different function name, to make it possible that the 'wchar_t'
152305436638acc7c010349a69c3395f1a57c642dc62Ying Wang   parametrization and the 'char' parametrization get compiled in the same
152405436638acc7c010349a69c3395f1a57c642dc62Ying Wang   translation unit.  */
152505436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if WIDE_CHAR_VERSION
152605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  define MAX_ROOM_NEEDED wmax_room_needed
152705436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else
152805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  define MAX_ROOM_NEEDED max_room_needed
152905436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
153005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
153105436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Returns the number of TCHAR_T units needed as temporary space for the result
153205436638acc7c010349a69c3395f1a57c642dc62Ying Wang   of sprintf or SNPRINTF of a single conversion directive.  */
153305436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic size_t
153405436638acc7c010349a69c3395f1a57c642dc62Ying WangMAX_ROOM_NEEDED (const arguments *ap, size_t arg_index, FCHAR_T conversion,
153505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                 arg_type type, int flags, size_t width, int has_precision,
153605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                 size_t precision, int pad_ourselves)
153705436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
153805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  size_t tmp_length;
153905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
154005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  switch (conversion)
154105436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
154205436638acc7c010349a69c3395f1a57c642dc62Ying Wang    case 'd': case 'i': case 'u':
154305436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if HAVE_LONG_LONG_INT
154405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
154505436638acc7c010349a69c3395f1a57c642dc62Ying Wang        tmp_length =
154605436638acc7c010349a69c3395f1a57c642dc62Ying Wang          (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
154705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          * 0.30103 /* binary -> decimal */
154805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                         )
154905436638acc7c010349a69c3395f1a57c642dc62Ying Wang          + 1; /* turn floor into ceil */
155005436638acc7c010349a69c3395f1a57c642dc62Ying Wang      else
155105436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
155205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
155305436638acc7c010349a69c3395f1a57c642dc62Ying Wang        tmp_length =
155405436638acc7c010349a69c3395f1a57c642dc62Ying Wang          (unsigned int) (sizeof (unsigned long) * CHAR_BIT
155505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          * 0.30103 /* binary -> decimal */
155605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                         )
155705436638acc7c010349a69c3395f1a57c642dc62Ying Wang          + 1; /* turn floor into ceil */
155805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      else
155905436638acc7c010349a69c3395f1a57c642dc62Ying Wang        tmp_length =
156005436638acc7c010349a69c3395f1a57c642dc62Ying Wang          (unsigned int) (sizeof (unsigned int) * CHAR_BIT
156105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          * 0.30103 /* binary -> decimal */
156205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                         )
156305436638acc7c010349a69c3395f1a57c642dc62Ying Wang          + 1; /* turn floor into ceil */
156405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (tmp_length < precision)
156505436638acc7c010349a69c3395f1a57c642dc62Ying Wang        tmp_length = precision;
156605436638acc7c010349a69c3395f1a57c642dc62Ying Wang      /* Multiply by 2, as an estimate for FLAG_GROUP.  */
156705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      tmp_length = xsum (tmp_length, tmp_length);
156805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      /* Add 1, to account for a leading sign.  */
156905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      tmp_length = xsum (tmp_length, 1);
157005436638acc7c010349a69c3395f1a57c642dc62Ying Wang      break;
157105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
157205436638acc7c010349a69c3395f1a57c642dc62Ying Wang    case 'o':
157305436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if HAVE_LONG_LONG_INT
157405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
157505436638acc7c010349a69c3395f1a57c642dc62Ying Wang        tmp_length =
157605436638acc7c010349a69c3395f1a57c642dc62Ying Wang          (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
157705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          * 0.333334 /* binary -> octal */
157805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                         )
157905436638acc7c010349a69c3395f1a57c642dc62Ying Wang          + 1; /* turn floor into ceil */
158005436638acc7c010349a69c3395f1a57c642dc62Ying Wang      else
158105436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
158205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
158305436638acc7c010349a69c3395f1a57c642dc62Ying Wang        tmp_length =
158405436638acc7c010349a69c3395f1a57c642dc62Ying Wang          (unsigned int) (sizeof (unsigned long) * CHAR_BIT
158505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          * 0.333334 /* binary -> octal */
158605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                         )
158705436638acc7c010349a69c3395f1a57c642dc62Ying Wang          + 1; /* turn floor into ceil */
158805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      else
158905436638acc7c010349a69c3395f1a57c642dc62Ying Wang        tmp_length =
159005436638acc7c010349a69c3395f1a57c642dc62Ying Wang          (unsigned int) (sizeof (unsigned int) * CHAR_BIT
159105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          * 0.333334 /* binary -> octal */
159205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                         )
159305436638acc7c010349a69c3395f1a57c642dc62Ying Wang          + 1; /* turn floor into ceil */
159405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (tmp_length < precision)
159505436638acc7c010349a69c3395f1a57c642dc62Ying Wang        tmp_length = precision;
159605436638acc7c010349a69c3395f1a57c642dc62Ying Wang      /* Add 1, to account for a leading sign.  */
159705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      tmp_length = xsum (tmp_length, 1);
159805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      break;
159905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
160005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    case 'x': case 'X':
160105436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if HAVE_LONG_LONG_INT
160205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
160305436638acc7c010349a69c3395f1a57c642dc62Ying Wang        tmp_length =
160405436638acc7c010349a69c3395f1a57c642dc62Ying Wang          (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
160505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          * 0.25 /* binary -> hexadecimal */
160605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                         )
160705436638acc7c010349a69c3395f1a57c642dc62Ying Wang          + 1; /* turn floor into ceil */
160805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      else
160905436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
161005436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
161105436638acc7c010349a69c3395f1a57c642dc62Ying Wang        tmp_length =
161205436638acc7c010349a69c3395f1a57c642dc62Ying Wang          (unsigned int) (sizeof (unsigned long) * CHAR_BIT
161305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          * 0.25 /* binary -> hexadecimal */
161405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                         )
161505436638acc7c010349a69c3395f1a57c642dc62Ying Wang          + 1; /* turn floor into ceil */
161605436638acc7c010349a69c3395f1a57c642dc62Ying Wang      else
161705436638acc7c010349a69c3395f1a57c642dc62Ying Wang        tmp_length =
161805436638acc7c010349a69c3395f1a57c642dc62Ying Wang          (unsigned int) (sizeof (unsigned int) * CHAR_BIT
161905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          * 0.25 /* binary -> hexadecimal */
162005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                         )
162105436638acc7c010349a69c3395f1a57c642dc62Ying Wang          + 1; /* turn floor into ceil */
162205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (tmp_length < precision)
162305436638acc7c010349a69c3395f1a57c642dc62Ying Wang        tmp_length = precision;
162405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      /* Add 2, to account for a leading sign or alternate form.  */
162505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      tmp_length = xsum (tmp_length, 2);
162605436638acc7c010349a69c3395f1a57c642dc62Ying Wang      break;
162705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
162805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    case 'f': case 'F':
162905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (type == TYPE_LONGDOUBLE)
163005436638acc7c010349a69c3395f1a57c642dc62Ying Wang        tmp_length =
163105436638acc7c010349a69c3395f1a57c642dc62Ying Wang          (unsigned int) (LDBL_MAX_EXP
163205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          * 0.30103 /* binary -> decimal */
163305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          * 2 /* estimate for FLAG_GROUP */
163405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                         )
163505436638acc7c010349a69c3395f1a57c642dc62Ying Wang          + 1 /* turn floor into ceil */
163605436638acc7c010349a69c3395f1a57c642dc62Ying Wang          + 10; /* sign, decimal point etc. */
163705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      else
163805436638acc7c010349a69c3395f1a57c642dc62Ying Wang        tmp_length =
163905436638acc7c010349a69c3395f1a57c642dc62Ying Wang          (unsigned int) (DBL_MAX_EXP
164005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          * 0.30103 /* binary -> decimal */
164105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          * 2 /* estimate for FLAG_GROUP */
164205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                         )
164305436638acc7c010349a69c3395f1a57c642dc62Ying Wang          + 1 /* turn floor into ceil */
164405436638acc7c010349a69c3395f1a57c642dc62Ying Wang          + 10; /* sign, decimal point etc. */
164505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      tmp_length = xsum (tmp_length, precision);
164605436638acc7c010349a69c3395f1a57c642dc62Ying Wang      break;
164705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
164805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    case 'e': case 'E': case 'g': case 'G':
164905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      tmp_length =
165005436638acc7c010349a69c3395f1a57c642dc62Ying Wang        12; /* sign, decimal point, exponent etc. */
165105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      tmp_length = xsum (tmp_length, precision);
165205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      break;
165305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
165405436638acc7c010349a69c3395f1a57c642dc62Ying Wang    case 'a': case 'A':
165505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (type == TYPE_LONGDOUBLE)
165605436638acc7c010349a69c3395f1a57c642dc62Ying Wang        tmp_length =
165705436638acc7c010349a69c3395f1a57c642dc62Ying Wang          (unsigned int) (LDBL_DIG
165805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          * 0.831 /* decimal -> hexadecimal */
165905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                         )
166005436638acc7c010349a69c3395f1a57c642dc62Ying Wang          + 1; /* turn floor into ceil */
166105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      else
166205436638acc7c010349a69c3395f1a57c642dc62Ying Wang        tmp_length =
166305436638acc7c010349a69c3395f1a57c642dc62Ying Wang          (unsigned int) (DBL_DIG
166405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          * 0.831 /* decimal -> hexadecimal */
166505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                         )
166605436638acc7c010349a69c3395f1a57c642dc62Ying Wang          + 1; /* turn floor into ceil */
166705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (tmp_length < precision)
166805436638acc7c010349a69c3395f1a57c642dc62Ying Wang        tmp_length = precision;
166905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      /* Account for sign, decimal point etc. */
167005436638acc7c010349a69c3395f1a57c642dc62Ying Wang      tmp_length = xsum (tmp_length, 12);
167105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      break;
167205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
167305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    case 'c':
167405436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if HAVE_WINT_T && !WIDE_CHAR_VERSION
167505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (type == TYPE_WIDE_CHAR)
167605436638acc7c010349a69c3395f1a57c642dc62Ying Wang        tmp_length = MB_CUR_MAX;
167705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      else
167805436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
167905436638acc7c010349a69c3395f1a57c642dc62Ying Wang        tmp_length = 1;
168005436638acc7c010349a69c3395f1a57c642dc62Ying Wang      break;
168105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
168205436638acc7c010349a69c3395f1a57c642dc62Ying Wang    case 's':
168305436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if HAVE_WCHAR_T
168405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (type == TYPE_WIDE_STRING)
168505436638acc7c010349a69c3395f1a57c642dc62Ying Wang        {
168605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if WIDE_CHAR_VERSION
168705436638acc7c010349a69c3395f1a57c642dc62Ying Wang          /* ISO C says about %ls in fwprintf:
168805436638acc7c010349a69c3395f1a57c642dc62Ying Wang               "If the precision is not specified or is greater than the size
168905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                of the array, the array shall contain a null wide character."
169005436638acc7c010349a69c3395f1a57c642dc62Ying Wang             So if there is a precision, we must not use wcslen.  */
169105436638acc7c010349a69c3395f1a57c642dc62Ying Wang          const wchar_t *arg = ap->arg[arg_index].a.a_wide_string;
169205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
169305436638acc7c010349a69c3395f1a57c642dc62Ying Wang          if (has_precision)
169405436638acc7c010349a69c3395f1a57c642dc62Ying Wang            tmp_length = local_wcsnlen (arg, precision);
169505436638acc7c010349a69c3395f1a57c642dc62Ying Wang          else
169605436638acc7c010349a69c3395f1a57c642dc62Ying Wang            tmp_length = local_wcslen (arg);
169705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  else
169805436638acc7c010349a69c3395f1a57c642dc62Ying Wang          /* ISO C says about %ls in fprintf:
169905436638acc7c010349a69c3395f1a57c642dc62Ying Wang               "If a precision is specified, no more than that many bytes are
170005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                written (including shift sequences, if any), and the array
170105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                shall contain a null wide character if, to equal the multibyte
170205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                character sequence length given by the precision, the function
170305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                would need to access a wide character one past the end of the
170405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                array."
170505436638acc7c010349a69c3395f1a57c642dc62Ying Wang             So if there is a precision, we must not use wcslen.  */
170605436638acc7c010349a69c3395f1a57c642dc62Ying Wang          /* This case has already been handled separately in VASNPRINTF.  */
170705436638acc7c010349a69c3395f1a57c642dc62Ying Wang          abort ();
170805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
170905436638acc7c010349a69c3395f1a57c642dc62Ying Wang        }
171005436638acc7c010349a69c3395f1a57c642dc62Ying Wang      else
171105436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
171205436638acc7c010349a69c3395f1a57c642dc62Ying Wang        {
171305436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if WIDE_CHAR_VERSION
171405436638acc7c010349a69c3395f1a57c642dc62Ying Wang          /* ISO C says about %s in fwprintf:
171505436638acc7c010349a69c3395f1a57c642dc62Ying Wang               "If the precision is not specified or is greater than the size
171605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                of the converted array, the converted array shall contain a
171705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                null wide character."
171805436638acc7c010349a69c3395f1a57c642dc62Ying Wang             So if there is a precision, we must not use strlen.  */
171905436638acc7c010349a69c3395f1a57c642dc62Ying Wang          /* This case has already been handled separately in VASNPRINTF.  */
172005436638acc7c010349a69c3395f1a57c642dc62Ying Wang          abort ();
172105436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else
172205436638acc7c010349a69c3395f1a57c642dc62Ying Wang          /* ISO C says about %s in fprintf:
172305436638acc7c010349a69c3395f1a57c642dc62Ying Wang               "If the precision is not specified or greater than the size of
172405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                the array, the array shall contain a null character."
172505436638acc7c010349a69c3395f1a57c642dc62Ying Wang             So if there is a precision, we must not use strlen.  */
172605436638acc7c010349a69c3395f1a57c642dc62Ying Wang          const char *arg = ap->arg[arg_index].a.a_string;
172705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
172805436638acc7c010349a69c3395f1a57c642dc62Ying Wang          if (has_precision)
172905436638acc7c010349a69c3395f1a57c642dc62Ying Wang            tmp_length = local_strnlen (arg, precision);
173005436638acc7c010349a69c3395f1a57c642dc62Ying Wang          else
173105436638acc7c010349a69c3395f1a57c642dc62Ying Wang            tmp_length = strlen (arg);
173205436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
173305436638acc7c010349a69c3395f1a57c642dc62Ying Wang        }
173405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      break;
173505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
173605436638acc7c010349a69c3395f1a57c642dc62Ying Wang    case 'p':
173705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      tmp_length =
173805436638acc7c010349a69c3395f1a57c642dc62Ying Wang        (unsigned int) (sizeof (void *) * CHAR_BIT
173905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        * 0.25 /* binary -> hexadecimal */
174005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                       )
174105436638acc7c010349a69c3395f1a57c642dc62Ying Wang          + 1 /* turn floor into ceil */
174205436638acc7c010349a69c3395f1a57c642dc62Ying Wang          + 2; /* account for leading 0x */
174305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      break;
174405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
174505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    default:
174605436638acc7c010349a69c3395f1a57c642dc62Ying Wang      abort ();
174705436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
174805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
174905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (!pad_ourselves)
175005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
175105436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if ENABLE_UNISTDIO
175205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      /* Padding considers the number of characters, therefore the number of
175305436638acc7c010349a69c3395f1a57c642dc62Ying Wang         elements after padding may be
175405436638acc7c010349a69c3395f1a57c642dc62Ying Wang           > max (tmp_length, width)
175505436638acc7c010349a69c3395f1a57c642dc62Ying Wang         but is certainly
175605436638acc7c010349a69c3395f1a57c642dc62Ying Wang           <= tmp_length + width.  */
175705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      tmp_length = xsum (tmp_length, width);
175805436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else
175905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      /* Padding considers the number of elements, says POSIX.  */
176005436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (tmp_length < width)
176105436638acc7c010349a69c3395f1a57c642dc62Ying Wang        tmp_length = width;
176205436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
176305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
176405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
176505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
176605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
176705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return tmp_length;
176805436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
176905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
177005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
177105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
177205436638acc7c010349a69c3395f1a57c642dc62Ying WangDCHAR_T *
177305436638acc7c010349a69c3395f1a57c642dc62Ying WangVASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
177405436638acc7c010349a69c3395f1a57c642dc62Ying Wang            const FCHAR_T *format, va_list args)
177505436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
177605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  DIRECTIVES d;
177705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  arguments a;
177805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
177905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (PRINTF_PARSE (format, &d, &a) < 0)
178005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    /* errno is already set.  */
178105436638acc7c010349a69c3395f1a57c642dc62Ying Wang    return NULL;
178205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
178305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define CLEANUP() \
178405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (d.dir != d.direct_alloc_dir)                                      \
178505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    free (d.dir);                                                       \
178605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (a.arg != a.direct_alloc_arg)                                      \
178705436638acc7c010349a69c3395f1a57c642dc62Ying Wang    free (a.arg);
178805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
178905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (PRINTF_FETCHARGS (args, &a) < 0)
179005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
179105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      CLEANUP ();
179205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      errno = EINVAL;
179305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      return NULL;
179405436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
179505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
179605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  {
179705436638acc7c010349a69c3395f1a57c642dc62Ying Wang    size_t buf_neededlength;
179805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    TCHAR_T *buf;
179905436638acc7c010349a69c3395f1a57c642dc62Ying Wang    TCHAR_T *buf_malloced;
180005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    const FCHAR_T *cp;
180105436638acc7c010349a69c3395f1a57c642dc62Ying Wang    size_t i;
180205436638acc7c010349a69c3395f1a57c642dc62Ying Wang    DIRECTIVE *dp;
180305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    /* Output string accumulator.  */
180405436638acc7c010349a69c3395f1a57c642dc62Ying Wang    DCHAR_T *result;
180505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    size_t allocated;
180605436638acc7c010349a69c3395f1a57c642dc62Ying Wang    size_t length;
180705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
180805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    /* Allocate a small buffer that will hold a directive passed to
180905436638acc7c010349a69c3395f1a57c642dc62Ying Wang       sprintf or snprintf.  */
181005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    buf_neededlength =
181105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      xsum4 (7, d.max_width_length, d.max_precision_length, 6);
181205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if HAVE_ALLOCA
181305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    if (buf_neededlength < 4000 / sizeof (TCHAR_T))
181405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      {
181505436638acc7c010349a69c3395f1a57c642dc62Ying Wang        buf = (TCHAR_T *) alloca (buf_neededlength * sizeof (TCHAR_T));
181605436638acc7c010349a69c3395f1a57c642dc62Ying Wang        buf_malloced = NULL;
181705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      }
181805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    else
181905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
182005436638acc7c010349a69c3395f1a57c642dc62Ying Wang      {
182105436638acc7c010349a69c3395f1a57c642dc62Ying Wang        size_t buf_memsize = xtimes (buf_neededlength, sizeof (TCHAR_T));
182205436638acc7c010349a69c3395f1a57c642dc62Ying Wang        if (size_overflow_p (buf_memsize))
182305436638acc7c010349a69c3395f1a57c642dc62Ying Wang          goto out_of_memory_1;
182405436638acc7c010349a69c3395f1a57c642dc62Ying Wang        buf = (TCHAR_T *) malloc (buf_memsize);
182505436638acc7c010349a69c3395f1a57c642dc62Ying Wang        if (buf == NULL)
182605436638acc7c010349a69c3395f1a57c642dc62Ying Wang          goto out_of_memory_1;
182705436638acc7c010349a69c3395f1a57c642dc62Ying Wang        buf_malloced = buf;
182805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      }
182905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
183005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    if (resultbuf != NULL)
183105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      {
183205436638acc7c010349a69c3395f1a57c642dc62Ying Wang        result = resultbuf;
183305436638acc7c010349a69c3395f1a57c642dc62Ying Wang        allocated = *lengthp;
183405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      }
183505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    else
183605436638acc7c010349a69c3395f1a57c642dc62Ying Wang      {
183705436638acc7c010349a69c3395f1a57c642dc62Ying Wang        result = NULL;
183805436638acc7c010349a69c3395f1a57c642dc62Ying Wang        allocated = 0;
183905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      }
184005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    length = 0;
184105436638acc7c010349a69c3395f1a57c642dc62Ying Wang    /* Invariants:
184205436638acc7c010349a69c3395f1a57c642dc62Ying Wang       result is either == resultbuf or == NULL or malloc-allocated.
184305436638acc7c010349a69c3395f1a57c642dc62Ying Wang       If length > 0, then result != NULL.  */
184405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
184505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    /* Ensures that allocated >= needed.  Aborts through a jump to
184605436638acc7c010349a69c3395f1a57c642dc62Ying Wang       out_of_memory if needed is SIZE_MAX or otherwise too big.  */
184705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define ENSURE_ALLOCATION(needed) \
184805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    if ((needed) > allocated)                                                \
184905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      {                                                                      \
185005436638acc7c010349a69c3395f1a57c642dc62Ying Wang        size_t memory_size;                                                  \
185105436638acc7c010349a69c3395f1a57c642dc62Ying Wang        DCHAR_T *memory;                                                     \
185205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                                             \
185305436638acc7c010349a69c3395f1a57c642dc62Ying Wang        allocated = (allocated > 0 ? xtimes (allocated, 2) : 12);            \
185405436638acc7c010349a69c3395f1a57c642dc62Ying Wang        if ((needed) > allocated)                                            \
185505436638acc7c010349a69c3395f1a57c642dc62Ying Wang          allocated = (needed);                                              \
185605436638acc7c010349a69c3395f1a57c642dc62Ying Wang        memory_size = xtimes (allocated, sizeof (DCHAR_T));                  \
185705436638acc7c010349a69c3395f1a57c642dc62Ying Wang        if (size_overflow_p (memory_size))                                   \
185805436638acc7c010349a69c3395f1a57c642dc62Ying Wang          goto out_of_memory;                                                \
185905436638acc7c010349a69c3395f1a57c642dc62Ying Wang        if (result == resultbuf || result == NULL)                           \
186005436638acc7c010349a69c3395f1a57c642dc62Ying Wang          memory = (DCHAR_T *) malloc (memory_size);                         \
186105436638acc7c010349a69c3395f1a57c642dc62Ying Wang        else                                                                 \
186205436638acc7c010349a69c3395f1a57c642dc62Ying Wang          memory = (DCHAR_T *) realloc (result, memory_size);                \
186305436638acc7c010349a69c3395f1a57c642dc62Ying Wang        if (memory == NULL)                                                  \
186405436638acc7c010349a69c3395f1a57c642dc62Ying Wang          goto out_of_memory;                                                \
186505436638acc7c010349a69c3395f1a57c642dc62Ying Wang        if (result == resultbuf && length > 0)                               \
186605436638acc7c010349a69c3395f1a57c642dc62Ying Wang          DCHAR_CPY (memory, result, length);                                \
186705436638acc7c010349a69c3395f1a57c642dc62Ying Wang        result = memory;                                                     \
186805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      }
186905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
187005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++)
187105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      {
187205436638acc7c010349a69c3395f1a57c642dc62Ying Wang        if (cp != dp->dir_start)
187305436638acc7c010349a69c3395f1a57c642dc62Ying Wang          {
187405436638acc7c010349a69c3395f1a57c642dc62Ying Wang            size_t n = dp->dir_start - cp;
187505436638acc7c010349a69c3395f1a57c642dc62Ying Wang            size_t augmented_length = xsum (length, n);
187605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
187705436638acc7c010349a69c3395f1a57c642dc62Ying Wang            ENSURE_ALLOCATION (augmented_length);
187805436638acc7c010349a69c3395f1a57c642dc62Ying Wang            /* This copies a piece of FCHAR_T[] into a DCHAR_T[].  Here we
187905436638acc7c010349a69c3395f1a57c642dc62Ying Wang               need that the format string contains only ASCII characters
188005436638acc7c010349a69c3395f1a57c642dc62Ying Wang               if FCHAR_T and DCHAR_T are not the same type.  */
188105436638acc7c010349a69c3395f1a57c642dc62Ying Wang            if (sizeof (FCHAR_T) == sizeof (DCHAR_T))
188205436638acc7c010349a69c3395f1a57c642dc62Ying Wang              {
188305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                DCHAR_CPY (result + length, (const DCHAR_T *) cp, n);
188405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                length = augmented_length;
188505436638acc7c010349a69c3395f1a57c642dc62Ying Wang              }
188605436638acc7c010349a69c3395f1a57c642dc62Ying Wang            else
188705436638acc7c010349a69c3395f1a57c642dc62Ying Wang              {
188805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                do
188905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  result[length++] = (unsigned char) *cp++;
189005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                while (--n > 0);
189105436638acc7c010349a69c3395f1a57c642dc62Ying Wang              }
189205436638acc7c010349a69c3395f1a57c642dc62Ying Wang          }
189305436638acc7c010349a69c3395f1a57c642dc62Ying Wang        if (i == d.count)
189405436638acc7c010349a69c3395f1a57c642dc62Ying Wang          break;
189505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
189605436638acc7c010349a69c3395f1a57c642dc62Ying Wang        /* Execute a single directive.  */
189705436638acc7c010349a69c3395f1a57c642dc62Ying Wang        if (dp->conversion == '%')
189805436638acc7c010349a69c3395f1a57c642dc62Ying Wang          {
189905436638acc7c010349a69c3395f1a57c642dc62Ying Wang            size_t augmented_length;
190005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
190105436638acc7c010349a69c3395f1a57c642dc62Ying Wang            if (!(dp->arg_index == ARG_NONE))
190205436638acc7c010349a69c3395f1a57c642dc62Ying Wang              abort ();
190305436638acc7c010349a69c3395f1a57c642dc62Ying Wang            augmented_length = xsum (length, 1);
190405436638acc7c010349a69c3395f1a57c642dc62Ying Wang            ENSURE_ALLOCATION (augmented_length);
190505436638acc7c010349a69c3395f1a57c642dc62Ying Wang            result[length] = '%';
190605436638acc7c010349a69c3395f1a57c642dc62Ying Wang            length = augmented_length;
190705436638acc7c010349a69c3395f1a57c642dc62Ying Wang          }
190805436638acc7c010349a69c3395f1a57c642dc62Ying Wang        else
190905436638acc7c010349a69c3395f1a57c642dc62Ying Wang          {
191005436638acc7c010349a69c3395f1a57c642dc62Ying Wang            if (!(dp->arg_index != ARG_NONE))
191105436638acc7c010349a69c3395f1a57c642dc62Ying Wang              abort ();
191205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
191305436638acc7c010349a69c3395f1a57c642dc62Ying Wang            if (dp->conversion == 'n')
191405436638acc7c010349a69c3395f1a57c642dc62Ying Wang              {
191505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                switch (a.arg[dp->arg_index].type)
191605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  {
191705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  case TYPE_COUNT_SCHAR_POINTER:
191805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    *a.arg[dp->arg_index].a.a_count_schar_pointer = length;
191905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    break;
192005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  case TYPE_COUNT_SHORT_POINTER:
192105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    *a.arg[dp->arg_index].a.a_count_short_pointer = length;
192205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    break;
192305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  case TYPE_COUNT_INT_POINTER:
192405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    *a.arg[dp->arg_index].a.a_count_int_pointer = length;
192505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    break;
192605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  case TYPE_COUNT_LONGINT_POINTER:
192705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    *a.arg[dp->arg_index].a.a_count_longint_pointer = length;
192805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    break;
192905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if HAVE_LONG_LONG_INT
193005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  case TYPE_COUNT_LONGLONGINT_POINTER:
193105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length;
193205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    break;
193305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
193405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  default:
193505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    abort ();
193605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  }
193705436638acc7c010349a69c3395f1a57c642dc62Ying Wang              }
193805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if ENABLE_UNISTDIO
193905436638acc7c010349a69c3395f1a57c642dc62Ying Wang            /* The unistdio extensions.  */
194005436638acc7c010349a69c3395f1a57c642dc62Ying Wang            else if (dp->conversion == 'U')
194105436638acc7c010349a69c3395f1a57c642dc62Ying Wang              {
194205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                arg_type type = a.arg[dp->arg_index].type;
194305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                int flags = dp->flags;
194405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                int has_width;
194505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                size_t width;
194605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                int has_precision;
194705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                size_t precision;
194805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
194905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                has_width = 0;
195005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                width = 0;
195105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (dp->width_start != dp->width_end)
195205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  {
195305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (dp->width_arg_index != ARG_NONE)
195405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
195505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        int arg;
195605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
195705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
195805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          abort ();
195905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        arg = a.arg[dp->width_arg_index].a.a_int;
196005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (arg < 0)
196105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
196205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            /* "A negative field width is taken as a '-' flag
196305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                followed by a positive field width."  */
196405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            flags |= FLAG_LEFT;
196505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            width = (unsigned int) (-arg);
196605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
196705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        else
196805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          width = arg;
196905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
197005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    else
197105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
197205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        const FCHAR_T *digitp = dp->width_start;
197305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
197405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        do
197505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          width = xsum (xtimes (width, 10), *digitp++ - '0');
197605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        while (digitp != dp->width_end);
197705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
197805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    has_width = 1;
197905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  }
198005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
198105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                has_precision = 0;
198205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                precision = 0;
198305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (dp->precision_start != dp->precision_end)
198405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  {
198505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (dp->precision_arg_index != ARG_NONE)
198605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
198705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        int arg;
198805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
198905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
199005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          abort ();
199105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        arg = a.arg[dp->precision_arg_index].a.a_int;
199205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        /* "A negative precision is taken as if the precision
199305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            were omitted."  */
199405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (arg >= 0)
199505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
199605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            precision = arg;
199705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            has_precision = 1;
199805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
199905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
200005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    else
200105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
200205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        const FCHAR_T *digitp = dp->precision_start + 1;
200305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
200405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        precision = 0;
200505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        while (digitp != dp->precision_end)
200605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          precision = xsum (xtimes (precision, 10), *digitp++ - '0');
200705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        has_precision = 1;
200805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
200905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  }
201005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
201105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                switch (type)
201205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  {
201305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  case TYPE_U8_STRING:
201405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    {
201505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      const uint8_t *arg = a.arg[dp->arg_index].a.a_u8_string;
201605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      const uint8_t *arg_end;
201705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      size_t characters;
201805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
201905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      if (has_precision)
202005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
202105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          /* Use only PRECISION characters, from the left.  */
202205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          arg_end = arg;
202305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          characters = 0;
202405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          for (; precision > 0; precision--)
202505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            {
202605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              int count = u8_strmblen (arg_end);
202705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              if (count == 0)
202805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                break;
202905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              if (count < 0)
203005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                {
203105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  if (!(result == resultbuf || result == NULL))
203205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    free (result);
203305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  if (buf_malloced != NULL)
203405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    free (buf_malloced);
203505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  CLEANUP ();
203605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  errno = EILSEQ;
203705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  return NULL;
203805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                }
203905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              arg_end += count;
204005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              characters++;
204105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            }
204205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
204305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      else if (has_width)
204405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
204505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          /* Use the entire string, and count the number of
204605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                             characters.  */
204705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          arg_end = arg;
204805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          characters = 0;
204905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          for (;;)
205005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            {
205105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              int count = u8_strmblen (arg_end);
205205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              if (count == 0)
205305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                break;
205405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              if (count < 0)
205505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                {
205605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  if (!(result == resultbuf || result == NULL))
205705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    free (result);
205805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  if (buf_malloced != NULL)
205905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    free (buf_malloced);
206005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  CLEANUP ();
206105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  errno = EILSEQ;
206205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  return NULL;
206305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                }
206405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              arg_end += count;
206505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              characters++;
206605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            }
206705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
206805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      else
206905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
207005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          /* Use the entire string.  */
207105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          arg_end = arg + u8_strlen (arg);
207205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          /* The number of characters doesn't matter.  */
207305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          characters = 0;
207405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
207505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
207605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      if (has_width && width > characters
207705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          && !(dp->flags & FLAG_LEFT))
207805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
207905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          size_t n = width - characters;
208005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          ENSURE_ALLOCATION (xsum (length, n));
208105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          DCHAR_SET (result + length, ' ', n);
208205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          length += n;
208305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
208405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
208505436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if DCHAR_IS_UINT8_T
208605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
208705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        size_t n = arg_end - arg;
208805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        ENSURE_ALLOCATION (xsum (length, n));
208905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        DCHAR_CPY (result + length, arg, n);
209005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        length += n;
209105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
209205436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else
209305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      { /* Convert.  */
209405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        DCHAR_T *converted = result + length;
209505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        size_t converted_len = allocated - length;
209605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if DCHAR_IS_TCHAR
209705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        /* Convert from UTF-8 to locale encoding.  */
209805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        converted =
209905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          u8_conv_to_encoding (locale_charset (),
210005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                               iconveh_question_mark,
210105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                               arg, arg_end - arg, NULL,
210205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                               converted, &converted_len);
210305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  else
210405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        /* Convert from UTF-8 to UTF-16/UTF-32.  */
210505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        converted =
210605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          U8_TO_DCHAR (arg, arg_end - arg,
210705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                       converted, &converted_len);
210805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
210905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (converted == NULL)
211005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
211105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            int saved_errno = errno;
211205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            if (!(result == resultbuf || result == NULL))
211305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              free (result);
211405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            if (buf_malloced != NULL)
211505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              free (buf_malloced);
211605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            CLEANUP ();
211705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            errno = saved_errno;
211805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            return NULL;
211905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
212005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (converted != result + length)
212105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
212205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            ENSURE_ALLOCATION (xsum (length, converted_len));
212305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            DCHAR_CPY (result + length, converted, converted_len);
212405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            free (converted);
212505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
212605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        length += converted_len;
212705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
212805436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
212905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
213005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      if (has_width && width > characters
213105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          && (dp->flags & FLAG_LEFT))
213205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
213305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          size_t n = width - characters;
213405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          ENSURE_ALLOCATION (xsum (length, n));
213505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          DCHAR_SET (result + length, ' ', n);
213605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          length += n;
213705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
213805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    }
213905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    break;
214005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
214105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  case TYPE_U16_STRING:
214205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    {
214305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      const uint16_t *arg = a.arg[dp->arg_index].a.a_u16_string;
214405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      const uint16_t *arg_end;
214505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      size_t characters;
214605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
214705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      if (has_precision)
214805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
214905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          /* Use only PRECISION characters, from the left.  */
215005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          arg_end = arg;
215105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          characters = 0;
215205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          for (; precision > 0; precision--)
215305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            {
215405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              int count = u16_strmblen (arg_end);
215505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              if (count == 0)
215605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                break;
215705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              if (count < 0)
215805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                {
215905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  if (!(result == resultbuf || result == NULL))
216005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    free (result);
216105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  if (buf_malloced != NULL)
216205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    free (buf_malloced);
216305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  CLEANUP ();
216405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  errno = EILSEQ;
216505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  return NULL;
216605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                }
216705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              arg_end += count;
216805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              characters++;
216905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            }
217005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
217105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      else if (has_width)
217205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
217305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          /* Use the entire string, and count the number of
217405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                             characters.  */
217505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          arg_end = arg;
217605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          characters = 0;
217705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          for (;;)
217805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            {
217905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              int count = u16_strmblen (arg_end);
218005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              if (count == 0)
218105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                break;
218205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              if (count < 0)
218305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                {
218405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  if (!(result == resultbuf || result == NULL))
218505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    free (result);
218605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  if (buf_malloced != NULL)
218705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    free (buf_malloced);
218805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  CLEANUP ();
218905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  errno = EILSEQ;
219005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  return NULL;
219105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                }
219205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              arg_end += count;
219305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              characters++;
219405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            }
219505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
219605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      else
219705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
219805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          /* Use the entire string.  */
219905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          arg_end = arg + u16_strlen (arg);
220005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          /* The number of characters doesn't matter.  */
220105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          characters = 0;
220205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
220305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
220405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      if (has_width && width > characters
220505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          && !(dp->flags & FLAG_LEFT))
220605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
220705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          size_t n = width - characters;
220805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          ENSURE_ALLOCATION (xsum (length, n));
220905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          DCHAR_SET (result + length, ' ', n);
221005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          length += n;
221105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
221205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
221305436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if DCHAR_IS_UINT16_T
221405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
221505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        size_t n = arg_end - arg;
221605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        ENSURE_ALLOCATION (xsum (length, n));
221705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        DCHAR_CPY (result + length, arg, n);
221805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        length += n;
221905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
222005436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else
222105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      { /* Convert.  */
222205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        DCHAR_T *converted = result + length;
222305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        size_t converted_len = allocated - length;
222405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if DCHAR_IS_TCHAR
222505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        /* Convert from UTF-16 to locale encoding.  */
222605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        converted =
222705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          u16_conv_to_encoding (locale_charset (),
222805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                iconveh_question_mark,
222905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                arg, arg_end - arg, NULL,
223005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                converted, &converted_len);
223105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  else
223205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        /* Convert from UTF-16 to UTF-8/UTF-32.  */
223305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        converted =
223405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          U16_TO_DCHAR (arg, arg_end - arg,
223505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        converted, &converted_len);
223605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
223705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (converted == NULL)
223805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
223905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            int saved_errno = errno;
224005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            if (!(result == resultbuf || result == NULL))
224105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              free (result);
224205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            if (buf_malloced != NULL)
224305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              free (buf_malloced);
224405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            CLEANUP ();
224505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            errno = saved_errno;
224605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            return NULL;
224705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
224805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (converted != result + length)
224905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
225005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            ENSURE_ALLOCATION (xsum (length, converted_len));
225105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            DCHAR_CPY (result + length, converted, converted_len);
225205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            free (converted);
225305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
225405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        length += converted_len;
225505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
225605436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
225705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
225805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      if (has_width && width > characters
225905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          && (dp->flags & FLAG_LEFT))
226005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
226105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          size_t n = width - characters;
226205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          ENSURE_ALLOCATION (xsum (length, n));
226305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          DCHAR_SET (result + length, ' ', n);
226405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          length += n;
226505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
226605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    }
226705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    break;
226805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
226905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  case TYPE_U32_STRING:
227005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    {
227105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      const uint32_t *arg = a.arg[dp->arg_index].a.a_u32_string;
227205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      const uint32_t *arg_end;
227305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      size_t characters;
227405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
227505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      if (has_precision)
227605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
227705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          /* Use only PRECISION characters, from the left.  */
227805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          arg_end = arg;
227905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          characters = 0;
228005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          for (; precision > 0; precision--)
228105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            {
228205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              int count = u32_strmblen (arg_end);
228305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              if (count == 0)
228405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                break;
228505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              if (count < 0)
228605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                {
228705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  if (!(result == resultbuf || result == NULL))
228805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    free (result);
228905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  if (buf_malloced != NULL)
229005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    free (buf_malloced);
229105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  CLEANUP ();
229205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  errno = EILSEQ;
229305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  return NULL;
229405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                }
229505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              arg_end += count;
229605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              characters++;
229705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            }
229805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
229905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      else if (has_width)
230005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
230105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          /* Use the entire string, and count the number of
230205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                             characters.  */
230305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          arg_end = arg;
230405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          characters = 0;
230505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          for (;;)
230605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            {
230705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              int count = u32_strmblen (arg_end);
230805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              if (count == 0)
230905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                break;
231005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              if (count < 0)
231105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                {
231205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  if (!(result == resultbuf || result == NULL))
231305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    free (result);
231405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  if (buf_malloced != NULL)
231505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    free (buf_malloced);
231605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  CLEANUP ();
231705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  errno = EILSEQ;
231805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  return NULL;
231905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                }
232005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              arg_end += count;
232105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              characters++;
232205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            }
232305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
232405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      else
232505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
232605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          /* Use the entire string.  */
232705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          arg_end = arg + u32_strlen (arg);
232805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          /* The number of characters doesn't matter.  */
232905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          characters = 0;
233005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
233105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
233205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      if (has_width && width > characters
233305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          && !(dp->flags & FLAG_LEFT))
233405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
233505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          size_t n = width - characters;
233605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          ENSURE_ALLOCATION (xsum (length, n));
233705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          DCHAR_SET (result + length, ' ', n);
233805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          length += n;
233905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
234005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
234105436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if DCHAR_IS_UINT32_T
234205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
234305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        size_t n = arg_end - arg;
234405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        ENSURE_ALLOCATION (xsum (length, n));
234505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        DCHAR_CPY (result + length, arg, n);
234605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        length += n;
234705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
234805436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else
234905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      { /* Convert.  */
235005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        DCHAR_T *converted = result + length;
235105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        size_t converted_len = allocated - length;
235205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if DCHAR_IS_TCHAR
235305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        /* Convert from UTF-32 to locale encoding.  */
235405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        converted =
235505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          u32_conv_to_encoding (locale_charset (),
235605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                iconveh_question_mark,
235705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                arg, arg_end - arg, NULL,
235805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                converted, &converted_len);
235905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  else
236005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        /* Convert from UTF-32 to UTF-8/UTF-16.  */
236105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        converted =
236205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          U32_TO_DCHAR (arg, arg_end - arg,
236305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        converted, &converted_len);
236405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
236505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (converted == NULL)
236605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
236705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            int saved_errno = errno;
236805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            if (!(result == resultbuf || result == NULL))
236905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              free (result);
237005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            if (buf_malloced != NULL)
237105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              free (buf_malloced);
237205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            CLEANUP ();
237305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            errno = saved_errno;
237405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            return NULL;
237505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
237605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (converted != result + length)
237705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
237805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            ENSURE_ALLOCATION (xsum (length, converted_len));
237905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            DCHAR_CPY (result + length, converted, converted_len);
238005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            free (converted);
238105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
238205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        length += converted_len;
238305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
238405436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
238505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
238605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      if (has_width && width > characters
238705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          && (dp->flags & FLAG_LEFT))
238805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
238905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          size_t n = width - characters;
239005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          ENSURE_ALLOCATION (xsum (length, n));
239105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          DCHAR_SET (result + length, ' ', n);
239205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          length += n;
239305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
239405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    }
239505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    break;
239605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
239705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  default:
239805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    abort ();
239905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  }
240005436638acc7c010349a69c3395f1a57c642dc62Ying Wang              }
240105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
240205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && HAVE_WCHAR_T
240305436638acc7c010349a69c3395f1a57c642dc62Ying Wang            else if (dp->conversion == 's'
240405436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if WIDE_CHAR_VERSION
240505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                     && a.arg[dp->arg_index].type != TYPE_WIDE_STRING
240605436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else
240705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                     && a.arg[dp->arg_index].type == TYPE_WIDE_STRING
240805436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
240905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    )
241005436638acc7c010349a69c3395f1a57c642dc62Ying Wang              {
241105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                /* The normal handling of the 's' directive below requires
241205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   allocating a temporary buffer.  The determination of its
241305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   length (tmp_length), in the case when a precision is
241405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   specified, below requires a conversion between a char[]
241505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   string and a wchar_t[] wide string.  It could be done, but
241605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   we have no guarantee that the implementation of sprintf will
241705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   use the exactly same algorithm.  Without this guarantee, it
241805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   is possible to have buffer overrun bugs.  In order to avoid
241905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   such bugs, we implement the entire processing of the 's'
242005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   directive ourselves.  */
242105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                int flags = dp->flags;
242205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                int has_width;
242305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                size_t width;
242405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                int has_precision;
242505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                size_t precision;
242605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
242705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                has_width = 0;
242805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                width = 0;
242905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (dp->width_start != dp->width_end)
243005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  {
243105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (dp->width_arg_index != ARG_NONE)
243205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
243305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        int arg;
243405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
243505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
243605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          abort ();
243705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        arg = a.arg[dp->width_arg_index].a.a_int;
243805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (arg < 0)
243905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
244005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            /* "A negative field width is taken as a '-' flag
244105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                followed by a positive field width."  */
244205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            flags |= FLAG_LEFT;
244305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            width = (unsigned int) (-arg);
244405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
244505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        else
244605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          width = arg;
244705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
244805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    else
244905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
245005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        const FCHAR_T *digitp = dp->width_start;
245105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
245205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        do
245305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          width = xsum (xtimes (width, 10), *digitp++ - '0');
245405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        while (digitp != dp->width_end);
245505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
245605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    has_width = 1;
245705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  }
245805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
245905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                has_precision = 0;
246005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                precision = 6;
246105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (dp->precision_start != dp->precision_end)
246205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  {
246305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (dp->precision_arg_index != ARG_NONE)
246405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
246505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        int arg;
246605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
246705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
246805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          abort ();
246905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        arg = a.arg[dp->precision_arg_index].a.a_int;
247005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        /* "A negative precision is taken as if the precision
247105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            were omitted."  */
247205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (arg >= 0)
247305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
247405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            precision = arg;
247505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            has_precision = 1;
247605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
247705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
247805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    else
247905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
248005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        const FCHAR_T *digitp = dp->precision_start + 1;
248105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
248205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        precision = 0;
248305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        while (digitp != dp->precision_end)
248405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          precision = xsum (xtimes (precision, 10), *digitp++ - '0');
248505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        has_precision = 1;
248605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
248705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  }
248805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
248905436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if WIDE_CHAR_VERSION
249005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                /* %s in vasnwprintf.  See the specification of fwprintf.  */
249105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                {
249205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  const char *arg = a.arg[dp->arg_index].a.a_string;
249305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  const char *arg_end;
249405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  size_t characters;
249505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
249605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  if (has_precision)
249705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    {
249805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      /* Use only as many bytes as needed to produce PRECISION
249905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                         wide characters, from the left.  */
250005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if HAVE_MBRTOWC
250105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      mbstate_t state;
250205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      memset (&state, '\0', sizeof (mbstate_t));
250305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
250405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      arg_end = arg;
250505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      characters = 0;
250605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      for (; precision > 0; precision--)
250705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
250805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          int count;
250905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if HAVE_MBRTOWC
251005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          count = mbrlen (arg_end, MB_CUR_MAX, &state);
251105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  else
251205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          count = mblen (arg_end, MB_CUR_MAX);
251305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
251405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          if (count == 0)
251505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            /* Found the terminating NUL.  */
251605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            break;
251705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          if (count < 0)
251805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            {
251905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              /* Invalid or incomplete multibyte character.  */
252005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              if (!(result == resultbuf || result == NULL))
252105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                free (result);
252205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              if (buf_malloced != NULL)
252305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                free (buf_malloced);
252405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              CLEANUP ();
252505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              errno = EILSEQ;
252605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              return NULL;
252705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            }
252805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          arg_end += count;
252905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          characters++;
253005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
253105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    }
253205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  else if (has_width)
253305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    {
253405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      /* Use the entire string, and count the number of wide
253505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                         characters.  */
253605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if HAVE_MBRTOWC
253705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      mbstate_t state;
253805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      memset (&state, '\0', sizeof (mbstate_t));
253905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
254005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      arg_end = arg;
254105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      characters = 0;
254205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      for (;;)
254305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
254405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          int count;
254505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if HAVE_MBRTOWC
254605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          count = mbrlen (arg_end, MB_CUR_MAX, &state);
254705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  else
254805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          count = mblen (arg_end, MB_CUR_MAX);
254905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
255005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          if (count == 0)
255105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            /* Found the terminating NUL.  */
255205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            break;
255305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          if (count < 0)
255405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            {
255505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              /* Invalid or incomplete multibyte character.  */
255605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              if (!(result == resultbuf || result == NULL))
255705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                free (result);
255805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              if (buf_malloced != NULL)
255905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                free (buf_malloced);
256005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              CLEANUP ();
256105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              errno = EILSEQ;
256205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              return NULL;
256305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            }
256405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          arg_end += count;
256505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          characters++;
256605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
256705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    }
256805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  else
256905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    {
257005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      /* Use the entire string.  */
257105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      arg_end = arg + strlen (arg);
257205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      /* The number of characters doesn't matter.  */
257305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      characters = 0;
257405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    }
257505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
257605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  if (has_width && width > characters
257705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      && !(dp->flags & FLAG_LEFT))
257805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    {
257905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      size_t n = width - characters;
258005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      ENSURE_ALLOCATION (xsum (length, n));
258105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      DCHAR_SET (result + length, ' ', n);
258205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      length += n;
258305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    }
258405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
258505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  if (has_precision || has_width)
258605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    {
258705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      /* We know the number of wide characters in advance.  */
258805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      size_t remaining;
258905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if HAVE_MBRTOWC
259005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      mbstate_t state;
259105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      memset (&state, '\0', sizeof (mbstate_t));
259205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
259305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      ENSURE_ALLOCATION (xsum (length, characters));
259405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      for (remaining = characters; remaining > 0; remaining--)
259505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
259605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          wchar_t wc;
259705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          int count;
259805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if HAVE_MBRTOWC
259905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          count = mbrtowc (&wc, arg, arg_end - arg, &state);
260005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  else
260105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          count = mbtowc (&wc, arg, arg_end - arg);
260205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
260305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          if (count <= 0)
260405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            /* mbrtowc not consistent with mbrlen, or mbtowc
260505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                               not consistent with mblen.  */
260605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            abort ();
260705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          result[length++] = wc;
260805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          arg += count;
260905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
261005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      if (!(arg == arg_end))
261105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        abort ();
261205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    }
261305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  else
261405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    {
261505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if HAVE_MBRTOWC
261605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      mbstate_t state;
261705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      memset (&state, '\0', sizeof (mbstate_t));
261805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
261905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      while (arg < arg_end)
262005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
262105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          wchar_t wc;
262205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          int count;
262305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if HAVE_MBRTOWC
262405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          count = mbrtowc (&wc, arg, arg_end - arg, &state);
262505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  else
262605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          count = mbtowc (&wc, arg, arg_end - arg);
262705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
262805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          if (count <= 0)
262905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            /* mbrtowc not consistent with mbrlen, or mbtowc
263005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                               not consistent with mblen.  */
263105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            abort ();
263205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          ENSURE_ALLOCATION (xsum (length, 1));
263305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          result[length++] = wc;
263405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          arg += count;
263505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
263605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    }
263705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
263805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  if (has_width && width > characters
263905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      && (dp->flags & FLAG_LEFT))
264005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    {
264105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      size_t n = width - characters;
264205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      ENSURE_ALLOCATION (xsum (length, n));
264305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      DCHAR_SET (result + length, ' ', n);
264405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      length += n;
264505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    }
264605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                }
264705436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else
264805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                /* %ls in vasnprintf.  See the specification of fprintf.  */
264905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                {
265005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
265105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  const wchar_t *arg_end;
265205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  size_t characters;
265305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if !DCHAR_IS_TCHAR
265405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  /* This code assumes that TCHAR_T is 'char'.  */
265505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  verify (sizeof (TCHAR_T) == 1);
265605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  TCHAR_T *tmpsrc;
265705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  DCHAR_T *tmpdst;
265805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  size_t tmpdst_len;
265905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
266005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  size_t w;
266105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
266205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  if (has_precision)
266305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    {
266405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      /* Use only as many wide characters as needed to produce
266505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                         at most PRECISION bytes, from the left.  */
266605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
266705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      mbstate_t state;
266805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      memset (&state, '\0', sizeof (mbstate_t));
266905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
267005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      arg_end = arg;
267105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      characters = 0;
267205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      while (precision > 0)
267305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
267405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          char cbuf[64]; /* Assume MB_CUR_MAX <= 64.  */
267505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          int count;
267605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
267705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          if (*arg_end == 0)
267805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            /* Found the terminating null wide character.  */
267905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            break;
268005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
268105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          count = wcrtomb (cbuf, *arg_end, &state);
268205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  else
268305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          count = wctomb (cbuf, *arg_end);
268405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
268505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          if (count < 0)
268605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            {
268705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              /* Cannot convert.  */
268805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              if (!(result == resultbuf || result == NULL))
268905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                free (result);
269005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              if (buf_malloced != NULL)
269105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                free (buf_malloced);
269205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              CLEANUP ();
269305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              errno = EILSEQ;
269405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              return NULL;
269505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            }
269605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          if (precision < count)
269705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            break;
269805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          arg_end++;
269905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          characters += count;
270005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          precision -= count;
270105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
270205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    }
270305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if DCHAR_IS_TCHAR
270405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  else if (has_width)
270505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  else
270605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  else
270705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
270805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    {
270905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      /* Use the entire string, and count the number of
271005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                         bytes.  */
271105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
271205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      mbstate_t state;
271305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      memset (&state, '\0', sizeof (mbstate_t));
271405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
271505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      arg_end = arg;
271605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      characters = 0;
271705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      for (;;)
271805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
271905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          char cbuf[64]; /* Assume MB_CUR_MAX <= 64.  */
272005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          int count;
272105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
272205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          if (*arg_end == 0)
272305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            /* Found the terminating null wide character.  */
272405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            break;
272505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
272605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          count = wcrtomb (cbuf, *arg_end, &state);
272705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  else
272805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          count = wctomb (cbuf, *arg_end);
272905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
273005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          if (count < 0)
273105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            {
273205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              /* Cannot convert.  */
273305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              if (!(result == resultbuf || result == NULL))
273405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                free (result);
273505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              if (buf_malloced != NULL)
273605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                free (buf_malloced);
273705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              CLEANUP ();
273805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              errno = EILSEQ;
273905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              return NULL;
274005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            }
274105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          arg_end++;
274205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          characters += count;
274305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
274405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    }
274505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if DCHAR_IS_TCHAR
274605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  else
274705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    {
274805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      /* Use the entire string.  */
274905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      arg_end = arg + local_wcslen (arg);
275005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      /* The number of bytes doesn't matter.  */
275105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      characters = 0;
275205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    }
275305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
275405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
275505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if !DCHAR_IS_TCHAR
275605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  /* Convert the string into a piece of temporary memory.  */
275705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  tmpsrc = (TCHAR_T *) malloc (characters * sizeof (TCHAR_T));
275805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  if (tmpsrc == NULL)
275905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    goto out_of_memory;
276005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  {
276105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    TCHAR_T *tmpptr = tmpsrc;
276205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    size_t remaining;
276305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
276405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    mbstate_t state;
276505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    memset (&state, '\0', sizeof (mbstate_t));
276605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   endif
276705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    for (remaining = characters; remaining > 0; )
276805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
276905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        char cbuf[64]; /* Assume MB_CUR_MAX <= 64.  */
277005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        int count;
277105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
277205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (*arg == 0)
277305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          abort ();
277405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
277505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        count = wcrtomb (cbuf, *arg, &state);
277605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   else
277705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        count = wctomb (cbuf, *arg);
277805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   endif
277905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (count <= 0)
278005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          /* Inconsistency.  */
278105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          abort ();
278205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        memcpy (tmpptr, cbuf, count);
278305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        tmpptr += count;
278405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        arg++;
278505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        remaining -= count;
278605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
278705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (!(arg == arg_end))
278805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      abort ();
278905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  }
279005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
279105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  /* Convert from TCHAR_T[] to DCHAR_T[].  */
279205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  tmpdst =
279305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    DCHAR_CONV_FROM_ENCODING (locale_charset (),
279405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                              iconveh_question_mark,
279505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                              tmpsrc, characters,
279605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                              NULL,
279705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                              NULL, &tmpdst_len);
279805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  if (tmpdst == NULL)
279905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    {
280005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      int saved_errno = errno;
280105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      free (tmpsrc);
280205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      if (!(result == resultbuf || result == NULL))
280305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        free (result);
280405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      if (buf_malloced != NULL)
280505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        free (buf_malloced);
280605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      CLEANUP ();
280705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      errno = saved_errno;
280805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      return NULL;
280905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    }
281005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  free (tmpsrc);
281105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
281205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
281305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  if (has_width)
281405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    {
281505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if ENABLE_UNISTDIO
281605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      /* Outside POSIX, it's preferable to compare the width
281705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                         against the number of _characters_ of the converted
281805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                         value.  */
281905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      w = DCHAR_MBSNLEN (result + length, characters);
282005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  else
282105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      /* The width is compared against the number of _bytes_
282205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                         of the converted value, says POSIX.  */
282305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      w = characters;
282405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
282505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    }
282605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  else
282705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    /* w doesn't matter.  */
282805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    w = 0;
282905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
283005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  if (has_width && width > w
283105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      && !(dp->flags & FLAG_LEFT))
283205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    {
283305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      size_t n = width - w;
283405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      ENSURE_ALLOCATION (xsum (length, n));
283505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      DCHAR_SET (result + length, ' ', n);
283605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      length += n;
283705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    }
283805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
283905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if DCHAR_IS_TCHAR
284005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  if (has_precision || has_width)
284105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    {
284205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      /* We know the number of bytes in advance.  */
284305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      size_t remaining;
284405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
284505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      mbstate_t state;
284605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      memset (&state, '\0', sizeof (mbstate_t));
284705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   endif
284805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      ENSURE_ALLOCATION (xsum (length, characters));
284905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      for (remaining = characters; remaining > 0; )
285005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
285105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          char cbuf[64]; /* Assume MB_CUR_MAX <= 64.  */
285205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          int count;
285305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
285405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          if (*arg == 0)
285505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            abort ();
285605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
285705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          count = wcrtomb (cbuf, *arg, &state);
285805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   else
285905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          count = wctomb (cbuf, *arg);
286005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   endif
286105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          if (count <= 0)
286205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            /* Inconsistency.  */
286305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            abort ();
286405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          memcpy (result + length, cbuf, count);
286505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          length += count;
286605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          arg++;
286705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          remaining -= count;
286805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
286905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      if (!(arg == arg_end))
287005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        abort ();
287105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    }
287205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  else
287305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    {
287405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
287505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      mbstate_t state;
287605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      memset (&state, '\0', sizeof (mbstate_t));
287705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   endif
287805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      while (arg < arg_end)
287905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
288005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          char cbuf[64]; /* Assume MB_CUR_MAX <= 64.  */
288105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          int count;
288205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
288305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          if (*arg == 0)
288405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            abort ();
288505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
288605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          count = wcrtomb (cbuf, *arg, &state);
288705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   else
288805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          count = wctomb (cbuf, *arg);
288905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   endif
289005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          if (count <= 0)
289105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            {
289205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              /* Cannot convert.  */
289305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              if (!(result == resultbuf || result == NULL))
289405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                free (result);
289505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              if (buf_malloced != NULL)
289605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                free (buf_malloced);
289705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              CLEANUP ();
289805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              errno = EILSEQ;
289905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              return NULL;
290005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            }
290105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          ENSURE_ALLOCATION (xsum (length, count));
290205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          memcpy (result + length, cbuf, count);
290305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          length += count;
290405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          arg++;
290505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
290605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    }
290705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  else
290805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  ENSURE_ALLOCATION (xsum (length, tmpdst_len));
290905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  DCHAR_CPY (result + length, tmpdst, tmpdst_len);
291005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  free (tmpdst);
291105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  length += tmpdst_len;
291205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
291305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
291405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  if (has_width && width > w
291505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      && (dp->flags & FLAG_LEFT))
291605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    {
291705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      size_t n = width - w;
291805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      ENSURE_ALLOCATION (xsum (length, n));
291905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      DCHAR_SET (result + length, ' ', n);
292005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      length += n;
292105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    }
292205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                }
292305436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
292405436638acc7c010349a69c3395f1a57c642dc62Ying Wang              }
292505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
292605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL
292705436638acc7c010349a69c3395f1a57c642dc62Ying Wang            else if ((dp->conversion == 'a' || dp->conversion == 'A')
292805436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if !(NEED_PRINTF_DIRECTIVE_A || (NEED_PRINTF_LONG_DOUBLE && NEED_PRINTF_DOUBLE))
292905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                     && (0
293005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if NEED_PRINTF_DOUBLE
293105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                         || a.arg[dp->arg_index].type == TYPE_DOUBLE
293205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
293305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if NEED_PRINTF_LONG_DOUBLE
293405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                         || a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
293505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
293605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        )
293705436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
293805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    )
293905436638acc7c010349a69c3395f1a57c642dc62Ying Wang              {
294005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                arg_type type = a.arg[dp->arg_index].type;
294105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                int flags = dp->flags;
294205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                int has_width;
294305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                size_t width;
294405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                int has_precision;
294505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                size_t precision;
294605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                size_t tmp_length;
294705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                DCHAR_T tmpbuf[700];
294805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                DCHAR_T *tmp;
294905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                DCHAR_T *pad_ptr;
295005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                DCHAR_T *p;
295105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
295205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                has_width = 0;
295305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                width = 0;
295405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (dp->width_start != dp->width_end)
295505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  {
295605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (dp->width_arg_index != ARG_NONE)
295705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
295805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        int arg;
295905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
296005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
296105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          abort ();
296205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        arg = a.arg[dp->width_arg_index].a.a_int;
296305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (arg < 0)
296405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
296505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            /* "A negative field width is taken as a '-' flag
296605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                followed by a positive field width."  */
296705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            flags |= FLAG_LEFT;
296805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            width = (unsigned int) (-arg);
296905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
297005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        else
297105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          width = arg;
297205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
297305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    else
297405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
297505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        const FCHAR_T *digitp = dp->width_start;
297605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
297705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        do
297805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          width = xsum (xtimes (width, 10), *digitp++ - '0');
297905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        while (digitp != dp->width_end);
298005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
298105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    has_width = 1;
298205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  }
298305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
298405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                has_precision = 0;
298505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                precision = 0;
298605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (dp->precision_start != dp->precision_end)
298705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  {
298805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (dp->precision_arg_index != ARG_NONE)
298905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
299005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        int arg;
299105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
299205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
299305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          abort ();
299405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        arg = a.arg[dp->precision_arg_index].a.a_int;
299505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        /* "A negative precision is taken as if the precision
299605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            were omitted."  */
299705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (arg >= 0)
299805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
299905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            precision = arg;
300005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            has_precision = 1;
300105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
300205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
300305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    else
300405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
300505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        const FCHAR_T *digitp = dp->precision_start + 1;
300605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
300705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        precision = 0;
300805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        while (digitp != dp->precision_end)
300905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          precision = xsum (xtimes (precision, 10), *digitp++ - '0');
301005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        has_precision = 1;
301105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
301205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  }
301305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
301405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                /* Allocate a temporary buffer of sufficient size.  */
301505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (type == TYPE_LONGDOUBLE)
301605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  tmp_length =
301705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    (unsigned int) ((LDBL_DIG + 1)
301805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    * 0.831 /* decimal -> hexadecimal */
301905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                   )
302005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    + 1; /* turn floor into ceil */
302105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                else
302205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  tmp_length =
302305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    (unsigned int) ((DBL_DIG + 1)
302405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    * 0.831 /* decimal -> hexadecimal */
302505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                   )
302605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    + 1; /* turn floor into ceil */
302705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (tmp_length < precision)
302805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  tmp_length = precision;
302905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                /* Account for sign, decimal point etc. */
303005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                tmp_length = xsum (tmp_length, 12);
303105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
303205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (tmp_length < width)
303305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  tmp_length = width;
303405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
303505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
303605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
303705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (tmp_length <= sizeof (tmpbuf) / sizeof (DCHAR_T))
303805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  tmp = tmpbuf;
303905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                else
304005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  {
304105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    size_t tmp_memsize = xtimes (tmp_length, sizeof (DCHAR_T));
304205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
304305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (size_overflow_p (tmp_memsize))
304405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      /* Overflow, would lead to out of memory.  */
304505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      goto out_of_memory;
304605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    tmp = (DCHAR_T *) malloc (tmp_memsize);
304705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (tmp == NULL)
304805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      /* Out of memory.  */
304905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      goto out_of_memory;
305005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  }
305105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
305205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                pad_ptr = NULL;
305305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                p = tmp;
305405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (type == TYPE_LONGDOUBLE)
305505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  {
305605436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE
305705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    long double arg = a.arg[dp->arg_index].a.a_longdouble;
305805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
305905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (isnanl (arg))
306005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
306105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (dp->conversion == 'A')
306205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
306305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
306405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
306505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        else
306605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
306705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
306805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
306905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
307005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    else
307105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
307205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        int sign = 0;
307305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        DECL_LONG_DOUBLE_ROUNDING
307405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
307505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        BEGIN_LONG_DOUBLE_ROUNDING ();
307605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
307705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (signbit (arg)) /* arg < 0.0L or negative zero */
307805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
307905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            sign = -1;
308005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            arg = -arg;
308105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
308205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
308305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (sign < 0)
308405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          *p++ = '-';
308505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        else if (flags & FLAG_SHOWSIGN)
308605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          *p++ = '+';
308705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        else if (flags & FLAG_SPACE)
308805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          *p++ = ' ';
308905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
309005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (arg > 0.0L && arg + arg == arg)
309105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
309205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            if (dp->conversion == 'A')
309305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              {
309405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
309505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              }
309605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            else
309705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              {
309805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
309905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              }
310005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
310105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        else
310205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
310305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            int exponent;
310405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            long double mantissa;
310505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
310605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            if (arg > 0.0L)
310705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              mantissa = printf_frexpl (arg, &exponent);
310805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            else
310905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              {
311005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                exponent = 0;
311105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                mantissa = 0.0L;
311205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              }
311305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
311405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            if (has_precision
311505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                && precision < (unsigned int) ((LDBL_DIG + 1) * 0.831) + 1)
311605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              {
311705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                /* Round the mantissa.  */
311805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                long double tail = mantissa;
311905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                size_t q;
312005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
312105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                for (q = precision; ; q--)
312205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  {
312305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    int digit = (int) tail;
312405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    tail -= digit;
312505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    if (q == 0)
312605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      {
312705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        if (digit & 1 ? tail >= 0.5L : tail > 0.5L)
312805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          tail = 1 - tail;
312905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        else
313005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          tail = - tail;
313105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        break;
313205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      }
313305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    tail *= 16.0L;
313405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  }
313505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                if (tail != 0.0L)
313605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  for (q = precision; q > 0; q--)
313705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    tail *= 0.0625L;
313805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                mantissa += tail;
313905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              }
314005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
314105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            *p++ = '0';
314205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            *p++ = dp->conversion - 'A' + 'X';
314305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            pad_ptr = p;
314405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            {
314505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              int digit;
314605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
314705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              digit = (int) mantissa;
314805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              mantissa -= digit;
314905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              *p++ = '0' + digit;
315005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              if ((flags & FLAG_ALT)
315105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  || mantissa > 0.0L || precision > 0)
315205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                {
315305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  *p++ = decimal_point_char ();
315405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  /* This loop terminates because we assume
315505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                     that FLT_RADIX is a power of 2.  */
315605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  while (mantissa > 0.0L)
315705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    {
315805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      mantissa *= 16.0L;
315905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      digit = (int) mantissa;
316005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      mantissa -= digit;
316105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      *p++ = digit
316205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                             + (digit < 10
316305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                ? '0'
316405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                : dp->conversion - 10);
316505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      if (precision > 0)
316605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        precision--;
316705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    }
316805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  while (precision > 0)
316905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    {
317005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      *p++ = '0';
317105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      precision--;
317205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    }
317305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                }
317405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              }
317505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              *p++ = dp->conversion - 'A' + 'P';
317605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if WIDE_CHAR_VERSION
317705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              {
317805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                static const wchar_t decimal_format[] =
317905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  { '%', '+', 'd', '\0' };
318005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                SNPRINTF (p, 6 + 1, decimal_format, exponent);
318105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              }
318205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              while (*p != '\0')
318305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                p++;
318405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  else
318505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              if (sizeof (DCHAR_T) == 1)
318605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                {
318705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  sprintf ((char *) p, "%+d", exponent);
318805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  while (*p != '\0')
318905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    p++;
319005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                }
319105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              else
319205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                {
319305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  char expbuf[6 + 1];
319405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  const char *ep;
319505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  sprintf (expbuf, "%+d", exponent);
319605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  for (ep = expbuf; (*p = *ep) != '\0'; ep++)
319705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    p++;
319805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                }
319905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
320005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
320105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
320205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        END_LONG_DOUBLE_ROUNDING ();
320305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
320405436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else
320505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    abort ();
320605436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
320705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  }
320805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                else
320905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  {
321005436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE
321105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    double arg = a.arg[dp->arg_index].a.a_double;
321205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
321305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (isnand (arg))
321405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
321505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (dp->conversion == 'A')
321605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
321705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
321805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
321905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        else
322005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
322105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
322205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
322305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
322405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    else
322505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
322605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        int sign = 0;
322705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
322805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (signbit (arg)) /* arg < 0.0 or negative zero */
322905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
323005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            sign = -1;
323105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            arg = -arg;
323205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
323305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
323405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (sign < 0)
323505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          *p++ = '-';
323605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        else if (flags & FLAG_SHOWSIGN)
323705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          *p++ = '+';
323805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        else if (flags & FLAG_SPACE)
323905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          *p++ = ' ';
324005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
324105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (arg > 0.0 && arg + arg == arg)
324205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
324305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            if (dp->conversion == 'A')
324405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              {
324505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
324605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              }
324705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            else
324805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              {
324905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
325005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              }
325105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
325205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        else
325305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
325405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            int exponent;
325505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            double mantissa;
325605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
325705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            if (arg > 0.0)
325805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              mantissa = printf_frexp (arg, &exponent);
325905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            else
326005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              {
326105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                exponent = 0;
326205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                mantissa = 0.0;
326305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              }
326405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
326505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            if (has_precision
326605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                && precision < (unsigned int) ((DBL_DIG + 1) * 0.831) + 1)
326705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              {
326805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                /* Round the mantissa.  */
326905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                double tail = mantissa;
327005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                size_t q;
327105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
327205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                for (q = precision; ; q--)
327305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  {
327405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    int digit = (int) tail;
327505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    tail -= digit;
327605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    if (q == 0)
327705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      {
327805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        if (digit & 1 ? tail >= 0.5 : tail > 0.5)
327905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          tail = 1 - tail;
328005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        else
328105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          tail = - tail;
328205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        break;
328305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      }
328405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    tail *= 16.0;
328505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  }
328605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                if (tail != 0.0)
328705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  for (q = precision; q > 0; q--)
328805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    tail *= 0.0625;
328905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                mantissa += tail;
329005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              }
329105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
329205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            *p++ = '0';
329305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            *p++ = dp->conversion - 'A' + 'X';
329405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            pad_ptr = p;
329505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            {
329605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              int digit;
329705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
329805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              digit = (int) mantissa;
329905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              mantissa -= digit;
330005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              *p++ = '0' + digit;
330105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              if ((flags & FLAG_ALT)
330205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  || mantissa > 0.0 || precision > 0)
330305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                {
330405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  *p++ = decimal_point_char ();
330505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  /* This loop terminates because we assume
330605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                     that FLT_RADIX is a power of 2.  */
330705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  while (mantissa > 0.0)
330805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    {
330905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      mantissa *= 16.0;
331005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      digit = (int) mantissa;
331105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      mantissa -= digit;
331205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      *p++ = digit
331305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                             + (digit < 10
331405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                ? '0'
331505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                : dp->conversion - 10);
331605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      if (precision > 0)
331705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        precision--;
331805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    }
331905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  while (precision > 0)
332005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    {
332105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      *p++ = '0';
332205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      precision--;
332305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    }
332405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                }
332505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              }
332605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              *p++ = dp->conversion - 'A' + 'P';
332705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if WIDE_CHAR_VERSION
332805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              {
332905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                static const wchar_t decimal_format[] =
333005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  { '%', '+', 'd', '\0' };
333105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                SNPRINTF (p, 6 + 1, decimal_format, exponent);
333205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              }
333305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              while (*p != '\0')
333405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                p++;
333505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  else
333605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              if (sizeof (DCHAR_T) == 1)
333705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                {
333805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  sprintf ((char *) p, "%+d", exponent);
333905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  while (*p != '\0')
334005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    p++;
334105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                }
334205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              else
334305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                {
334405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  char expbuf[6 + 1];
334505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  const char *ep;
334605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  sprintf (expbuf, "%+d", exponent);
334705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  for (ep = expbuf; (*p = *ep) != '\0'; ep++)
334805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    p++;
334905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                }
335005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
335105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
335205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
335305436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else
335405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    abort ();
335505436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
335605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  }
335705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                /* The generated string now extends from tmp to p, with the
335805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   zero padding insertion point being at pad_ptr.  */
335905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (has_width && p - tmp < width)
336005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  {
336105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    size_t pad = width - (p - tmp);
336205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    DCHAR_T *end = p + pad;
336305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
336405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (flags & FLAG_LEFT)
336505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
336605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        /* Pad with spaces on the right.  */
336705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        for (; pad > 0; pad--)
336805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          *p++ = ' ';
336905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
337005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
337105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
337205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        /* Pad with zeroes.  */
337305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        DCHAR_T *q = end;
337405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
337505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        while (p > pad_ptr)
337605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          *--q = *--p;
337705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        for (; pad > 0; pad--)
337805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          *p++ = '0';
337905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
338005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    else
338105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
338205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        /* Pad with spaces on the left.  */
338305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        DCHAR_T *q = end;
338405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
338505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        while (p > tmp)
338605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          *--q = *--p;
338705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        for (; pad > 0; pad--)
338805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          *p++ = ' ';
338905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
339005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
339105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    p = end;
339205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  }
339305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
339405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                {
339505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  size_t count = p - tmp;
339605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
339705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  if (count >= tmp_length)
339805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    /* tmp_length was incorrectly calculated - fix the
339905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                       code above!  */
340005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    abort ();
340105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
340205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  /* Make room for the result.  */
340305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  if (count >= allocated - length)
340405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    {
340505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      size_t n = xsum (length, count);
340605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
340705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      ENSURE_ALLOCATION (n);
340805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    }
340905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
341005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  /* Append the result.  */
341105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  memcpy (result + length, tmp, count * sizeof (DCHAR_T));
341205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  if (tmp != tmpbuf)
341305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    free (tmp);
341405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  length += count;
341505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                }
341605436638acc7c010349a69c3395f1a57c642dc62Ying Wang              }
341705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
341805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if (NEED_PRINTF_INFINITE_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL
341905436638acc7c010349a69c3395f1a57c642dc62Ying Wang            else if ((dp->conversion == 'f' || dp->conversion == 'F'
342005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      || dp->conversion == 'e' || dp->conversion == 'E'
342105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      || dp->conversion == 'g' || dp->conversion == 'G'
342205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      || dp->conversion == 'a' || dp->conversion == 'A')
342305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                     && (0
342405436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if NEED_PRINTF_DOUBLE
342505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                         || a.arg[dp->arg_index].type == TYPE_DOUBLE
342605436638acc7c010349a69c3395f1a57c642dc62Ying Wang# elif NEED_PRINTF_INFINITE_DOUBLE
342705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                         || (a.arg[dp->arg_index].type == TYPE_DOUBLE
342805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                             /* The systems (mingw) which produce wrong output
342905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                for Inf, -Inf, and NaN also do so for -0.0.
343005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                Therefore we treat this case here as well.  */
343105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                             && is_infinite_or_zero (a.arg[dp->arg_index].a.a_double))
343205436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
343305436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if NEED_PRINTF_LONG_DOUBLE
343405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                         || a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
343505436638acc7c010349a69c3395f1a57c642dc62Ying Wang# elif NEED_PRINTF_INFINITE_LONG_DOUBLE
343605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                         || (a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
343705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                             /* Some systems produce wrong output for Inf,
343805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                -Inf, and NaN.  Some systems in this category
343905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                (IRIX 5.3) also do so for -0.0.  Therefore we
344005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                treat this case here as well.  */
344105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                             && is_infinite_or_zerol (a.arg[dp->arg_index].a.a_longdouble))
344205436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
344305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        ))
344405436638acc7c010349a69c3395f1a57c642dc62Ying Wang              {
344505436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if (NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE)
344605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                arg_type type = a.arg[dp->arg_index].type;
344705436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
344805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                int flags = dp->flags;
344905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                int has_width;
345005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                size_t width;
345105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                int has_precision;
345205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                size_t precision;
345305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                size_t tmp_length;
345405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                DCHAR_T tmpbuf[700];
345505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                DCHAR_T *tmp;
345605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                DCHAR_T *pad_ptr;
345705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                DCHAR_T *p;
345805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
345905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                has_width = 0;
346005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                width = 0;
346105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (dp->width_start != dp->width_end)
346205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  {
346305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (dp->width_arg_index != ARG_NONE)
346405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
346505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        int arg;
346605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
346705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
346805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          abort ();
346905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        arg = a.arg[dp->width_arg_index].a.a_int;
347005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (arg < 0)
347105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
347205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            /* "A negative field width is taken as a '-' flag
347305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                followed by a positive field width."  */
347405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            flags |= FLAG_LEFT;
347505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            width = (unsigned int) (-arg);
347605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
347705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        else
347805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          width = arg;
347905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
348005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    else
348105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
348205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        const FCHAR_T *digitp = dp->width_start;
348305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
348405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        do
348505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          width = xsum (xtimes (width, 10), *digitp++ - '0');
348605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        while (digitp != dp->width_end);
348705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
348805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    has_width = 1;
348905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  }
349005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
349105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                has_precision = 0;
349205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                precision = 0;
349305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (dp->precision_start != dp->precision_end)
349405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  {
349505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (dp->precision_arg_index != ARG_NONE)
349605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
349705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        int arg;
349805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
349905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
350005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          abort ();
350105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        arg = a.arg[dp->precision_arg_index].a.a_int;
350205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        /* "A negative precision is taken as if the precision
350305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            were omitted."  */
350405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (arg >= 0)
350505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
350605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            precision = arg;
350705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            has_precision = 1;
350805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
350905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
351005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    else
351105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
351205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        const FCHAR_T *digitp = dp->precision_start + 1;
351305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
351405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        precision = 0;
351505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        while (digitp != dp->precision_end)
351605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          precision = xsum (xtimes (precision, 10), *digitp++ - '0');
351705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        has_precision = 1;
351805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
351905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  }
352005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
352105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                /* POSIX specifies the default precision to be 6 for %f, %F,
352205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   %e, %E, but not for %g, %G.  Implementations appear to use
352305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   the same default precision also for %g, %G.  But for %a, %A,
352405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   the default precision is 0.  */
352505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (!has_precision)
352605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  if (!(dp->conversion == 'a' || dp->conversion == 'A'))
352705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    precision = 6;
352805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
352905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                /* Allocate a temporary buffer of sufficient size.  */
353005436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if NEED_PRINTF_DOUBLE && NEED_PRINTF_LONG_DOUBLE
353105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                tmp_length = (type == TYPE_LONGDOUBLE ? LDBL_DIG + 1 : DBL_DIG + 1);
353205436638acc7c010349a69c3395f1a57c642dc62Ying Wang# elif NEED_PRINTF_INFINITE_DOUBLE && NEED_PRINTF_LONG_DOUBLE
353305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                tmp_length = (type == TYPE_LONGDOUBLE ? LDBL_DIG + 1 : 0);
353405436638acc7c010349a69c3395f1a57c642dc62Ying Wang# elif NEED_PRINTF_LONG_DOUBLE
353505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                tmp_length = LDBL_DIG + 1;
353605436638acc7c010349a69c3395f1a57c642dc62Ying Wang# elif NEED_PRINTF_DOUBLE
353705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                tmp_length = DBL_DIG + 1;
353805436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else
353905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                tmp_length = 0;
354005436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
354105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (tmp_length < precision)
354205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  tmp_length = precision;
354305436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if NEED_PRINTF_LONG_DOUBLE
354405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
354505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (type == TYPE_LONGDOUBLE)
354605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
354705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  if (dp->conversion == 'f' || dp->conversion == 'F')
354805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    {
354905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      long double arg = a.arg[dp->arg_index].a.a_longdouble;
355005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      if (!(isnanl (arg) || arg + arg == arg))
355105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
355205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          /* arg is finite and nonzero.  */
355305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          int exponent = floorlog10l (arg < 0 ? -arg : arg);
355405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          if (exponent >= 0 && tmp_length < exponent + precision)
355505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            tmp_length = exponent + precision;
355605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
355705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    }
355805436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
355905436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if NEED_PRINTF_DOUBLE
356005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE
356105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (type == TYPE_DOUBLE)
356205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
356305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  if (dp->conversion == 'f' || dp->conversion == 'F')
356405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    {
356505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      double arg = a.arg[dp->arg_index].a.a_double;
356605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      if (!(isnand (arg) || arg + arg == arg))
356705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
356805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          /* arg is finite and nonzero.  */
356905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          int exponent = floorlog10 (arg < 0 ? -arg : arg);
357005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          if (exponent >= 0 && tmp_length < exponent + precision)
357105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            tmp_length = exponent + precision;
357205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
357305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    }
357405436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
357505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                /* Account for sign, decimal point etc. */
357605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                tmp_length = xsum (tmp_length, 12);
357705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
357805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (tmp_length < width)
357905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  tmp_length = width;
358005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
358105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
358205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
358305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (tmp_length <= sizeof (tmpbuf) / sizeof (DCHAR_T))
358405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  tmp = tmpbuf;
358505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                else
358605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  {
358705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    size_t tmp_memsize = xtimes (tmp_length, sizeof (DCHAR_T));
358805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
358905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (size_overflow_p (tmp_memsize))
359005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      /* Overflow, would lead to out of memory.  */
359105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      goto out_of_memory;
359205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    tmp = (DCHAR_T *) malloc (tmp_memsize);
359305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (tmp == NULL)
359405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      /* Out of memory.  */
359505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      goto out_of_memory;
359605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  }
359705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
359805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                pad_ptr = NULL;
359905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                p = tmp;
360005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
360105436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE
360205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
360305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (type == TYPE_LONGDOUBLE)
360405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
360505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  {
360605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    long double arg = a.arg[dp->arg_index].a.a_longdouble;
360705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
360805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (isnanl (arg))
360905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
361005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (dp->conversion >= 'A' && dp->conversion <= 'Z')
361105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
361205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
361305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
361405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        else
361505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
361605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
361705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
361805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
361905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    else
362005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
362105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        int sign = 0;
362205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        DECL_LONG_DOUBLE_ROUNDING
362305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
362405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        BEGIN_LONG_DOUBLE_ROUNDING ();
362505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
362605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (signbit (arg)) /* arg < 0.0L or negative zero */
362705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
362805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            sign = -1;
362905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            arg = -arg;
363005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
363105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
363205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (sign < 0)
363305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          *p++ = '-';
363405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        else if (flags & FLAG_SHOWSIGN)
363505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          *p++ = '+';
363605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        else if (flags & FLAG_SPACE)
363705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          *p++ = ' ';
363805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
363905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (arg > 0.0L && arg + arg == arg)
364005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
364105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            if (dp->conversion >= 'A' && dp->conversion <= 'Z')
364205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              {
364305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
364405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              }
364505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            else
364605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              {
364705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
364805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              }
364905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
365005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        else
365105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
365205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if NEED_PRINTF_LONG_DOUBLE
365305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            pad_ptr = p;
365405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
365505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            if (dp->conversion == 'f' || dp->conversion == 'F')
365605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              {
365705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                char *digits;
365805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                size_t ndigits;
365905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
366005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                digits =
366105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  scale10_round_decimal_long_double (arg, precision);
366205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                if (digits == NULL)
366305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  {
366405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    END_LONG_DOUBLE_ROUNDING ();
366505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    goto out_of_memory;
366605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  }
366705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                ndigits = strlen (digits);
366805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
366905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                if (ndigits > precision)
367005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  do
367105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    {
367205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      --ndigits;
367305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      *p++ = digits[ndigits];
367405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    }
367505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  while (ndigits > precision);
367605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                else
367705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  *p++ = '0';
367805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                /* Here ndigits <= precision.  */
367905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                if ((flags & FLAG_ALT) || precision > 0)
368005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  {
368105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    *p++ = decimal_point_char ();
368205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    for (; precision > ndigits; precision--)
368305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      *p++ = '0';
368405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    while (ndigits > 0)
368505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      {
368605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        --ndigits;
368705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        *p++ = digits[ndigits];
368805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      }
368905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  }
369005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
369105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                free (digits);
369205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              }
369305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            else if (dp->conversion == 'e' || dp->conversion == 'E')
369405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              {
369505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                int exponent;
369605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
369705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                if (arg == 0.0L)
369805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  {
369905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    exponent = 0;
370005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    *p++ = '0';
370105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    if ((flags & FLAG_ALT) || precision > 0)
370205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      {
370305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        *p++ = decimal_point_char ();
370405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        for (; precision > 0; precision--)
370505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          *p++ = '0';
370605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      }
370705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  }
370805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                else
370905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  {
371005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    /* arg > 0.0L.  */
371105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    int adjusted;
371205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    char *digits;
371305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    size_t ndigits;
371405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
371505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    exponent = floorlog10l (arg);
371605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    adjusted = 0;
371705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    for (;;)
371805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      {
371905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        digits =
372005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          scale10_round_decimal_long_double (arg,
372105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                                             (int)precision - exponent);
372205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        if (digits == NULL)
372305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          {
372405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            END_LONG_DOUBLE_ROUNDING ();
372505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            goto out_of_memory;
372605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          }
372705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        ndigits = strlen (digits);
372805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
372905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        if (ndigits == precision + 1)
373005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          break;
373105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        if (ndigits < precision
373205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            || ndigits > precision + 2)
373305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          /* The exponent was not guessed
373405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                             precisely enough.  */
373505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          abort ();
373605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        if (adjusted)
373705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          /* None of two values of exponent is
373805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                             the right one.  Prevent an endless
373905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                             loop.  */
374005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          abort ();
374105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        free (digits);
374205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        if (ndigits == precision)
374305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          exponent -= 1;
374405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        else
374505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          exponent += 1;
374605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        adjusted = 1;
374705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      }
374805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    /* Here ndigits = precision+1.  */
374905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    if (is_borderline (digits, precision))
375005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      {
375105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        /* Maybe the exponent guess was too high
375205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                           and a smaller exponent can be reached
375305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                           by turning a 10...0 into 9...9x.  */
375405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        char *digits2 =
375505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          scale10_round_decimal_long_double (arg,
375605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                                             (int)precision - exponent + 1);
375705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        if (digits2 == NULL)
375805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          {
375905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            free (digits);
376005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            END_LONG_DOUBLE_ROUNDING ();
376105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            goto out_of_memory;
376205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          }
376305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        if (strlen (digits2) == precision + 1)
376405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          {
376505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            free (digits);
376605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            digits = digits2;
376705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            exponent -= 1;
376805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          }
376905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        else
377005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          free (digits2);
377105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      }
377205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    /* Here ndigits = precision+1.  */
377305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
377405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    *p++ = digits[--ndigits];
377505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    if ((flags & FLAG_ALT) || precision > 0)
377605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      {
377705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        *p++ = decimal_point_char ();
377805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        while (ndigits > 0)
377905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          {
378005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            --ndigits;
378105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            *p++ = digits[ndigits];
378205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          }
378305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      }
378405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
378505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    free (digits);
378605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  }
378705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
378805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                *p++ = dp->conversion; /* 'e' or 'E' */
378905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   if WIDE_CHAR_VERSION
379005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                {
379105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  static const wchar_t decimal_format[] =
379205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    { '%', '+', '.', '2', 'd', '\0' };
379305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  SNPRINTF (p, 6 + 1, decimal_format, exponent);
379405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                }
379505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                while (*p != '\0')
379605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  p++;
379705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   else
379805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                if (sizeof (DCHAR_T) == 1)
379905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  {
380005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    sprintf ((char *) p, "%+.2d", exponent);
380105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    while (*p != '\0')
380205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      p++;
380305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  }
380405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                else
380505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  {
380605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    char expbuf[6 + 1];
380705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    const char *ep;
380805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    sprintf (expbuf, "%+.2d", exponent);
380905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    for (ep = expbuf; (*p = *ep) != '\0'; ep++)
381005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      p++;
381105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  }
381205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   endif
381305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              }
381405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            else if (dp->conversion == 'g' || dp->conversion == 'G')
381505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              {
381605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                if (precision == 0)
381705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  precision = 1;
381805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                /* precision >= 1.  */
381905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
382005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                if (arg == 0.0L)
382105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  /* The exponent is 0, >= -4, < precision.
382205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                     Use fixed-point notation.  */
382305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  {
382405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    size_t ndigits = precision;
382505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    /* Number of trailing zeroes that have to be
382605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                       dropped.  */
382705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    size_t nzeroes =
382805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      (flags & FLAG_ALT ? 0 : precision - 1);
382905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
383005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    --ndigits;
383105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    *p++ = '0';
383205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    if ((flags & FLAG_ALT) || ndigits > nzeroes)
383305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      {
383405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        *p++ = decimal_point_char ();
383505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        while (ndigits > nzeroes)
383605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          {
383705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            --ndigits;
383805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            *p++ = '0';
383905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          }
384005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      }
384105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  }
384205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                else
384305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  {
384405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    /* arg > 0.0L.  */
384505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    int exponent;
384605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    int adjusted;
384705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    char *digits;
384805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    size_t ndigits;
384905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    size_t nzeroes;
385005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
385105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    exponent = floorlog10l (arg);
385205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    adjusted = 0;
385305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    for (;;)
385405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      {
385505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        digits =
385605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          scale10_round_decimal_long_double (arg,
385705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                                             (int)(precision - 1) - exponent);
385805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        if (digits == NULL)
385905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          {
386005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            END_LONG_DOUBLE_ROUNDING ();
386105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            goto out_of_memory;
386205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          }
386305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        ndigits = strlen (digits);
386405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
386505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        if (ndigits == precision)
386605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          break;
386705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        if (ndigits < precision - 1
386805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            || ndigits > precision + 1)
386905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          /* The exponent was not guessed
387005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                             precisely enough.  */
387105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          abort ();
387205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        if (adjusted)
387305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          /* None of two values of exponent is
387405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                             the right one.  Prevent an endless
387505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                             loop.  */
387605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          abort ();
387705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        free (digits);
387805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        if (ndigits < precision)
387905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          exponent -= 1;
388005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        else
388105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          exponent += 1;
388205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        adjusted = 1;
388305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      }
388405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    /* Here ndigits = precision.  */
388505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    if (is_borderline (digits, precision - 1))
388605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      {
388705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        /* Maybe the exponent guess was too high
388805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                           and a smaller exponent can be reached
388905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                           by turning a 10...0 into 9...9x.  */
389005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        char *digits2 =
389105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          scale10_round_decimal_long_double (arg,
389205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                                             (int)(precision - 1) - exponent + 1);
389305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        if (digits2 == NULL)
389405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          {
389505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            free (digits);
389605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            END_LONG_DOUBLE_ROUNDING ();
389705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            goto out_of_memory;
389805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          }
389905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        if (strlen (digits2) == precision)
390005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          {
390105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            free (digits);
390205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            digits = digits2;
390305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            exponent -= 1;
390405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          }
390505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        else
390605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          free (digits2);
390705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      }
390805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    /* Here ndigits = precision.  */
390905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
391005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    /* Determine the number of trailing zeroes
391105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                       that have to be dropped.  */
391205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    nzeroes = 0;
391305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    if ((flags & FLAG_ALT) == 0)
391405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      while (nzeroes < ndigits
391505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                             && digits[nzeroes] == '0')
391605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        nzeroes++;
391705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
391805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    /* The exponent is now determined.  */
391905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    if (exponent >= -4
392005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        && exponent < (long)precision)
392105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      {
392205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        /* Fixed-point notation:
392305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                           max(exponent,0)+1 digits, then the
392405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                           decimal point, then the remaining
392505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                           digits without trailing zeroes.  */
392605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        if (exponent >= 0)
392705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          {
392805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            size_t count = exponent + 1;
392905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            /* Note: count <= precision = ndigits.  */
393005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            for (; count > 0; count--)
393105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                              *p++ = digits[--ndigits];
393205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            if ((flags & FLAG_ALT) || ndigits > nzeroes)
393305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                              {
393405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                *p++ = decimal_point_char ();
393505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                while (ndigits > nzeroes)
393605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                  {
393705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                    --ndigits;
393805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                    *p++ = digits[ndigits];
393905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                  }
394005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                              }
394105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          }
394205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        else
394305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          {
394405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            size_t count = -exponent - 1;
394505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            *p++ = '0';
394605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            *p++ = decimal_point_char ();
394705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            for (; count > 0; count--)
394805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                              *p++ = '0';
394905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            while (ndigits > nzeroes)
395005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                              {
395105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                --ndigits;
395205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                *p++ = digits[ndigits];
395305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                              }
395405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          }
395505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      }
395605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    else
395705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      {
395805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        /* Exponential notation.  */
395905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        *p++ = digits[--ndigits];
396005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        if ((flags & FLAG_ALT) || ndigits > nzeroes)
396105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          {
396205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            *p++ = decimal_point_char ();
396305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            while (ndigits > nzeroes)
396405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                              {
396505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                --ndigits;
396605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                *p++ = digits[ndigits];
396705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                              }
396805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          }
396905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        *p++ = dp->conversion - 'G' + 'E'; /* 'e' or 'E' */
397005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   if WIDE_CHAR_VERSION
397105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        {
397205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          static const wchar_t decimal_format[] =
397305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            { '%', '+', '.', '2', 'd', '\0' };
397405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          SNPRINTF (p, 6 + 1, decimal_format, exponent);
397505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        }
397605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        while (*p != '\0')
397705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          p++;
397805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   else
397905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        if (sizeof (DCHAR_T) == 1)
398005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          {
398105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            sprintf ((char *) p, "%+.2d", exponent);
398205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            while (*p != '\0')
398305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                              p++;
398405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          }
398505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        else
398605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          {
398705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            char expbuf[6 + 1];
398805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            const char *ep;
398905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            sprintf (expbuf, "%+.2d", exponent);
399005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            for (ep = expbuf; (*p = *ep) != '\0'; ep++)
399105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                              p++;
399205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          }
399305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   endif
399405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      }
399505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
399605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    free (digits);
399705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  }
399805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              }
399905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            else
400005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              abort ();
400105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  else
400205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            /* arg is finite.  */
400305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            if (!(arg == 0.0L))
400405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              abort ();
400505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
400605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            pad_ptr = p;
400705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
400805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            if (dp->conversion == 'f' || dp->conversion == 'F')
400905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              {
401005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                *p++ = '0';
401105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                if ((flags & FLAG_ALT) || precision > 0)
401205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  {
401305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    *p++ = decimal_point_char ();
401405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    for (; precision > 0; precision--)
401505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      *p++ = '0';
401605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  }
401705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              }
401805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            else if (dp->conversion == 'e' || dp->conversion == 'E')
401905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              {
402005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                *p++ = '0';
402105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                if ((flags & FLAG_ALT) || precision > 0)
402205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  {
402305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    *p++ = decimal_point_char ();
402405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    for (; precision > 0; precision--)
402505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      *p++ = '0';
402605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  }
402705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                *p++ = dp->conversion; /* 'e' or 'E' */
402805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                *p++ = '+';
402905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                *p++ = '0';
403005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                *p++ = '0';
403105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              }
403205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            else if (dp->conversion == 'g' || dp->conversion == 'G')
403305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              {
403405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                *p++ = '0';
403505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                if (flags & FLAG_ALT)
403605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  {
403705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    size_t ndigits =
403805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      (precision > 0 ? precision - 1 : 0);
403905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    *p++ = decimal_point_char ();
404005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    for (; ndigits > 0; --ndigits)
404105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      *p++ = '0';
404205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  }
404305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              }
404405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            else if (dp->conversion == 'a' || dp->conversion == 'A')
404505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              {
404605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                *p++ = '0';
404705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                *p++ = dp->conversion - 'A' + 'X';
404805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                pad_ptr = p;
404905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                *p++ = '0';
405005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                if ((flags & FLAG_ALT) || precision > 0)
405105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  {
405205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    *p++ = decimal_point_char ();
405305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    for (; precision > 0; precision--)
405405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      *p++ = '0';
405505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  }
405605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                *p++ = dp->conversion - 'A' + 'P';
405705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                *p++ = '+';
405805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                *p++ = '0';
405905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              }
406005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            else
406105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              abort ();
406205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
406305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
406405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
406505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        END_LONG_DOUBLE_ROUNDING ();
406605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
406705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  }
406805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
406905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                else
407005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
407105436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
407205436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
407305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  {
407405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    double arg = a.arg[dp->arg_index].a.a_double;
407505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
407605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (isnand (arg))
407705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
407805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (dp->conversion >= 'A' && dp->conversion <= 'Z')
407905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
408005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
408105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
408205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        else
408305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
408405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
408505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
408605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
408705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    else
408805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
408905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        int sign = 0;
409005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
409105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (signbit (arg)) /* arg < 0.0 or negative zero */
409205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
409305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            sign = -1;
409405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            arg = -arg;
409505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
409605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
409705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (sign < 0)
409805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          *p++ = '-';
409905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        else if (flags & FLAG_SHOWSIGN)
410005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          *p++ = '+';
410105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        else if (flags & FLAG_SPACE)
410205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          *p++ = ' ';
410305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
410405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (arg > 0.0 && arg + arg == arg)
410505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
410605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            if (dp->conversion >= 'A' && dp->conversion <= 'Z')
410705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              {
410805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
410905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              }
411005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            else
411105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              {
411205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
411305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              }
411405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
411505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        else
411605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
411705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  if NEED_PRINTF_DOUBLE
411805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            pad_ptr = p;
411905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
412005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            if (dp->conversion == 'f' || dp->conversion == 'F')
412105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              {
412205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                char *digits;
412305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                size_t ndigits;
412405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
412505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                digits =
412605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  scale10_round_decimal_double (arg, precision);
412705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                if (digits == NULL)
412805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  goto out_of_memory;
412905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                ndigits = strlen (digits);
413005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
413105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                if (ndigits > precision)
413205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  do
413305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    {
413405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      --ndigits;
413505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      *p++ = digits[ndigits];
413605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    }
413705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  while (ndigits > precision);
413805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                else
413905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  *p++ = '0';
414005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                /* Here ndigits <= precision.  */
414105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                if ((flags & FLAG_ALT) || precision > 0)
414205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  {
414305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    *p++ = decimal_point_char ();
414405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    for (; precision > ndigits; precision--)
414505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      *p++ = '0';
414605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    while (ndigits > 0)
414705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      {
414805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        --ndigits;
414905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        *p++ = digits[ndigits];
415005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      }
415105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  }
415205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
415305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                free (digits);
415405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              }
415505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            else if (dp->conversion == 'e' || dp->conversion == 'E')
415605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              {
415705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                int exponent;
415805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
415905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                if (arg == 0.0)
416005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  {
416105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    exponent = 0;
416205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    *p++ = '0';
416305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    if ((flags & FLAG_ALT) || precision > 0)
416405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      {
416505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        *p++ = decimal_point_char ();
416605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        for (; precision > 0; precision--)
416705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          *p++ = '0';
416805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      }
416905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  }
417005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                else
417105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  {
417205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    /* arg > 0.0.  */
417305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    int adjusted;
417405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    char *digits;
417505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    size_t ndigits;
417605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
417705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    exponent = floorlog10 (arg);
417805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    adjusted = 0;
417905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    for (;;)
418005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      {
418105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        digits =
418205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          scale10_round_decimal_double (arg,
418305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                                        (int)precision - exponent);
418405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        if (digits == NULL)
418505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          goto out_of_memory;
418605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        ndigits = strlen (digits);
418705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
418805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        if (ndigits == precision + 1)
418905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          break;
419005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        if (ndigits < precision
419105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            || ndigits > precision + 2)
419205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          /* The exponent was not guessed
419305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                             precisely enough.  */
419405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          abort ();
419505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        if (adjusted)
419605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          /* None of two values of exponent is
419705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                             the right one.  Prevent an endless
419805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                             loop.  */
419905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          abort ();
420005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        free (digits);
420105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        if (ndigits == precision)
420205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          exponent -= 1;
420305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        else
420405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          exponent += 1;
420505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        adjusted = 1;
420605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      }
420705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    /* Here ndigits = precision+1.  */
420805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    if (is_borderline (digits, precision))
420905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      {
421005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        /* Maybe the exponent guess was too high
421105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                           and a smaller exponent can be reached
421205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                           by turning a 10...0 into 9...9x.  */
421305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        char *digits2 =
421405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          scale10_round_decimal_double (arg,
421505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                                        (int)precision - exponent + 1);
421605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        if (digits2 == NULL)
421705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          {
421805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            free (digits);
421905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            goto out_of_memory;
422005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          }
422105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        if (strlen (digits2) == precision + 1)
422205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          {
422305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            free (digits);
422405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            digits = digits2;
422505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            exponent -= 1;
422605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          }
422705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        else
422805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          free (digits2);
422905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      }
423005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    /* Here ndigits = precision+1.  */
423105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
423205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    *p++ = digits[--ndigits];
423305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    if ((flags & FLAG_ALT) || precision > 0)
423405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      {
423505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        *p++ = decimal_point_char ();
423605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        while (ndigits > 0)
423705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          {
423805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            --ndigits;
423905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            *p++ = digits[ndigits];
424005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          }
424105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      }
424205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
424305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    free (digits);
424405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  }
424505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
424605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                *p++ = dp->conversion; /* 'e' or 'E' */
424705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   if WIDE_CHAR_VERSION
424805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                {
424905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  static const wchar_t decimal_format[] =
425005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    /* Produce the same number of exponent digits
425105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                       as the native printf implementation.  */
425205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#    if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
425305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    { '%', '+', '.', '3', 'd', '\0' };
425405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#    else
425505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    { '%', '+', '.', '2', 'd', '\0' };
425605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#    endif
425705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  SNPRINTF (p, 6 + 1, decimal_format, exponent);
425805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                }
425905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                while (*p != '\0')
426005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  p++;
426105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   else
426205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                {
426305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  static const char decimal_format[] =
426405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    /* Produce the same number of exponent digits
426505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                       as the native printf implementation.  */
426605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#    if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
426705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    "%+.3d";
426805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#    else
426905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    "%+.2d";
427005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#    endif
427105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  if (sizeof (DCHAR_T) == 1)
427205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    {
427305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      sprintf ((char *) p, decimal_format, exponent);
427405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      while (*p != '\0')
427505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        p++;
427605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    }
427705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  else
427805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    {
427905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      char expbuf[6 + 1];
428005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      const char *ep;
428105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      sprintf (expbuf, decimal_format, exponent);
428205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      for (ep = expbuf; (*p = *ep) != '\0'; ep++)
428305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        p++;
428405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    }
428505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                }
428605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   endif
428705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              }
428805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            else if (dp->conversion == 'g' || dp->conversion == 'G')
428905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              {
429005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                if (precision == 0)
429105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  precision = 1;
429205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                /* precision >= 1.  */
429305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
429405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                if (arg == 0.0)
429505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  /* The exponent is 0, >= -4, < precision.
429605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                     Use fixed-point notation.  */
429705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  {
429805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    size_t ndigits = precision;
429905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    /* Number of trailing zeroes that have to be
430005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                       dropped.  */
430105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    size_t nzeroes =
430205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      (flags & FLAG_ALT ? 0 : precision - 1);
430305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
430405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    --ndigits;
430505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    *p++ = '0';
430605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    if ((flags & FLAG_ALT) || ndigits > nzeroes)
430705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      {
430805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        *p++ = decimal_point_char ();
430905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        while (ndigits > nzeroes)
431005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          {
431105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            --ndigits;
431205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            *p++ = '0';
431305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          }
431405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      }
431505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  }
431605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                else
431705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  {
431805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    /* arg > 0.0.  */
431905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    int exponent;
432005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    int adjusted;
432105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    char *digits;
432205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    size_t ndigits;
432305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    size_t nzeroes;
432405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
432505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    exponent = floorlog10 (arg);
432605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    adjusted = 0;
432705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    for (;;)
432805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      {
432905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        digits =
433005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          scale10_round_decimal_double (arg,
433105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                                        (int)(precision - 1) - exponent);
433205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        if (digits == NULL)
433305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          goto out_of_memory;
433405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        ndigits = strlen (digits);
433505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
433605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        if (ndigits == precision)
433705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          break;
433805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        if (ndigits < precision - 1
433905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            || ndigits > precision + 1)
434005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          /* The exponent was not guessed
434105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                             precisely enough.  */
434205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          abort ();
434305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        if (adjusted)
434405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          /* None of two values of exponent is
434505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                             the right one.  Prevent an endless
434605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                             loop.  */
434705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          abort ();
434805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        free (digits);
434905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        if (ndigits < precision)
435005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          exponent -= 1;
435105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        else
435205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          exponent += 1;
435305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        adjusted = 1;
435405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      }
435505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    /* Here ndigits = precision.  */
435605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    if (is_borderline (digits, precision - 1))
435705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      {
435805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        /* Maybe the exponent guess was too high
435905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                           and a smaller exponent can be reached
436005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                           by turning a 10...0 into 9...9x.  */
436105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        char *digits2 =
436205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          scale10_round_decimal_double (arg,
436305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                                        (int)(precision - 1) - exponent + 1);
436405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        if (digits2 == NULL)
436505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          {
436605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            free (digits);
436705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            goto out_of_memory;
436805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          }
436905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        if (strlen (digits2) == precision)
437005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          {
437105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            free (digits);
437205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            digits = digits2;
437305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            exponent -= 1;
437405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          }
437505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        else
437605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          free (digits2);
437705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      }
437805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    /* Here ndigits = precision.  */
437905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
438005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    /* Determine the number of trailing zeroes
438105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                       that have to be dropped.  */
438205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    nzeroes = 0;
438305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    if ((flags & FLAG_ALT) == 0)
438405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      while (nzeroes < ndigits
438505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                             && digits[nzeroes] == '0')
438605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        nzeroes++;
438705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
438805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    /* The exponent is now determined.  */
438905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    if (exponent >= -4
439005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        && exponent < (long)precision)
439105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      {
439205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        /* Fixed-point notation:
439305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                           max(exponent,0)+1 digits, then the
439405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                           decimal point, then the remaining
439505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                           digits without trailing zeroes.  */
439605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        if (exponent >= 0)
439705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          {
439805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            size_t count = exponent + 1;
439905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            /* Note: count <= precision = ndigits.  */
440005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            for (; count > 0; count--)
440105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                              *p++ = digits[--ndigits];
440205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            if ((flags & FLAG_ALT) || ndigits > nzeroes)
440305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                              {
440405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                *p++ = decimal_point_char ();
440505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                while (ndigits > nzeroes)
440605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                  {
440705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                    --ndigits;
440805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                    *p++ = digits[ndigits];
440905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                  }
441005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                              }
441105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          }
441205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        else
441305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          {
441405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            size_t count = -exponent - 1;
441505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            *p++ = '0';
441605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            *p++ = decimal_point_char ();
441705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            for (; count > 0; count--)
441805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                              *p++ = '0';
441905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            while (ndigits > nzeroes)
442005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                              {
442105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                --ndigits;
442205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                *p++ = digits[ndigits];
442305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                              }
442405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          }
442505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      }
442605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    else
442705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      {
442805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        /* Exponential notation.  */
442905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        *p++ = digits[--ndigits];
443005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        if ((flags & FLAG_ALT) || ndigits > nzeroes)
443105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          {
443205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            *p++ = decimal_point_char ();
443305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            while (ndigits > nzeroes)
443405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                              {
443505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                --ndigits;
443605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                *p++ = digits[ndigits];
443705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                              }
443805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          }
443905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        *p++ = dp->conversion - 'G' + 'E'; /* 'e' or 'E' */
444005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   if WIDE_CHAR_VERSION
444105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        {
444205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          static const wchar_t decimal_format[] =
444305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            /* Produce the same number of exponent digits
444405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                               as the native printf implementation.  */
444505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#    if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
444605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            { '%', '+', '.', '3', 'd', '\0' };
444705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#    else
444805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            { '%', '+', '.', '2', 'd', '\0' };
444905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#    endif
445005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          SNPRINTF (p, 6 + 1, decimal_format, exponent);
445105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        }
445205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        while (*p != '\0')
445305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          p++;
445405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   else
445505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        {
445605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          static const char decimal_format[] =
445705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            /* Produce the same number of exponent digits
445805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                               as the native printf implementation.  */
445905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#    if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
446005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            "%+.3d";
446105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#    else
446205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            "%+.2d";
446305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#    endif
446405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          if (sizeof (DCHAR_T) == 1)
446505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            {
446605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                              sprintf ((char *) p, decimal_format, exponent);
446705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                              while (*p != '\0')
446805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                p++;
446905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            }
447005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          else
447105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            {
447205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                              char expbuf[6 + 1];
447305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                              const char *ep;
447405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                              sprintf (expbuf, decimal_format, exponent);
447505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                              for (ep = expbuf; (*p = *ep) != '\0'; ep++)
447605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                p++;
447705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            }
447805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        }
447905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   endif
448005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      }
448105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
448205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    free (digits);
448305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  }
448405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              }
448505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            else
448605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              abort ();
448705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  else
448805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            /* arg is finite.  */
448905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            if (!(arg == 0.0))
449005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              abort ();
449105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
449205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            pad_ptr = p;
449305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
449405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            if (dp->conversion == 'f' || dp->conversion == 'F')
449505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              {
449605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                *p++ = '0';
449705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                if ((flags & FLAG_ALT) || precision > 0)
449805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  {
449905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    *p++ = decimal_point_char ();
450005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    for (; precision > 0; precision--)
450105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      *p++ = '0';
450205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  }
450305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              }
450405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            else if (dp->conversion == 'e' || dp->conversion == 'E')
450505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              {
450605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                *p++ = '0';
450705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                if ((flags & FLAG_ALT) || precision > 0)
450805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  {
450905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    *p++ = decimal_point_char ();
451005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    for (; precision > 0; precision--)
451105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      *p++ = '0';
451205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  }
451305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                *p++ = dp->conversion; /* 'e' or 'E' */
451405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                *p++ = '+';
451505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                /* Produce the same number of exponent digits as
451605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                   the native printf implementation.  */
451705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
451805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                *p++ = '0';
451905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#   endif
452005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                *p++ = '0';
452105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                *p++ = '0';
452205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              }
452305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            else if (dp->conversion == 'g' || dp->conversion == 'G')
452405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              {
452505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                *p++ = '0';
452605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                if (flags & FLAG_ALT)
452705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  {
452805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    size_t ndigits =
452905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      (precision > 0 ? precision - 1 : 0);
453005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    *p++ = decimal_point_char ();
453105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    for (; ndigits > 0; --ndigits)
453205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      *p++ = '0';
453305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  }
453405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              }
453505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            else
453605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              abort ();
453705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  endif
453805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
453905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
454005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  }
454105436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
454205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
454305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                /* The generated string now extends from tmp to p, with the
454405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   zero padding insertion point being at pad_ptr.  */
454505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (has_width && p - tmp < width)
454605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  {
454705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    size_t pad = width - (p - tmp);
454805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    DCHAR_T *end = p + pad;
454905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
455005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (flags & FLAG_LEFT)
455105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
455205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        /* Pad with spaces on the right.  */
455305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        for (; pad > 0; pad--)
455405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          *p++ = ' ';
455505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
455605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
455705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
455805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        /* Pad with zeroes.  */
455905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        DCHAR_T *q = end;
456005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
456105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        while (p > pad_ptr)
456205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          *--q = *--p;
456305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        for (; pad > 0; pad--)
456405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          *p++ = '0';
456505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
456605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    else
456705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
456805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        /* Pad with spaces on the left.  */
456905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        DCHAR_T *q = end;
457005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
457105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        while (p > tmp)
457205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          *--q = *--p;
457305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        for (; pad > 0; pad--)
457405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          *p++ = ' ';
457505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
457605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
457705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    p = end;
457805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  }
457905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
458005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                {
458105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  size_t count = p - tmp;
458205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
458305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  if (count >= tmp_length)
458405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    /* tmp_length was incorrectly calculated - fix the
458505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                       code above!  */
458605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    abort ();
458705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
458805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  /* Make room for the result.  */
458905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  if (count >= allocated - length)
459005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    {
459105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      size_t n = xsum (length, count);
459205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
459305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      ENSURE_ALLOCATION (n);
459405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    }
459505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
459605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  /* Append the result.  */
459705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  memcpy (result + length, tmp, count * sizeof (DCHAR_T));
459805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  if (tmp != tmpbuf)
459905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    free (tmp);
460005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  length += count;
460105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                }
460205436638acc7c010349a69c3395f1a57c642dc62Ying Wang              }
460305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
460405436638acc7c010349a69c3395f1a57c642dc62Ying Wang            else
460505436638acc7c010349a69c3395f1a57c642dc62Ying Wang              {
460605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                arg_type type = a.arg[dp->arg_index].type;
460705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                int flags = dp->flags;
460805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
460905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                int has_width;
461005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                size_t width;
461105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
461205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || NEED_PRINTF_UNBOUNDED_PRECISION
461305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                int has_precision;
461405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                size_t precision;
461505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
461605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if NEED_PRINTF_UNBOUNDED_PRECISION
461705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                int prec_ourselves;
461805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#else
461905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#               define prec_ourselves 0
462005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
462105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if NEED_PRINTF_FLAG_LEFTADJUST
462205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#               define pad_ourselves 1
462305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#elif !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
462405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                int pad_ourselves;
462505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#else
462605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#               define pad_ourselves 0
462705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
462805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                TCHAR_T *fbp;
462905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                unsigned int prefix_count;
463005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                int prefixes[2] IF_LINT (= { 0 });
463105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                int orig_errno;
463205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if !USE_SNPRINTF
463305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                size_t tmp_length;
463405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                TCHAR_T tmpbuf[700];
463505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                TCHAR_T *tmp;
463605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
463705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
463805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
463905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                has_width = 0;
464005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                width = 0;
464105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (dp->width_start != dp->width_end)
464205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  {
464305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (dp->width_arg_index != ARG_NONE)
464405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
464505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        int arg;
464605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
464705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
464805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          abort ();
464905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        arg = a.arg[dp->width_arg_index].a.a_int;
465005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (arg < 0)
465105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
465205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            /* "A negative field width is taken as a '-' flag
465305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                followed by a positive field width."  */
465405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            flags |= FLAG_LEFT;
465505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            width = (unsigned int) (-arg);
465605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
465705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        else
465805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          width = arg;
465905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
466005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    else
466105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
466205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        const FCHAR_T *digitp = dp->width_start;
466305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
466405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        do
466505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          width = xsum (xtimes (width, 10), *digitp++ - '0');
466605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        while (digitp != dp->width_end);
466705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
466805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    has_width = 1;
466905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  }
467005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
467105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
467205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || NEED_PRINTF_UNBOUNDED_PRECISION
467305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                has_precision = 0;
467405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                precision = 6;
467505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (dp->precision_start != dp->precision_end)
467605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  {
467705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (dp->precision_arg_index != ARG_NONE)
467805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
467905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        int arg;
468005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
468105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
468205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          abort ();
468305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        arg = a.arg[dp->precision_arg_index].a.a_int;
468405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        /* "A negative precision is taken as if the precision
468505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            were omitted."  */
468605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (arg >= 0)
468705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
468805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            precision = arg;
468905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            has_precision = 1;
469005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
469105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
469205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    else
469305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
469405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        const FCHAR_T *digitp = dp->precision_start + 1;
469505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
469605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        precision = 0;
469705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        while (digitp != dp->precision_end)
469805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          precision = xsum (xtimes (precision, 10), *digitp++ - '0');
469905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        has_precision = 1;
470005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
470105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  }
470205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
470305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
470405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                /* Decide whether to handle the precision ourselves.  */
470505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if NEED_PRINTF_UNBOUNDED_PRECISION
470605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                switch (dp->conversion)
470705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  {
470805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  case 'd': case 'i': case 'u':
470905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  case 'o':
471005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  case 'x': case 'X': case 'p':
471105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    prec_ourselves = has_precision && (precision > 0);
471205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    break;
471305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  default:
471405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    prec_ourselves = 0;
471505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    break;
471605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  }
471705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
471805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
471905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                /* Decide whether to perform the padding ourselves.  */
472005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if !NEED_PRINTF_FLAG_LEFTADJUST && (!DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION)
472105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                switch (dp->conversion)
472205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  {
472305436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO
472405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  /* If we need conversion from TCHAR_T[] to DCHAR_T[], we need
472505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                     to perform the padding after this conversion.  Functions
472605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                     with unistdio extensions perform the padding based on
472705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                     character count rather than element count.  */
472805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  case 'c': case 's':
472905436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
473005436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if NEED_PRINTF_FLAG_ZERO
473105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
473205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  case 'a': case 'A':
473305436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
473405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    pad_ourselves = 1;
473505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    break;
473605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  default:
473705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    pad_ourselves = prec_ourselves;
473805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    break;
473905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  }
474005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
474105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
474205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if !USE_SNPRINTF
474305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                /* Allocate a temporary buffer of sufficient size for calling
474405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   sprintf.  */
474505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                tmp_length =
474605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  MAX_ROOM_NEEDED (&a, dp->arg_index, dp->conversion, type,
474705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                   flags, width, has_precision, precision,
474805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                   pad_ourselves);
474905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
475005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (tmp_length <= sizeof (tmpbuf) / sizeof (TCHAR_T))
475105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  tmp = tmpbuf;
475205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                else
475305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  {
475405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    size_t tmp_memsize = xtimes (tmp_length, sizeof (TCHAR_T));
475505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
475605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (size_overflow_p (tmp_memsize))
475705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      /* Overflow, would lead to out of memory.  */
475805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      goto out_of_memory;
475905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    tmp = (TCHAR_T *) malloc (tmp_memsize);
476005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (tmp == NULL)
476105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      /* Out of memory.  */
476205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      goto out_of_memory;
476305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  }
476405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
476505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
476605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                /* Construct the format string for calling snprintf or
476705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   sprintf.  */
476805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                fbp = buf;
476905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                *fbp++ = '%';
477005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if NEED_PRINTF_FLAG_GROUPING
477105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                /* The underlying implementation doesn't support the ' flag.
477205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   Produce no grouping characters in this case; this is
477305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   acceptable because the grouping is locale dependent.  */
477405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#else
477505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (flags & FLAG_GROUP)
477605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  *fbp++ = '\'';
477705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
477805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (flags & FLAG_LEFT)
477905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  *fbp++ = '-';
478005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (flags & FLAG_SHOWSIGN)
478105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  *fbp++ = '+';
478205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (flags & FLAG_SPACE)
478305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  *fbp++ = ' ';
478405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (flags & FLAG_ALT)
478505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  *fbp++ = '#';
478605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if __GLIBC__ >= 2 && !defined __UCLIBC__
478705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (flags & FLAG_LOCALIZED)
478805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  *fbp++ = 'I';
478905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
479005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (!pad_ourselves)
479105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  {
479205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (flags & FLAG_ZERO)
479305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      *fbp++ = '0';
479405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (dp->width_start != dp->width_end)
479505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
479605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        size_t n = dp->width_end - dp->width_start;
479705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        /* The width specification is known to consist only
479805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                           of standard ASCII characters.  */
479905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (sizeof (FCHAR_T) == sizeof (TCHAR_T))
480005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
480105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            memcpy (fbp, dp->width_start, n * sizeof (TCHAR_T));
480205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            fbp += n;
480305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
480405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        else
480505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
480605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            const FCHAR_T *mp = dp->width_start;
480705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            do
480805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              *fbp++ = (unsigned char) *mp++;
480905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            while (--n > 0);
481005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
481105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
481205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  }
481305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (!prec_ourselves)
481405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  {
481505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (dp->precision_start != dp->precision_end)
481605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
481705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        size_t n = dp->precision_end - dp->precision_start;
481805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        /* The precision specification is known to consist only
481905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                           of standard ASCII characters.  */
482005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (sizeof (FCHAR_T) == sizeof (TCHAR_T))
482105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
482205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            memcpy (fbp, dp->precision_start, n * sizeof (TCHAR_T));
482305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            fbp += n;
482405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
482505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        else
482605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
482705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            const FCHAR_T *mp = dp->precision_start;
482805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            do
482905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              *fbp++ = (unsigned char) *mp++;
483005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            while (--n > 0);
483105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
483205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
483305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  }
483405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
483505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                switch (type)
483605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  {
483705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if HAVE_LONG_LONG_INT
483805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  case TYPE_LONGLONGINT:
483905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  case TYPE_ULONGLONGINT:
484005436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
484105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    *fbp++ = 'I';
484205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    *fbp++ = '6';
484305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    *fbp++ = '4';
484405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    break;
484505436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else
484605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    *fbp++ = 'l';
484705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    /*FALLTHROUGH*/
484805436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
484905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
485005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  case TYPE_LONGINT:
485105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  case TYPE_ULONGINT:
485205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if HAVE_WINT_T
485305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  case TYPE_WIDE_CHAR:
485405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
485505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if HAVE_WCHAR_T
485605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  case TYPE_WIDE_STRING:
485705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
485805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    *fbp++ = 'l';
485905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    break;
486005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  case TYPE_LONGDOUBLE:
486105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    *fbp++ = 'L';
486205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    break;
486305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  default:
486405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    break;
486505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  }
486605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if NEED_PRINTF_DIRECTIVE_F
486705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (dp->conversion == 'F')
486805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  *fbp = 'f';
486905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                else
487005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
487105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  *fbp = dp->conversion;
487205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if USE_SNPRINTF
487305436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if !(((__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)) && !defined __UCLIBC__) || ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__))
487405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                fbp[1] = '%';
487505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                fbp[2] = 'n';
487605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                fbp[3] = '\0';
487705436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else
487805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                /* On glibc2 systems from glibc >= 2.3 - probably also older
487905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   ones - we know that snprintf's return value conforms to
488005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   ISO C 99: the tests gl_SNPRINTF_RETVAL_C99 and
488105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   gl_SNPRINTF_TRUNCATION_C99 pass.
488205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   Therefore we can avoid using %n in this situation.
488305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   On glibc2 systems from 2004-10-18 or newer, the use of %n
488405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   in format strings in writable memory may crash the program
488505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   (if compiled with _FORTIFY_SOURCE=2), so we should avoid it
488605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   in this situation.  */
488705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                /* On native Windows systems (such as mingw), we can avoid using
488805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   %n because:
488905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                     - Although the gl_SNPRINTF_TRUNCATION_C99 test fails,
489005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                       snprintf does not write more than the specified number
489105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                       of bytes. (snprintf (buf, 3, "%d %d", 4567, 89) writes
489205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                       '4', '5', '6' into buf, not '4', '5', '\0'.)
489305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                     - Although the gl_SNPRINTF_RETVAL_C99 test fails, snprintf
489405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                       allows us to recognize the case of an insufficient
489505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                       buffer size: it returns -1 in this case.
489605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   On native Windows systems (such as mingw) where the OS is
489705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   Windows Vista, the use of %n in format strings by default
489805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   crashes the program. See
489905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                     <http://gcc.gnu.org/ml/gcc/2007-06/msg00122.html> and
490005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                     <http://msdn2.microsoft.com/en-us/library/ms175782(VS.80).aspx>
490105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   So we should avoid %n in this situation.  */
490205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                fbp[1] = '\0';
490305436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
490405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#else
490505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                fbp[1] = '\0';
490605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
490705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
490805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                /* Construct the arguments for calling snprintf or sprintf.  */
490905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                prefix_count = 0;
491005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (!pad_ourselves && dp->width_arg_index != ARG_NONE)
491105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  {
491205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
491305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      abort ();
491405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int;
491505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  }
491605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                if (!prec_ourselves && dp->precision_arg_index != ARG_NONE)
491705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  {
491805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
491905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      abort ();
492005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int;
492105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  }
492205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
492305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if USE_SNPRINTF
492405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                /* The SNPRINTF result is appended after result[0..length].
492505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   The latter is an array of DCHAR_T; SNPRINTF appends an
492605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   array of TCHAR_T to it.  This is possible because
492705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   sizeof (TCHAR_T) divides sizeof (DCHAR_T) and
492805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   alignof (TCHAR_T) <= alignof (DCHAR_T).  */
492905436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define TCHARS_PER_DCHAR (sizeof (DCHAR_T) / sizeof (TCHAR_T))
493005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                /* Ensure that maxlen below will be >= 2.  Needed on BeOS,
493105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   where an snprintf() with maxlen==1 acts like sprintf().  */
493205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                ENSURE_ALLOCATION (xsum (length,
493305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                         (2 + TCHARS_PER_DCHAR - 1)
493405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                         / TCHARS_PER_DCHAR));
493505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                /* Prepare checking whether snprintf returns the count
493605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                   via %n.  */
493705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                *(TCHAR_T *) (result + length) = '\0';
493805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
493905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
494005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                orig_errno = errno;
494105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
494205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                for (;;)
494305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  {
494405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    int count = -1;
494505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
494605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if USE_SNPRINTF
494705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    int retcount = 0;
494805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    size_t maxlen = allocated - length;
494905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    /* SNPRINTF can fail if its second argument is
495005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                       > INT_MAX.  */
495105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (maxlen > INT_MAX / TCHARS_PER_DCHAR)
495205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      maxlen = INT_MAX / TCHARS_PER_DCHAR;
495305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    maxlen = maxlen * TCHARS_PER_DCHAR;
495405436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define SNPRINTF_BUF(arg) \
495505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    switch (prefix_count)                                   \
495605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {                                                     \
495705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      case 0:                                               \
495805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        retcount = SNPRINTF ((TCHAR_T *) (result + length), \
495905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                             maxlen, buf,                   \
496005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                             arg, &count);                  \
496105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        break;                                              \
496205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      case 1:                                               \
496305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        retcount = SNPRINTF ((TCHAR_T *) (result + length), \
496405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                             maxlen, buf,                   \
496505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                             prefixes[0], arg, &count);     \
496605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        break;                                              \
496705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      case 2:                                               \
496805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        retcount = SNPRINTF ((TCHAR_T *) (result + length), \
496905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                             maxlen, buf,                   \
497005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                             prefixes[0], prefixes[1], arg, \
497105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                             &count);                       \
497205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        break;                                              \
497305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      default:                                              \
497405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        abort ();                                           \
497505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
497605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#else
497705436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define SNPRINTF_BUF(arg) \
497805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    switch (prefix_count)                                   \
497905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {                                                     \
498005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      case 0:                                               \
498105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        count = sprintf (tmp, buf, arg);                    \
498205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        break;                                              \
498305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      case 1:                                               \
498405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        count = sprintf (tmp, buf, prefixes[0], arg);       \
498505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        break;                                              \
498605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      case 2:                                               \
498705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        count = sprintf (tmp, buf, prefixes[0], prefixes[1],\
498805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                         arg);                              \
498905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        break;                                              \
499005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      default:                                              \
499105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        abort ();                                           \
499205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
499305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
499405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
499505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    errno = 0;
499605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    switch (type)
499705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
499805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      case TYPE_SCHAR:
499905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
500005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          int arg = a.arg[dp->arg_index].a.a_schar;
500105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          SNPRINTF_BUF (arg);
500205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
500305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        break;
500405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      case TYPE_UCHAR:
500505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
500605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          unsigned int arg = a.arg[dp->arg_index].a.a_uchar;
500705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          SNPRINTF_BUF (arg);
500805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
500905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        break;
501005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      case TYPE_SHORT:
501105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
501205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          int arg = a.arg[dp->arg_index].a.a_short;
501305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          SNPRINTF_BUF (arg);
501405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
501505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        break;
501605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      case TYPE_USHORT:
501705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
501805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          unsigned int arg = a.arg[dp->arg_index].a.a_ushort;
501905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          SNPRINTF_BUF (arg);
502005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
502105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        break;
502205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      case TYPE_INT:
502305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
502405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          int arg = a.arg[dp->arg_index].a.a_int;
502505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          SNPRINTF_BUF (arg);
502605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
502705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        break;
502805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      case TYPE_UINT:
502905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
503005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          unsigned int arg = a.arg[dp->arg_index].a.a_uint;
503105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          SNPRINTF_BUF (arg);
503205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
503305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        break;
503405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      case TYPE_LONGINT:
503505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
503605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          long int arg = a.arg[dp->arg_index].a.a_longint;
503705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          SNPRINTF_BUF (arg);
503805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
503905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        break;
504005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      case TYPE_ULONGINT:
504105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
504205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint;
504305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          SNPRINTF_BUF (arg);
504405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
504505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        break;
504605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if HAVE_LONG_LONG_INT
504705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      case TYPE_LONGLONGINT:
504805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
504905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          long long int arg = a.arg[dp->arg_index].a.a_longlongint;
505005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          SNPRINTF_BUF (arg);
505105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
505205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        break;
505305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      case TYPE_ULONGLONGINT:
505405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
505505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint;
505605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          SNPRINTF_BUF (arg);
505705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
505805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        break;
505905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
506005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      case TYPE_DOUBLE:
506105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
506205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          double arg = a.arg[dp->arg_index].a.a_double;
506305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          SNPRINTF_BUF (arg);
506405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
506505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        break;
506605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      case TYPE_LONGDOUBLE:
506705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
506805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          long double arg = a.arg[dp->arg_index].a.a_longdouble;
506905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          SNPRINTF_BUF (arg);
507005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
507105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        break;
507205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      case TYPE_CHAR:
507305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
507405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          int arg = a.arg[dp->arg_index].a.a_char;
507505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          SNPRINTF_BUF (arg);
507605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
507705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        break;
507805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if HAVE_WINT_T
507905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      case TYPE_WIDE_CHAR:
508005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
508105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          wint_t arg = a.arg[dp->arg_index].a.a_wide_char;
508205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          SNPRINTF_BUF (arg);
508305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
508405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        break;
508505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
508605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      case TYPE_STRING:
508705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
508805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          const char *arg = a.arg[dp->arg_index].a.a_string;
508905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          SNPRINTF_BUF (arg);
509005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
509105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        break;
509205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if HAVE_WCHAR_T
509305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      case TYPE_WIDE_STRING:
509405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
509505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
509605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          SNPRINTF_BUF (arg);
509705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
509805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        break;
509905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
510005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      case TYPE_POINTER:
510105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        {
510205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          void *arg = a.arg[dp->arg_index].a.a_pointer;
510305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          SNPRINTF_BUF (arg);
510405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        }
510505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        break;
510605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      default:
510705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        abort ();
510805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
510905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
511005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if USE_SNPRINTF
511105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    /* Portability: Not all implementations of snprintf()
511205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                       are ISO C 99 compliant.  Determine the number of
511305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                       bytes that snprintf() has produced or would have
511405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                       produced.  */
511505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (count >= 0)
511605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
511705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        /* Verify that snprintf() has NUL-terminated its
511805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                           result.  */
511905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (count < maxlen
512005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            && ((TCHAR_T *) (result + length)) [count] != '\0')
512105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          abort ();
512205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        /* Portability hack.  */
512305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (retcount > count)
512405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          count = retcount;
512505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
512605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    else
512705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
512805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        /* snprintf() doesn't understand the '%n'
512905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                           directive.  */
513005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (fbp[1] != '\0')
513105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
513205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            /* Don't use the '%n' directive; instead, look
513305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                               at the snprintf() return value.  */
513405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            fbp[1] = '\0';
513505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            continue;
513605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
513705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        else
513805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
513905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            /* Look at the snprintf() return value.  */
514005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            if (retcount < 0)
514105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              {
514205436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if !HAVE_SNPRINTF_RETVAL_C99
514305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                /* HP-UX 10.20 snprintf() is doubly deficient:
514405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                   It doesn't understand the '%n' directive,
514505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                   *and* it returns -1 (rather than the length
514605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                   that would have been required) when the
514705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                   buffer is too small.
514805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                   But a failure at this point can also come
514905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                   from other reasons than a too small buffer,
515005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                   such as an invalid wide string argument to
515105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                   the %ls directive, or possibly an invalid
515205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                   floating-point argument.  */
515305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                size_t tmp_length =
515405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  MAX_ROOM_NEEDED (&a, dp->arg_index,
515505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                   dp->conversion, type, flags,
515605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                   width, has_precision,
515705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                   precision, pad_ourselves);
515805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
515905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                if (maxlen < tmp_length)
516005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  {
516105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    /* Make more room.  But try to do through
516205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                       this reallocation only once.  */
516305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    size_t bigger_need =
516405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      xsum (length,
516505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            xsum (tmp_length,
516605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                  TCHARS_PER_DCHAR - 1)
516705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                            / TCHARS_PER_DCHAR);
516805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    /* And always grow proportionally.
516905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                       (There may be several arguments, each
517005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                       needing a little more room than the
517105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                       previous one.)  */
517205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    size_t bigger_need2 =
517305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      xsum (xtimes (allocated, 2), 12);
517405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    if (bigger_need < bigger_need2)
517505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      bigger_need = bigger_need2;
517605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    ENSURE_ALLOCATION (bigger_need);
517705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    continue;
517805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  }
517905436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
518005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              }
518105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            else
518205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              count = retcount;
518305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
518405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
518505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
518605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
518705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    /* Attempt to handle failure.  */
518805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (count < 0)
518905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
519005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        /* SNPRINTF or sprintf failed.  Save and use the errno
519105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                           that it has set, if any.  */
519205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        int saved_errno = errno;
519305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
519405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (!(result == resultbuf || result == NULL))
519505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          free (result);
519605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (buf_malloced != NULL)
519705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          free (buf_malloced);
519805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        CLEANUP ();
519905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        errno =
520005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          (saved_errno != 0
520105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                           ? saved_errno
520205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                           : (dp->conversion == 'c' || dp->conversion == 's'
520305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              ? EILSEQ
520405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              : EINVAL));
520505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        return NULL;
520605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
520705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
520805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if USE_SNPRINTF
520905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    /* Handle overflow of the allocated buffer.
521005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                       If such an overflow occurs, a C99 compliant snprintf()
521105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                       returns a count >= maxlen.  However, a non-compliant
521205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                       snprintf() function returns only count = maxlen - 1.  To
521305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                       cover both cases, test whether count >= maxlen - 1.  */
521405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if ((unsigned int) count + 1 >= maxlen)
521505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
521605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        /* If maxlen already has attained its allowed maximum,
521705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                           allocating more memory will not increase maxlen.
521805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                           Instead of looping, bail out.  */
521905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (maxlen == INT_MAX / TCHARS_PER_DCHAR)
522005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          goto overflow;
522105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        else
522205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
522305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            /* Need at least (count + 1) * sizeof (TCHAR_T)
522405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                               bytes.  (The +1 is for the trailing NUL.)
522505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                               But ask for (count + 2) * sizeof (TCHAR_T)
522605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                               bytes, so that in the next round, we likely get
522705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                 maxlen > (unsigned int) count + 1
522805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                               and so we don't get here again.
522905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                               And allocate proportionally, to avoid looping
523005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                               eternally if snprintf() reports a too small
523105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                               count.  */
523205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            size_t n =
523305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              xmax (xsum (length,
523405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          ((unsigned int) count + 2
523505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                           + TCHARS_PER_DCHAR - 1)
523605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                          / TCHARS_PER_DCHAR),
523705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    xtimes (allocated, 2));
523805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
523905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            ENSURE_ALLOCATION (n);
524005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            continue;
524105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
524205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
524305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
524405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
524505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if NEED_PRINTF_UNBOUNDED_PRECISION
524605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (prec_ourselves)
524705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
524805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        /* Handle the precision.  */
524905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        TCHAR_T *prec_ptr =
525005436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if USE_SNPRINTF
525105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          (TCHAR_T *) (result + length);
525205436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else
525305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          tmp;
525405436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
525505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        size_t prefix_count;
525605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        size_t move;
525705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
525805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        prefix_count = 0;
525905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        /* Put the additional zeroes after the sign.  */
526005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (count >= 1
526105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            && (*prec_ptr == '-' || *prec_ptr == '+'
526205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                || *prec_ptr == ' '))
526305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          prefix_count = 1;
526405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        /* Put the additional zeroes after the 0x prefix if
526505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                           (flags & FLAG_ALT) || (dp->conversion == 'p').  */
526605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        else if (count >= 2
526705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                 && prec_ptr[0] == '0'
526805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                 && (prec_ptr[1] == 'x' || prec_ptr[1] == 'X'))
526905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          prefix_count = 2;
527005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
527105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        move = count - prefix_count;
527205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (precision > move)
527305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
527405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            /* Insert zeroes.  */
527505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            size_t insert = precision - move;
527605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            TCHAR_T *prec_end;
527705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
527805436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if USE_SNPRINTF
527905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            size_t n =
528005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              xsum (length,
528105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    (count + insert + TCHARS_PER_DCHAR - 1)
528205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    / TCHARS_PER_DCHAR);
528305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            length += (count + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR;
528405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            ENSURE_ALLOCATION (n);
528505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            length -= (count + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR;
528605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            prec_ptr = (TCHAR_T *) (result + length);
528705436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
528805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
528905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            prec_end = prec_ptr + count;
529005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            prec_ptr += prefix_count;
529105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
529205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            while (prec_end > prec_ptr)
529305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              {
529405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                prec_end--;
529505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                prec_end[insert] = prec_end[0];
529605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              }
529705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
529805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            prec_end += insert;
529905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            do
530005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              *--prec_end = '0';
530105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            while (prec_end > prec_ptr);
530205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
530305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            count += insert;
530405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
530505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
530605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
530705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
530805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if !USE_SNPRINTF
530905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (count >= tmp_length)
531005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      /* tmp_length was incorrectly calculated - fix the
531105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                         code above!  */
531205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      abort ();
531305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
531405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
531505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if !DCHAR_IS_TCHAR
531605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    /* Convert from TCHAR_T[] to DCHAR_T[].  */
531705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (dp->conversion == 'c' || dp->conversion == 's')
531805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
531905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        /* type = TYPE_CHAR or TYPE_WIDE_CHAR or TYPE_STRING
532005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                           TYPE_WIDE_STRING.
532105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                           The result string is not certainly ASCII.  */
532205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        const TCHAR_T *tmpsrc;
532305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        DCHAR_T *tmpdst;
532405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        size_t tmpdst_len;
532505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        /* This code assumes that TCHAR_T is 'char'.  */
532605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        verify (sizeof (TCHAR_T) == 1);
532705436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if USE_SNPRINTF
532805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        tmpsrc = (TCHAR_T *) (result + length);
532905436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else
533005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        tmpsrc = tmp;
533105436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
533205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        tmpdst =
533305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          DCHAR_CONV_FROM_ENCODING (locale_charset (),
533405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                    iconveh_question_mark,
533505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                    tmpsrc, count,
533605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                    NULL,
533705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                                    NULL, &tmpdst_len);
533805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (tmpdst == NULL)
533905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
534005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            int saved_errno = errno;
534105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            if (!(result == resultbuf || result == NULL))
534205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              free (result);
534305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            if (buf_malloced != NULL)
534405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              free (buf_malloced);
534505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            CLEANUP ();
534605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            errno = saved_errno;
534705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            return NULL;
534805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
534905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        ENSURE_ALLOCATION (xsum (length, tmpdst_len));
535005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        DCHAR_CPY (result + length, tmpdst, tmpdst_len);
535105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        free (tmpdst);
535205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        count = tmpdst_len;
535305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
535405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    else
535505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
535605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        /* The result string is ASCII.
535705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                           Simple 1:1 conversion.  */
535805436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if USE_SNPRINTF
535905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        /* If sizeof (DCHAR_T) == sizeof (TCHAR_T), it's a
536005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                           no-op conversion, in-place on the array starting
536105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                           at (result + length).  */
536205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (sizeof (DCHAR_T) != sizeof (TCHAR_T))
536305436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
536405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
536505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            const TCHAR_T *tmpsrc;
536605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            DCHAR_T *tmpdst;
536705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            size_t n;
536805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
536905436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if USE_SNPRINTF
537005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            if (result == resultbuf)
537105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              {
537205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                tmpsrc = (TCHAR_T *) (result + length);
537305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                /* ENSURE_ALLOCATION will not move tmpsrc
537405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                   (because it's part of resultbuf).  */
537505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                ENSURE_ALLOCATION (xsum (length, count));
537605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              }
537705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            else
537805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              {
537905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                /* ENSURE_ALLOCATION will move the array
538005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                   (because it uses realloc().  */
538105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                ENSURE_ALLOCATION (xsum (length, count));
538205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                tmpsrc = (TCHAR_T *) (result + length);
538305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              }
538405436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else
538505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            tmpsrc = tmp;
538605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            ENSURE_ALLOCATION (xsum (length, count));
538705436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
538805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            tmpdst = result + length;
538905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            /* Copy backwards, because of overlapping.  */
539005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            tmpsrc += count;
539105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            tmpdst += count;
539205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            for (n = count; n > 0; n--)
539305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              *--tmpdst = (unsigned char) *--tmpsrc;
539405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
539505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
539605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
539705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
539805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if DCHAR_IS_TCHAR && !USE_SNPRINTF
539905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    /* Make room for the result.  */
540005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (count > allocated - length)
540105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
540205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        /* Need at least count elements.  But allocate
540305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                           proportionally.  */
540405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        size_t n =
540505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          xmax (xsum (length, count), xtimes (allocated, 2));
540605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
540705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        ENSURE_ALLOCATION (n);
540805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
540905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
541005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
541105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    /* Here count <= allocated - length.  */
541205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
541305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    /* Perform padding.  */
541405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
541505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (pad_ourselves && has_width)
541605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
541705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        size_t w;
541805436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if ENABLE_UNISTDIO
541905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        /* Outside POSIX, it's preferable to compare the width
542005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                           against the number of _characters_ of the converted
542105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                           value.  */
542205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        w = DCHAR_MBSNLEN (result + length, count);
542305436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else
542405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        /* The width is compared against the number of _bytes_
542505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                           of the converted value, says POSIX.  */
542605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        w = count;
542705436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
542805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        if (w < width)
542905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          {
543005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            size_t pad = width - w;
543105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
543205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            /* Make room for the result.  */
543305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            if (xsum (count, pad) > allocated - length)
543405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              {
543505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                /* Need at least count + pad elements.  But
543605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                   allocate proportionally.  */
543705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                size_t n =
543805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  xmax (xsum3 (length, count, pad),
543905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                        xtimes (allocated, 2));
544005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
544105436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if USE_SNPRINTF
544205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                length += count;
544305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                ENSURE_ALLOCATION (n);
544405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                length -= count;
544505436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else
544605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                ENSURE_ALLOCATION (n);
544705436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
544805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              }
544905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            /* Here count + pad <= allocated - length.  */
545005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
545105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            {
545205436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if !DCHAR_IS_TCHAR || USE_SNPRINTF
545305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              DCHAR_T * const rp = result + length;
545405436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else
545505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              DCHAR_T * const rp = tmp;
545605436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
545705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              DCHAR_T *p = rp + count;
545805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              DCHAR_T *end = p + pad;
545905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              DCHAR_T *pad_ptr;
546005436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO
546105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              if (dp->conversion == 'c'
546205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  || dp->conversion == 's')
546305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                /* No zero-padding for string directives.  */
546405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                pad_ptr = NULL;
546505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              else
546605436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
546705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                {
546805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  pad_ptr = (*rp == '-' ? rp + 1 : rp);
546905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  /* No zero-padding of "inf" and "nan".  */
547005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  if ((*pad_ptr >= 'A' && *pad_ptr <= 'Z')
547105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                      || (*pad_ptr >= 'a' && *pad_ptr <= 'z'))
547205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    pad_ptr = NULL;
547305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                }
547405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              /* The generated string now extends from rp to p,
547505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                 with the zero padding insertion point being at
547605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                 pad_ptr.  */
547705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
547805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              count = count + pad; /* = end - rp */
547905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
548005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              if (flags & FLAG_LEFT)
548105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                {
548205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  /* Pad with spaces on the right.  */
548305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  for (; pad > 0; pad--)
548405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    *p++ = ' ';
548505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                }
548605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
548705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                {
548805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  /* Pad with zeroes.  */
548905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  DCHAR_T *q = end;
549005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
549105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  while (p > pad_ptr)
549205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    *--q = *--p;
549305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  for (; pad > 0; pad--)
549405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    *p++ = '0';
549505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                }
549605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              else
549705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                {
549805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  /* Pad with spaces on the left.  */
549905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  DCHAR_T *q = end;
550005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
550105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  while (p > rp)
550205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    *--q = *--p;
550305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  for (; pad > 0; pad--)
550405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    *p++ = ' ';
550505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                }
550605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            }
550705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          }
550805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
550905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
551005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
551105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    /* Here still count <= allocated - length.  */
551205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
551305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if !DCHAR_IS_TCHAR || USE_SNPRINTF
551405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    /* The snprintf() result did fit.  */
551505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#else
551605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    /* Append the sprintf() result.  */
551705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    memcpy (result + length, tmp, count * sizeof (DCHAR_T));
551805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
551905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if !USE_SNPRINTF
552005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (tmp != tmpbuf)
552105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      free (tmp);
552205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
552305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
552405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if NEED_PRINTF_DIRECTIVE_F
552505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    if (dp->conversion == 'F')
552605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      {
552705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        /* Convert the %f result to upper case for %F.  */
552805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        DCHAR_T *rp = result + length;
552905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        size_t rc;
553005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                        for (rc = count; rc > 0; rc--, rp++)
553105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          if (*rp >= 'a' && *rp <= 'z')
553205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            *rp = *rp - 'a' + 'A';
553305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      }
553405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
553505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
553605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    length += count;
553705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                    break;
553805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  }
553905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                errno = orig_errno;
554005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#undef pad_ourselves
554105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#undef prec_ourselves
554205436638acc7c010349a69c3395f1a57c642dc62Ying Wang              }
554305436638acc7c010349a69c3395f1a57c642dc62Ying Wang          }
554405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      }
554505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
554605436638acc7c010349a69c3395f1a57c642dc62Ying Wang    /* Add the final NUL.  */
554705436638acc7c010349a69c3395f1a57c642dc62Ying Wang    ENSURE_ALLOCATION (xsum (length, 1));
554805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    result[length] = '\0';
554905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
555005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    if (result != resultbuf && length + 1 < allocated)
555105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      {
555205436638acc7c010349a69c3395f1a57c642dc62Ying Wang        /* Shrink the allocated memory if possible.  */
555305436638acc7c010349a69c3395f1a57c642dc62Ying Wang        DCHAR_T *memory;
555405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
555505436638acc7c010349a69c3395f1a57c642dc62Ying Wang        memory = (DCHAR_T *) realloc (result, (length + 1) * sizeof (DCHAR_T));
555605436638acc7c010349a69c3395f1a57c642dc62Ying Wang        if (memory != NULL)
555705436638acc7c010349a69c3395f1a57c642dc62Ying Wang          result = memory;
555805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      }
555905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
556005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    if (buf_malloced != NULL)
556105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      free (buf_malloced);
556205436638acc7c010349a69c3395f1a57c642dc62Ying Wang    CLEANUP ();
556305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    *lengthp = length;
556405436638acc7c010349a69c3395f1a57c642dc62Ying Wang    /* Note that we can produce a big string of a length > INT_MAX.  POSIX
556505436638acc7c010349a69c3395f1a57c642dc62Ying Wang       says that snprintf() fails with errno = EOVERFLOW in this case, but
556605436638acc7c010349a69c3395f1a57c642dc62Ying Wang       that's only because snprintf() returns an 'int'.  This function does
556705436638acc7c010349a69c3395f1a57c642dc62Ying Wang       not have this limitation.  */
556805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    return result;
556905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
557005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if USE_SNPRINTF
557105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  overflow:
557205436638acc7c010349a69c3395f1a57c642dc62Ying Wang    if (!(result == resultbuf || result == NULL))
557305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      free (result);
557405436638acc7c010349a69c3395f1a57c642dc62Ying Wang    if (buf_malloced != NULL)
557505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      free (buf_malloced);
557605436638acc7c010349a69c3395f1a57c642dc62Ying Wang    CLEANUP ();
557705436638acc7c010349a69c3395f1a57c642dc62Ying Wang    errno = EOVERFLOW;
557805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    return NULL;
557905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
558005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
558105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  out_of_memory:
558205436638acc7c010349a69c3395f1a57c642dc62Ying Wang    if (!(result == resultbuf || result == NULL))
558305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      free (result);
558405436638acc7c010349a69c3395f1a57c642dc62Ying Wang    if (buf_malloced != NULL)
558505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      free (buf_malloced);
558605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  out_of_memory_1:
558705436638acc7c010349a69c3395f1a57c642dc62Ying Wang    CLEANUP ();
558805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    errno = ENOMEM;
558905436638acc7c010349a69c3395f1a57c642dc62Ying Wang    return NULL;
559005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  }
559105436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
559205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
559305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#undef MAX_ROOM_NEEDED
559405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#undef TCHARS_PER_DCHAR
559505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#undef SNPRINTF
559605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#undef USE_SNPRINTF
559705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#undef DCHAR_SET
559805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#undef DCHAR_CPY
559905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#undef PRINTF_PARSE
560005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#undef DIRECTIVES
560105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#undef DIRECTIVE
560205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#undef DCHAR_IS_TCHAR
560305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#undef TCHAR_T
560405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#undef DCHAR_T
560505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#undef FCHAR_T
560605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#undef VASNPRINTF
5607