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