annotate lib/vasnprintf.c @ 8840:792e05ae7ac8

Fix *printf result for NaN, Inf, -0.0 on mingw.
author Bruno Haible <bruno@clisp.org>
date Sat, 19 May 2007 14:52:36 +0000
parents db95bdbeb72c
children 6fe000202977
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1 /* vsprintf with automatic memory allocation.
8051
9c2b0396b27c Stylistic change: Use '#if HAVE_*' instead of '#ifdef HAVE_*'.
Bruno Haible <bruno@clisp.org>
parents: 7475
diff changeset
2 Copyright (C) 1999, 2002-2007 Free Software Foundation, Inc.
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3
4440
e58a1c05a6ba Update gettext source files from gettext automatically, using srclist-update.
Paul Eggert <eggert@cs.ucla.edu>
parents: 4428
diff changeset
4 This program is free software; you can redistribute it and/or modify
e58a1c05a6ba Update gettext source files from gettext automatically, using srclist-update.
Paul Eggert <eggert@cs.ucla.edu>
parents: 4428
diff changeset
5 it under the terms of the GNU General Public License as published by
e58a1c05a6ba Update gettext source files from gettext automatically, using srclist-update.
Paul Eggert <eggert@cs.ucla.edu>
parents: 4428
diff changeset
6 the Free Software Foundation; either version 2, or (at your option)
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
7 any later version.
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
8
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
9 This program is distributed in the hope that it will be useful,
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
4440
e58a1c05a6ba Update gettext source files from gettext automatically, using srclist-update.
Paul Eggert <eggert@cs.ucla.edu>
parents: 4428
diff changeset
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
e58a1c05a6ba Update gettext source files from gettext automatically, using srclist-update.
Paul Eggert <eggert@cs.ucla.edu>
parents: 4428
diff changeset
12 GNU General Public License for more details.
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
13
4440
e58a1c05a6ba Update gettext source files from gettext automatically, using srclist-update.
Paul Eggert <eggert@cs.ucla.edu>
parents: 4428
diff changeset
14 You should have received a copy of the GNU General Public License along
e58a1c05a6ba Update gettext source files from gettext automatically, using srclist-update.
Paul Eggert <eggert@cs.ucla.edu>
parents: 4428
diff changeset
15 with this program; if not, write to the Free Software Foundation,
5848
a48fb0e98c8c *** empty log message ***
Paul Eggert <eggert@cs.ucla.edu>
parents: 5670
diff changeset
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
17
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
18 /* Tell glibc's <stdio.h> to provide a prototype for snprintf().
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
19 This must come before <config.h> because <config.h> may include
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
20 <features.h>, and once <features.h> has been included, it's too late. */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
21 #ifndef _GNU_SOURCE
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
22 # define _GNU_SOURCE 1
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
23 #endif
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
24
7304
1c4ed7637c24 Include <config.h> unconditionally.
Bruno Haible <bruno@clisp.org>
parents: 7218
diff changeset
25 #include <config.h>
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
26 #ifndef IN_LIBINTL
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
27 # include <alloca.h>
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
28 #endif
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
29
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
30 /* Specification. */
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
31 #if WIDE_CHAR_VERSION
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
32 # include "vasnwprintf.h"
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
33 #else
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
34 # include "vasnprintf.h"
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
35 #endif
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
36
8400
655fca11a0e6 The decimal point must be locale dependent.
Bruno Haible <bruno@clisp.org>
parents: 8343
diff changeset
37 #include <locale.h> /* localeconv() */
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
38 #include <stdio.h> /* snprintf(), sprintf() */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
39 #include <stdlib.h> /* abort(), malloc(), realloc(), free() */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
40 #include <string.h> /* memcpy(), strlen() */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
41 #include <errno.h> /* errno */
7218
0fd12ba5cfc6 Do the INT_MAX check only where size_t is converted to 'int'.
Bruno Haible <bruno@clisp.org>
parents: 6583
diff changeset
42 #include <limits.h> /* CHAR_BIT */
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
43 #include <float.h> /* DBL_MAX_EXP, LDBL_MAX_EXP */
8554
35eb5062216c Prefer nl_langinfo over localeconv.
Bruno Haible <bruno@clisp.org>
parents: 8531
diff changeset
44 #if HAVE_NL_LANGINFO
35eb5062216c Prefer nl_langinfo over localeconv.
Bruno Haible <bruno@clisp.org>
parents: 8531
diff changeset
45 # include <langinfo.h>
35eb5062216c Prefer nl_langinfo over localeconv.
Bruno Haible <bruno@clisp.org>
parents: 8531
diff changeset
46 #endif
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
47 #if WIDE_CHAR_VERSION
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
48 # include "wprintf-parse.h"
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
49 #else
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
50 # include "printf-parse.h"
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
51 #endif
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
52
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
53 /* Checked size_t computations. */
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
54 #include "xsize.h"
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
55
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
56 #if NEED_PRINTF_INFINITE && !defined IN_LIBINTL
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
57 # include <math.h>
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
58 # include "isnan.h"
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
59 #endif
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
60
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
61 #if NEED_PRINTF_LONG_DOUBLE && !defined IN_LIBINTL
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
62 # include <math.h>
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
63 # include "float+.h"
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
64 #endif
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
65
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
66 #if NEED_PRINTF_DIRECTIVE_A && !defined IN_LIBINTL
8655
9a272158fe43 Faster determination of the sign of a number.
Bruno Haible <bruno@clisp.org>
parents: 8648
diff changeset
67 # include <math.h>
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
68 # include "isnan.h"
8526
67e9a647f2fa Fix includes.
Bruno Haible <bruno@clisp.org>
parents: 8487
diff changeset
69 # include "printf-frexp.h"
8648
359d135f748c Assume 'long double' exists.
Bruno Haible <bruno@clisp.org>
parents: 8569
diff changeset
70 # include "isnanl-nolibm.h"
359d135f748c Assume 'long double' exists.
Bruno Haible <bruno@clisp.org>
parents: 8569
diff changeset
71 # include "printf-frexpl.h"
359d135f748c Assume 'long double' exists.
Bruno Haible <bruno@clisp.org>
parents: 8569
diff changeset
72 # include "fpucw.h"
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
73 #endif
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
74
8468
336e69863755 Fix endless loop when the given allocated size was > INT_MAX.
Bruno Haible <bruno@clisp.org>
parents: 8465
diff changeset
75 /* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW. */
336e69863755 Fix endless loop when the given allocated size was > INT_MAX.
Bruno Haible <bruno@clisp.org>
parents: 8465
diff changeset
76 #ifndef EOVERFLOW
336e69863755 Fix endless loop when the given allocated size was > INT_MAX.
Bruno Haible <bruno@clisp.org>
parents: 8465
diff changeset
77 # define EOVERFLOW E2BIG
336e69863755 Fix endless loop when the given allocated size was > INT_MAX.
Bruno Haible <bruno@clisp.org>
parents: 8465
diff changeset
78 #endif
336e69863755 Fix endless loop when the given allocated size was > INT_MAX.
Bruno Haible <bruno@clisp.org>
parents: 8465
diff changeset
79
8051
9c2b0396b27c Stylistic change: Use '#if HAVE_*' instead of '#ifdef HAVE_*'.
Bruno Haible <bruno@clisp.org>
parents: 7475
diff changeset
80 #if HAVE_WCHAR_T
9c2b0396b27c Stylistic change: Use '#if HAVE_*' instead of '#ifdef HAVE_*'.
Bruno Haible <bruno@clisp.org>
parents: 7475
diff changeset
81 # if HAVE_WCSLEN
4523
6cc4874a100b Work around the lack of wcslen() on Solaris 2.5.1.
Bruno Haible <bruno@clisp.org>
parents: 4444
diff changeset
82 # define local_wcslen wcslen
6cc4874a100b Work around the lack of wcslen() on Solaris 2.5.1.
Bruno Haible <bruno@clisp.org>
parents: 4444
diff changeset
83 # else
6cc4874a100b Work around the lack of wcslen() on Solaris 2.5.1.
Bruno Haible <bruno@clisp.org>
parents: 4444
diff changeset
84 /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
85 a dependency towards this library, here is a local substitute.
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
86 Define this substitute only once, even if this file is included
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
87 twice in the same compilation unit. */
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
88 # ifndef local_wcslen_defined
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
89 # define local_wcslen_defined 1
4523
6cc4874a100b Work around the lack of wcslen() on Solaris 2.5.1.
Bruno Haible <bruno@clisp.org>
parents: 4444
diff changeset
90 static size_t
6cc4874a100b Work around the lack of wcslen() on Solaris 2.5.1.
Bruno Haible <bruno@clisp.org>
parents: 4444
diff changeset
91 local_wcslen (const wchar_t *s)
6cc4874a100b Work around the lack of wcslen() on Solaris 2.5.1.
Bruno Haible <bruno@clisp.org>
parents: 4444
diff changeset
92 {
6cc4874a100b Work around the lack of wcslen() on Solaris 2.5.1.
Bruno Haible <bruno@clisp.org>
parents: 4444
diff changeset
93 const wchar_t *ptr;
6cc4874a100b Work around the lack of wcslen() on Solaris 2.5.1.
Bruno Haible <bruno@clisp.org>
parents: 4444
diff changeset
94
6cc4874a100b Work around the lack of wcslen() on Solaris 2.5.1.
Bruno Haible <bruno@clisp.org>
parents: 4444
diff changeset
95 for (ptr = s; *ptr != (wchar_t) 0; ptr++)
6cc4874a100b Work around the lack of wcslen() on Solaris 2.5.1.
Bruno Haible <bruno@clisp.org>
parents: 4444
diff changeset
96 ;
6cc4874a100b Work around the lack of wcslen() on Solaris 2.5.1.
Bruno Haible <bruno@clisp.org>
parents: 4444
diff changeset
97 return ptr - s;
6cc4874a100b Work around the lack of wcslen() on Solaris 2.5.1.
Bruno Haible <bruno@clisp.org>
parents: 4444
diff changeset
98 }
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
99 # endif
4523
6cc4874a100b Work around the lack of wcslen() on Solaris 2.5.1.
Bruno Haible <bruno@clisp.org>
parents: 4444
diff changeset
100 # endif
6cc4874a100b Work around the lack of wcslen() on Solaris 2.5.1.
Bruno Haible <bruno@clisp.org>
parents: 4444
diff changeset
101 #endif
6cc4874a100b Work around the lack of wcslen() on Solaris 2.5.1.
Bruno Haible <bruno@clisp.org>
parents: 4444
diff changeset
102
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
103 #if WIDE_CHAR_VERSION
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
104 # define VASNPRINTF vasnwprintf
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
105 # define CHAR_T wchar_t
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
106 # define DIRECTIVE wchar_t_directive
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
107 # define DIRECTIVES wchar_t_directives
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
108 # define PRINTF_PARSE wprintf_parse
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
109 # define USE_SNPRINTF 1
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
110 # if HAVE_DECL__SNWPRINTF
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
111 /* On Windows, the function swprintf() has a different signature than
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
112 on Unix; we use the _snwprintf() function instead. */
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
113 # define SNPRINTF _snwprintf
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
114 # else
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
115 /* Unix. */
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
116 # define SNPRINTF swprintf
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
117 # endif
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
118 #else
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
119 # define VASNPRINTF vasnprintf
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
120 # define CHAR_T char
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
121 # define DIRECTIVE char_directive
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
122 # define DIRECTIVES char_directives
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
123 # define PRINTF_PARSE printf_parse
8831
d3f907c33d15 Work around broken snprintf function on BeOS.
Bruno Haible <bruno@clisp.org>
parents: 8830
diff changeset
124 # /* Use snprintf if it exists under the name 'snprintf' or '_snprintf'.
d3f907c33d15 Work around broken snprintf function on BeOS.
Bruno Haible <bruno@clisp.org>
parents: 8830
diff changeset
125 But don't use it on BeOS, since BeOS snprintf produces no output if the
d3f907c33d15 Work around broken snprintf function on BeOS.
Bruno Haible <bruno@clisp.org>
parents: 8830
diff changeset
126 size argument is >= 0x3000000. */
d3f907c33d15 Work around broken snprintf function on BeOS.
Bruno Haible <bruno@clisp.org>
parents: 8830
diff changeset
127 # if (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF) && !defined __BEOS__
d3f907c33d15 Work around broken snprintf function on BeOS.
Bruno Haible <bruno@clisp.org>
parents: 8830
diff changeset
128 # define USE_SNPRINTF 1
d3f907c33d15 Work around broken snprintf function on BeOS.
Bruno Haible <bruno@clisp.org>
parents: 8830
diff changeset
129 # else
d3f907c33d15 Work around broken snprintf function on BeOS.
Bruno Haible <bruno@clisp.org>
parents: 8830
diff changeset
130 # define USE_SNPRINTF 0
d3f907c33d15 Work around broken snprintf function on BeOS.
Bruno Haible <bruno@clisp.org>
parents: 8830
diff changeset
131 # endif
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
132 # if HAVE_DECL__SNPRINTF
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
133 /* Windows. */
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
134 # define SNPRINTF _snprintf
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
135 # else
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
136 /* Unix. */
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
137 # define SNPRINTF snprintf
8417
ee40afd85f2c Avoid an endless recursion.
Bruno Haible <bruno@clisp.org>
parents: 8400
diff changeset
138 /* Here we need to call the native snprintf, not rpl_snprintf. */
ee40afd85f2c Avoid an endless recursion.
Bruno Haible <bruno@clisp.org>
parents: 8400
diff changeset
139 # undef snprintf
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
140 # endif
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
141 #endif
8424
ec3450ce9889 Use the system's sprintf function.
Bruno Haible <bruno@clisp.org>
parents: 8417
diff changeset
142 /* Here we need to call the native sprintf, not rpl_sprintf. */
ec3450ce9889 Use the system's sprintf function.
Bruno Haible <bruno@clisp.org>
parents: 8417
diff changeset
143 #undef sprintf
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
144
8569
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
145 #if NEED_PRINTF_DIRECTIVE_A && !defined IN_LIBINTL
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
146 /* Determine the decimal-point character according to the current locale. */
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
147 # ifndef decimal_point_char_defined
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
148 # define decimal_point_char_defined 1
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
149 static char
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
150 decimal_point_char ()
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
151 {
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
152 const char *point;
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
153 /* Determine it in a multithread-safe way. We know nl_langinfo is
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
154 multithread-safe on glibc systems, but is not required to be multithread-
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
155 safe by POSIX. sprintf(), however, is multithread-safe. localeconv()
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
156 is rarely multithread-safe. */
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
157 # if HAVE_NL_LANGINFO && __GLIBC__
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
158 point = nl_langinfo (RADIXCHAR);
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
159 # elif 1
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
160 char pointbuf[5];
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
161 sprintf (pointbuf, "%#.0f", 1.0);
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
162 point = &pointbuf[1];
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
163 # else
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
164 point = localeconv () -> decimal_point;
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
165 # endif
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
166 /* The decimal point is always a single byte: either '.' or ','. */
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
167 return (point[0] != '\0' ? point[0] : '.');
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
168 }
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
169 # endif
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
170 #endif
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
171
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
172 #if NEED_PRINTF_INFINITE && !defined IN_LIBINTL
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
173
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
174 /* Equivalent to !isfinite(x) || x == 0, but does not require libm. */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
175 static int
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
176 is_infinite_or_zero (double x)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
177 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
178 return isnan (x) || x + x == x;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
179 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
180
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
181 #endif
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
182
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
183 #if NEED_PRINTF_LONG_DOUBLE && !defined IN_LIBINTL
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
184
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
185 /* Converting 'long double' to decimal without rare rounding bugs requires
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
186 real bignums. We use the naming conventions of GNU gmp, but vastly simpler
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
187 (and slower) algorithms. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
188
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
189 typedef unsigned int mp_limb_t;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
190 # define GMP_LIMB_BITS 32
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
191 typedef int mp_limb_verify[2 * (sizeof (mp_limb_t) * CHAR_BIT == GMP_LIMB_BITS) - 1];
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
192
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
193 typedef unsigned long long mp_twolimb_t;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
194 # define GMP_TWOLIMB_BITS 64
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
195 typedef int mp_twolimb_verify[2 * (sizeof (mp_twolimb_t) * CHAR_BIT == GMP_TWOLIMB_BITS) - 1];
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
196
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
197 /* Representation of a bignum >= 0. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
198 typedef struct
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
199 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
200 size_t nlimbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
201 mp_limb_t *limbs; /* Bits in little-endian order, allocated with malloc(). */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
202 } mpn_t;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
203
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
204 /* Compute the product of two bignums >= 0.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
205 Return the allocated memory in case of success, NULL in case of memory
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
206 allocation failure. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
207 static void *
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
208 multiply (mpn_t src1, mpn_t src2, mpn_t *dest)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
209 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
210 const mp_limb_t *p1;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
211 const mp_limb_t *p2;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
212 size_t len1;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
213 size_t len2;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
214
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
215 if (src1.nlimbs <= src2.nlimbs)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
216 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
217 len1 = src1.nlimbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
218 p1 = src1.limbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
219 len2 = src2.nlimbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
220 p2 = src2.limbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
221 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
222 else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
223 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
224 len1 = src2.nlimbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
225 p1 = src2.limbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
226 len2 = src1.nlimbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
227 p2 = src1.limbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
228 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
229 /* Now 0 <= len1 <= len2. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
230 if (len1 == 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
231 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
232 /* src1 or src2 is zero. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
233 dest->nlimbs = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
234 dest->limbs = (mp_limb_t *) malloc (1);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
235 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
236 else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
237 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
238 /* Here 1 <= len1 <= len2. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
239 size_t dlen;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
240 mp_limb_t *dp;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
241 size_t k, i, j;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
242
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
243 dlen = len1 + len2;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
244 dp = (mp_limb_t *) malloc (dlen * sizeof (mp_limb_t));
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
245 if (dp == NULL)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
246 return NULL;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
247 for (k = len2; k > 0; )
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
248 dp[--k] = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
249 for (i = 0; i < len1; i++)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
250 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
251 mp_limb_t digit1 = p1[i];
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
252 mp_twolimb_t carry = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
253 for (j = 0; j < len2; j++)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
254 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
255 mp_limb_t digit2 = p2[j];
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
256 carry += (mp_twolimb_t) digit1 * (mp_twolimb_t) digit2;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
257 carry += dp[i + j];
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
258 dp[i + j] = (mp_limb_t) carry;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
259 carry = carry >> GMP_LIMB_BITS;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
260 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
261 dp[i + len2] = (mp_limb_t) carry;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
262 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
263 /* Normalise. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
264 while (dlen > 0 && dp[dlen - 1] == 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
265 dlen--;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
266 dest->nlimbs = dlen;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
267 dest->limbs = dp;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
268 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
269 return dest->limbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
270 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
271
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
272 /* Compute the quotient of a bignum a >= 0 and a bignum b > 0.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
273 a is written as a = q * b + r with 0 <= r < b. q is the quotient, r
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
274 the remainder.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
275 Finally, round-to-even is performed: If r > b/2 or if r = b/2 and q is odd,
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
276 q is incremented.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
277 Return the allocated memory in case of success, NULL in case of memory
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
278 allocation failure. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
279 static void *
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
280 divide (mpn_t a, mpn_t b, mpn_t *q)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
281 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
282 /* Algorithm:
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
283 First normalise a and b: a=[a[m-1],...,a[0]], b=[b[n-1],...,b[0]]
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
284 with m>=0 and n>0 (in base beta = 2^GMP_LIMB_BITS).
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
285 If m<n, then q:=0 and r:=a.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
286 If m>=n=1, perform a single-precision division:
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
287 r:=0, j:=m,
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
288 while j>0 do
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
289 {Here (q[m-1]*beta^(m-1)+...+q[j]*beta^j) * b[0] + r*beta^j =
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
290 = a[m-1]*beta^(m-1)+...+a[j]*beta^j und 0<=r<b[0]<beta}
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
291 j:=j-1, r:=r*beta+a[j], q[j]:=floor(r/b[0]), r:=r-b[0]*q[j].
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
292 Normalise [q[m-1],...,q[0]], yields q.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
293 If m>=n>1, perform a multiple-precision division:
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
294 We have a/b < beta^(m-n+1).
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
295 s:=intDsize-1-(hightest bit in b[n-1]), 0<=s<intDsize.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
296 Shift a and b left by s bits, copying them. r:=a.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
297 r=[r[m],...,r[0]], b=[b[n-1],...,b[0]] with b[n-1]>=beta/2.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
298 For j=m-n,...,0: {Here 0 <= r < b*beta^(j+1).}
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
299 Compute q* :
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
300 q* := floor((r[j+n]*beta+r[j+n-1])/b[n-1]).
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
301 In case of overflow (q* >= beta) set q* := beta-1.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
302 Compute c2 := ((r[j+n]*beta+r[j+n-1]) - q* * b[n-1])*beta + r[j+n-2]
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
303 and c3 := b[n-2] * q*.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
304 {We have 0 <= c2 < 2*beta^2, even 0 <= c2 < beta^2 if no overflow
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
305 occurred. Furthermore 0 <= c3 < beta^2.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
306 If there was overflow and
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
307 r[j+n]*beta+r[j+n-1] - q* * b[n-1] >= beta, i.e. c2 >= beta^2,
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
308 the next test can be skipped.}
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
309 While c3 > c2, {Here 0 <= c2 < c3 < beta^2}
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
310 Put q* := q* - 1, c2 := c2 + b[n-1]*beta, c3 := c3 - b[n-2].
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
311 If q* > 0:
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
312 Put r := r - b * q* * beta^j. In detail:
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
313 [r[n+j],...,r[j]] := [r[n+j],...,r[j]] - q* * [b[n-1],...,b[0]].
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
314 hence: u:=0, for i:=0 to n-1 do
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
315 u := u + q* * b[i],
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
316 r[j+i]:=r[j+i]-(u mod beta) (+ beta, if carry),
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
317 u:=u div beta (+ 1, if carry in subtraction)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
318 r[n+j]:=r[n+j]-u.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
319 {Since always u = (q* * [b[i-1],...,b[0]] div beta^i) + 1
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
320 < q* + 1 <= beta,
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
321 the carry u does not overflow.}
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
322 If a negative carry occurs, put q* := q* - 1
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
323 and [r[n+j],...,r[j]] := [r[n+j],...,r[j]] + [0,b[n-1],...,b[0]].
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
324 Set q[j] := q*.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
325 Normalise [q[m-n],..,q[0]]; this yields the quotient q.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
326 Shift [r[n-1],...,r[0]] right by s bits and normalise; this yields the
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
327 rest r.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
328 The room for q[j] can be allocated at the memory location of r[n+j].
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
329 Finally, round-to-even:
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
330 Shift r left by 1 bit.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
331 If r > b or if r = b and q[0] is odd, q := q+1.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
332 */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
333 const mp_limb_t *a_ptr = a.limbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
334 size_t a_len = a.nlimbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
335 const mp_limb_t *b_ptr = b.limbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
336 size_t b_len = b.nlimbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
337 mp_limb_t *roomptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
338 mp_limb_t *tmp_roomptr = NULL;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
339 mp_limb_t *q_ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
340 size_t q_len;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
341 mp_limb_t *r_ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
342 size_t r_len;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
343
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
344 /* Allocate room for a_len+2 digits.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
345 (Need a_len+1 digits for the real division and 1 more digit for the
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
346 final rounding of q.) */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
347 roomptr = (mp_limb_t *) malloc ((a_len + 2) * sizeof (mp_limb_t));
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
348 if (roomptr == NULL)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
349 return NULL;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
350
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
351 /* Normalise a. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
352 while (a_len > 0 && a_ptr[a_len - 1] == 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
353 a_len--;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
354
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
355 /* Normalise b. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
356 for (;;)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
357 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
358 if (b_len == 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
359 /* Division by zero. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
360 abort ();
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
361 if (b_ptr[b_len - 1] == 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
362 b_len--;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
363 else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
364 break;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
365 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
366
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
367 /* Here m = a_len >= 0 and n = b_len > 0. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
368
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
369 if (a_len < b_len)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
370 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
371 /* m<n: trivial case. q=0, r := copy of a. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
372 r_ptr = roomptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
373 r_len = a_len;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
374 memcpy (r_ptr, a_ptr, a_len * sizeof (mp_limb_t));
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
375 q_ptr = roomptr + a_len;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
376 q_len = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
377 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
378 else if (b_len == 1)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
379 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
380 /* n=1: single precision division.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
381 beta^(m-1) <= a < beta^m ==> beta^(m-2) <= a/b < beta^m */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
382 r_ptr = roomptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
383 q_ptr = roomptr + 1;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
384 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
385 mp_limb_t den = b_ptr[0];
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
386 mp_limb_t remainder = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
387 const mp_limb_t *sourceptr = a_ptr + a_len;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
388 mp_limb_t *destptr = q_ptr + a_len;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
389 size_t count;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
390 for (count = a_len; count > 0; count--)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
391 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
392 mp_twolimb_t num =
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
393 ((mp_twolimb_t) remainder << GMP_LIMB_BITS) | *--sourceptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
394 *--destptr = num / den;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
395 remainder = num % den;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
396 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
397 /* Normalise and store r. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
398 if (remainder > 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
399 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
400 r_ptr[0] = remainder;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
401 r_len = 1;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
402 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
403 else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
404 r_len = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
405 /* Normalise q. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
406 q_len = a_len;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
407 if (q_ptr[q_len - 1] == 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
408 q_len--;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
409 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
410 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
411 else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
412 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
413 /* n>1: multiple precision division.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
414 beta^(m-1) <= a < beta^m, beta^(n-1) <= b < beta^n ==>
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
415 beta^(m-n-1) <= a/b < beta^(m-n+1). */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
416 /* Determine s. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
417 size_t s;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
418 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
419 mp_limb_t msd = b_ptr[b_len - 1]; /* = b[n-1], > 0 */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
420 s = 31;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
421 if (msd >= 0x10000)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
422 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
423 msd = msd >> 16;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
424 s -= 16;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
425 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
426 if (msd >= 0x100)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
427 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
428 msd = msd >> 8;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
429 s -= 8;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
430 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
431 if (msd >= 0x10)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
432 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
433 msd = msd >> 4;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
434 s -= 4;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
435 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
436 if (msd >= 0x4)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
437 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
438 msd = msd >> 2;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
439 s -= 2;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
440 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
441 if (msd >= 0x2)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
442 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
443 msd = msd >> 1;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
444 s -= 1;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
445 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
446 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
447 /* 0 <= s < GMP_LIMB_BITS.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
448 Copy b, shifting it left by s bits. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
449 if (s > 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
450 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
451 tmp_roomptr = (mp_limb_t *) malloc (b_len * sizeof (mp_limb_t));
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
452 if (tmp_roomptr == NULL)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
453 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
454 free (roomptr);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
455 return NULL;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
456 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
457 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
458 const mp_limb_t *sourceptr = b_ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
459 mp_limb_t *destptr = tmp_roomptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
460 mp_twolimb_t accu = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
461 size_t count;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
462 for (count = b_len; count > 0; count--)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
463 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
464 accu += (mp_twolimb_t) *sourceptr++ << s;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
465 *destptr++ = (mp_limb_t) accu;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
466 accu = accu >> GMP_LIMB_BITS;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
467 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
468 /* accu must be zero, since that was how s was determined. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
469 if (accu != 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
470 abort ();
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
471 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
472 b_ptr = tmp_roomptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
473 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
474 /* Copy a, shifting it left by s bits, yields r.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
475 Memory layout:
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
476 At the beginning: r = roomptr[0..a_len],
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
477 at the end: r = roomptr[0..b_len-1], q = roomptr[b_len..a_len] */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
478 r_ptr = roomptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
479 if (s == 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
480 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
481 memcpy (r_ptr, a_ptr, a_len * sizeof (mp_limb_t));
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
482 r_ptr[a_len] = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
483 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
484 else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
485 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
486 const mp_limb_t *sourceptr = a_ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
487 mp_limb_t *destptr = r_ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
488 mp_twolimb_t accu = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
489 size_t count;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
490 for (count = a_len; count > 0; count--)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
491 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
492 accu += (mp_twolimb_t) *sourceptr++ << s;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
493 *destptr++ = (mp_limb_t) accu;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
494 accu = accu >> GMP_LIMB_BITS;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
495 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
496 *destptr++ = (mp_limb_t) accu;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
497 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
498 q_ptr = roomptr + b_len;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
499 q_len = a_len - b_len + 1; /* q will have m-n+1 limbs */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
500 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
501 size_t j = a_len - b_len; /* m-n */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
502 mp_limb_t b_msd = b_ptr[b_len - 1]; /* b[n-1] */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
503 mp_limb_t b_2msd = b_ptr[b_len - 2]; /* b[n-2] */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
504 mp_twolimb_t b_msdd = /* b[n-1]*beta+b[n-2] */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
505 ((mp_twolimb_t) b_msd << GMP_LIMB_BITS) | b_2msd;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
506 /* Division loop, traversed m-n+1 times.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
507 j counts down, b is unchanged, beta/2 <= b[n-1] < beta. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
508 for (;;)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
509 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
510 mp_limb_t q_star;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
511 mp_limb_t c1;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
512 if (r_ptr[j + b_len] < b_msd) /* r[j+n] < b[n-1] ? */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
513 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
514 /* Divide r[j+n]*beta+r[j+n-1] by b[n-1], no overflow. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
515 mp_twolimb_t num =
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
516 ((mp_twolimb_t) r_ptr[j + b_len] << GMP_LIMB_BITS)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
517 | r_ptr[j + b_len - 1];
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
518 q_star = num / b_msd;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
519 c1 = num % b_msd;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
520 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
521 else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
522 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
523 /* Overflow, hence r[j+n]*beta+r[j+n-1] >= beta*b[n-1]. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
524 q_star = (mp_limb_t)~(mp_limb_t)0; /* q* = beta-1 */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
525 /* Test whether r[j+n]*beta+r[j+n-1] - (beta-1)*b[n-1] >= beta
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
526 <==> r[j+n]*beta+r[j+n-1] + b[n-1] >= beta*b[n-1]+beta
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
527 <==> b[n-1] < floor((r[j+n]*beta+r[j+n-1]+b[n-1])/beta)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
528 {<= beta !}.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
529 If yes, jump directly to the subtraction loop.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
530 (Otherwise, r[j+n]*beta+r[j+n-1] - (beta-1)*b[n-1] < beta
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
531 <==> floor((r[j+n]*beta+r[j+n-1]+b[n-1])/beta) = b[n-1] ) */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
532 if (r_ptr[j + b_len] > b_msd
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
533 || (c1 = r_ptr[j + b_len - 1] + b_msd) < b_msd)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
534 /* r[j+n] >= b[n-1]+1 or
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
535 r[j+n] = b[n-1] and the addition r[j+n-1]+b[n-1] gives a
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
536 carry. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
537 goto subtract;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
538 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
539 /* q_star = q*,
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
540 c1 = (r[j+n]*beta+r[j+n-1]) - q* * b[n-1] (>=0, <beta). */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
541 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
542 mp_twolimb_t c2 = /* c1*beta+r[j+n-2] */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
543 ((mp_twolimb_t) c1 << GMP_LIMB_BITS) | r_ptr[j + b_len - 2];
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
544 mp_twolimb_t c3 = /* b[n-2] * q* */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
545 (mp_twolimb_t) b_2msd * (mp_twolimb_t) q_star;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
546 /* While c2 < c3, increase c2 and decrease c3.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
547 Consider c3-c2. While it is > 0, decrease it by
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
548 b[n-1]*beta+b[n-2]. Because of b[n-1]*beta+b[n-2] >= beta^2/2
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
549 this can happen only twice. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
550 if (c3 > c2)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
551 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
552 q_star = q_star - 1; /* q* := q* - 1 */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
553 if (c3 - c2 > b_msdd)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
554 q_star = q_star - 1; /* q* := q* - 1 */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
555 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
556 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
557 if (q_star > 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
558 subtract:
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
559 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
560 /* Subtract r := r - b * q* * beta^j. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
561 mp_limb_t cr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
562 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
563 const mp_limb_t *sourceptr = b_ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
564 mp_limb_t *destptr = r_ptr + j;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
565 mp_twolimb_t carry = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
566 size_t count;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
567 for (count = b_len; count > 0; count--)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
568 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
569 /* Here 0 <= carry <= q*. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
570 carry =
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
571 carry
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
572 + (mp_twolimb_t) q_star * (mp_twolimb_t) *sourceptr++
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
573 + (mp_limb_t) ~(*destptr);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
574 /* Here 0 <= carry <= beta*q* + beta-1. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
575 *destptr++ = ~(mp_limb_t) carry;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
576 carry = carry >> GMP_LIMB_BITS; /* <= q* */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
577 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
578 cr = (mp_limb_t) carry;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
579 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
580 /* Subtract cr from r_ptr[j + b_len], then forget about
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
581 r_ptr[j + b_len]. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
582 if (cr > r_ptr[j + b_len])
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
583 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
584 /* Subtraction gave a carry. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
585 q_star = q_star - 1; /* q* := q* - 1 */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
586 /* Add b back. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
587 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
588 const mp_limb_t *sourceptr = b_ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
589 mp_limb_t *destptr = r_ptr + j;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
590 mp_limb_t carry = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
591 size_t count;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
592 for (count = b_len; count > 0; count--)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
593 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
594 mp_limb_t source1 = *sourceptr++;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
595 mp_limb_t source2 = *destptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
596 *destptr++ = source1 + source2 + carry;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
597 carry =
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
598 (carry
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
599 ? source1 >= (mp_limb_t) ~source2
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
600 : source1 > (mp_limb_t) ~source2);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
601 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
602 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
603 /* Forget about the carry and about r[j+n]. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
604 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
605 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
606 /* q* is determined. Store it as q[j]. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
607 q_ptr[j] = q_star;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
608 if (j == 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
609 break;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
610 j--;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
611 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
612 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
613 r_len = b_len;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
614 /* Normalise q. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
615 if (q_ptr[q_len - 1] == 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
616 q_len--;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
617 # if 0 /* Not needed here, since we need r only to compare it with b/2, and
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
618 b is shifted left by s bits. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
619 /* Shift r right by s bits. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
620 if (s > 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
621 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
622 mp_limb_t ptr = r_ptr + r_len;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
623 mp_twolimb_t accu = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
624 size_t count;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
625 for (count = r_len; count > 0; count--)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
626 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
627 accu = (mp_twolimb_t) (mp_limb_t) accu << GMP_LIMB_BITS;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
628 accu += (mp_twolimb_t) *--ptr << (GMP_LIMB_BITS - s);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
629 *ptr = (mp_limb_t) (accu >> GMP_LIMB_BITS);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
630 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
631 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
632 # endif
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
633 /* Normalise r. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
634 while (r_len > 0 && r_ptr[r_len - 1] == 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
635 r_len--;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
636 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
637 /* Compare r << 1 with b. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
638 if (r_len > b_len)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
639 goto increment_q;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
640 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
641 size_t i;
8835
c06bc412ffc3 Fix small bug in 'divide' function.
Bruno Haible <bruno@clisp.org>
parents: 8832
diff changeset
642 for (i = b_len;;)
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
643 {
8835
c06bc412ffc3 Fix small bug in 'divide' function.
Bruno Haible <bruno@clisp.org>
parents: 8832
diff changeset
644 mp_limb_t r_i =
c06bc412ffc3 Fix small bug in 'divide' function.
Bruno Haible <bruno@clisp.org>
parents: 8832
diff changeset
645 (i <= r_len && i > 0 ? r_ptr[i - 1] >> (GMP_LIMB_BITS - 1) : 0)
c06bc412ffc3 Fix small bug in 'divide' function.
Bruno Haible <bruno@clisp.org>
parents: 8832
diff changeset
646 | (i < r_len ? r_ptr[i] << 1 : 0);
c06bc412ffc3 Fix small bug in 'divide' function.
Bruno Haible <bruno@clisp.org>
parents: 8832
diff changeset
647 mp_limb_t b_i = (i < b_len ? b_ptr[i] : 0);
c06bc412ffc3 Fix small bug in 'divide' function.
Bruno Haible <bruno@clisp.org>
parents: 8832
diff changeset
648 if (r_i > b_i)
c06bc412ffc3 Fix small bug in 'divide' function.
Bruno Haible <bruno@clisp.org>
parents: 8832
diff changeset
649 goto increment_q;
c06bc412ffc3 Fix small bug in 'divide' function.
Bruno Haible <bruno@clisp.org>
parents: 8832
diff changeset
650 if (r_i < b_i)
c06bc412ffc3 Fix small bug in 'divide' function.
Bruno Haible <bruno@clisp.org>
parents: 8832
diff changeset
651 goto keep_q;
c06bc412ffc3 Fix small bug in 'divide' function.
Bruno Haible <bruno@clisp.org>
parents: 8832
diff changeset
652 if (i == 0)
c06bc412ffc3 Fix small bug in 'divide' function.
Bruno Haible <bruno@clisp.org>
parents: 8832
diff changeset
653 break;
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
654 i--;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
655 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
656 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
657 if (q_len > 0 && ((q_ptr[0] & 1) != 0))
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
658 /* q is odd. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
659 increment_q:
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
660 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
661 size_t i;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
662 for (i = 0; i < q_len; i++)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
663 if (++(q_ptr[i]) != 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
664 goto keep_q;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
665 q_ptr[q_len++] = 1;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
666 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
667 keep_q:
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
668 if (tmp_roomptr != NULL)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
669 free (tmp_roomptr);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
670 q->limbs = q_ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
671 q->nlimbs = q_len;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
672 return roomptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
673 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
674
8838
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
675 /* Convert a bignum a >= 0, multiplied with 10^extra_zeroes, to decimal
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
676 representation.
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
677 Destroys the contents of a.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
678 Return the allocated memory - containing the decimal digits in low-to-high
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
679 order, terminated with a NUL character - in case of success, NULL in case
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
680 of memory allocation failure. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
681 static char *
8838
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
682 convert_to_decimal (mpn_t a, size_t extra_zeroes)
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
683 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
684 mp_limb_t *a_ptr = a.limbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
685 size_t a_len = a.nlimbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
686 /* 0.03345 is slightly larger than log(2)/(9*log(10)). */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
687 size_t c_len = 9 * ((size_t)(a_len * (GMP_LIMB_BITS * 0.03345f)) + 1);
8838
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
688 char *c_ptr = (char *) malloc (xsum (c_len, extra_zeroes));
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
689 if (c_ptr != NULL)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
690 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
691 char *d_ptr = c_ptr;
8838
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
692 for (; extra_zeroes > 0; extra_zeroes--)
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
693 *d_ptr++ = '0';
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
694 while (a_len > 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
695 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
696 /* Divide a by 10^9, in-place. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
697 mp_limb_t remainder = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
698 mp_limb_t *ptr = a_ptr + a_len;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
699 size_t count;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
700 for (count = a_len; count > 0; count--)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
701 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
702 mp_twolimb_t num =
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
703 ((mp_twolimb_t) remainder << GMP_LIMB_BITS) | *--ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
704 *ptr = num / 1000000000;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
705 remainder = num % 1000000000;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
706 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
707 /* Store the remainder as 9 decimal digits. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
708 for (count = 9; count > 0; count--)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
709 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
710 *d_ptr++ = '0' + (remainder % 10);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
711 remainder = remainder / 10;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
712 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
713 /* Normalize a. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
714 if (a_ptr[a_len - 1] == 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
715 a_len--;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
716 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
717 /* Remove leading zeroes. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
718 while (d_ptr > c_ptr && d_ptr[-1] == '0')
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
719 d_ptr--;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
720 /* But keep at least one zero. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
721 if (d_ptr == c_ptr)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
722 *d_ptr++ = '0';
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
723 /* Terminate the string. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
724 *d_ptr = '\0';
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
725 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
726 return c_ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
727 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
728
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
729 /* Assuming x is finite and >= 0:
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
730 write x as x = 2^e * m, where m is a bignum.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
731 Return the allocated memory in case of success, NULL in case of memory
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
732 allocation failure. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
733 static void *
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
734 decode_long_double (long double x, int *ep, mpn_t *mp)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
735 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
736 mpn_t m;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
737 int exp;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
738 long double y;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
739 size_t i;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
740
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
741 /* Allocate memory for result. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
742 m.nlimbs = (LDBL_MANT_BIT + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
743 m.limbs = (mp_limb_t *) malloc (m.nlimbs * sizeof (mp_limb_t));
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
744 if (m.limbs == NULL)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
745 return NULL;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
746 /* Split into exponential part and mantissa. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
747 y = frexpl (x, &exp);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
748 if (!(y >= 0.0L && y < 1.0L))
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
749 abort ();
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
750 /* x = 2^exp * y = 2^(exp - LDBL_MANT_BIT) * (y * LDBL_MANT_BIT), and the
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
751 latter is an integer. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
752 /* Convert the mantissa (y * LDBL_MANT_BIT) to a sequence of limbs.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
753 I'm not sure whether it's safe to cast a 'long double' value between
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
754 2^31 and 2^32 to 'unsigned int', therefore play safe and cast only
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
755 'long double' values between 0 and 2^16 (to 'unsigned int' or 'int',
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
756 doesn't matter). */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
757 # if (LDBL_MANT_BIT % GMP_LIMB_BITS) != 0
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
758 # if (LDBL_MANT_BIT % GMP_LIMB_BITS) > GMP_LIMB_BITS / 2
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
759 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
760 mp_limb_t hi, lo;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
761 y *= (mp_limb_t) 1 << (LDBL_MANT_BIT % (GMP_LIMB_BITS / 2));
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
762 hi = (int) y;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
763 y -= hi;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
764 if (!(y >= 0.0L && y < 1.0L))
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
765 abort ();
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
766 y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
767 lo = (int) y;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
768 y -= lo;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
769 if (!(y >= 0.0L && y < 1.0L))
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
770 abort ();
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
771 m.limbs[LDBL_MANT_BIT / GMP_LIMB_BITS] = (hi << (GMP_LIMB_BITS / 2)) | lo;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
772 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
773 # else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
774 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
775 mp_limb_t d;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
776 y *= (mp_limb_t) 1 << (LDBL_MANT_BIT % GMP_LIMB_BITS);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
777 d = (int) y;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
778 y -= d;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
779 if (!(y >= 0.0L && y < 1.0L))
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
780 abort ();
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
781 m.limbs[LDBL_MANT_BIT / GMP_LIMB_BITS] = d;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
782 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
783 # endif
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
784 # endif
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
785 for (i = LDBL_MANT_BIT / GMP_LIMB_BITS; i > 0; )
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
786 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
787 mp_limb_t hi, lo;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
788 y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
789 hi = (int) y;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
790 y -= hi;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
791 if (!(y >= 0.0L && y < 1.0L))
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
792 abort ();
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
793 y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
794 lo = (int) y;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
795 y -= lo;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
796 if (!(y >= 0.0L && y < 1.0L))
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
797 abort ();
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
798 m.limbs[--i] = (hi << (GMP_LIMB_BITS / 2)) | lo;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
799 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
800 if (!(y == 0.0L))
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
801 abort ();
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
802 /* Normalise. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
803 while (m.nlimbs > 0 && m.limbs[m.nlimbs - 1] == 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
804 m.nlimbs--;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
805 *mp = m;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
806 *ep = exp - LDBL_MANT_BIT;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
807 return m.limbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
808 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
809
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
810 /* Assuming x is finite and >= 0, and n is an integer:
8838
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
811 Returns the decimal representation of round (x * 10^n).
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
812 Return the allocated memory - containing the decimal digits in low-to-high
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
813 order, terminated with a NUL character - in case of success, NULL in case
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
814 of memory allocation failure. */
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
815 static char *
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
816 scale10_round_decimal_long_double (long double x, int n)
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
817 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
818 int e;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
819 mpn_t m;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
820 void *memory = decode_long_double (x, &e, &m);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
821 int s;
8838
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
822 size_t extra_zeroes;
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
823 unsigned int abs_n;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
824 unsigned int abs_s;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
825 mp_limb_t *pow5_ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
826 size_t pow5_len;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
827 unsigned int s_limbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
828 unsigned int s_bits;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
829 mpn_t pow5;
8838
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
830 mpn_t z;
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
831 void *z_memory;
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
832 char *digits;
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
833
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
834 if (memory == NULL)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
835 return NULL;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
836 /* x = 2^e * m, hence
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
837 y = round (2^e * 10^n * m) = round (2^(e+n) * 5^n * m)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
838 = round (2^s * 5^n * m). */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
839 s = e + n;
8838
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
840 extra_zeroes = 0;
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
841 /* Factor out a common power of 10 if possible. */
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
842 if (s > 0 && n > 0)
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
843 {
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
844 extra_zeroes = (s < n ? s : n);
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
845 s -= extra_zeroes;
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
846 n -= extra_zeroes;
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
847 }
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
848 /* Here y = round (2^s * 5^n * m) * 10^extra_zeroes.
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
849 Before converting to decimal, we need to compute
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
850 z = round (2^s * 5^n * m). */
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
851 /* Compute 5^|n|, possibly shifted by |s| bits if n and s have the same
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
852 sign. 2.322 is slightly larger than log(5)/log(2). */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
853 abs_n = (n >= 0 ? n : -n);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
854 abs_s = (s >= 0 ? s : -s);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
855 pow5_ptr = (mp_limb_t *) malloc (((int)(abs_n * (2.322f / GMP_LIMB_BITS)) + 1
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
856 + abs_s / GMP_LIMB_BITS + 1)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
857 * sizeof (mp_limb_t));
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
858 if (pow5_ptr == NULL)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
859 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
860 free (memory);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
861 return NULL;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
862 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
863 /* Initialize with 1. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
864 pow5_ptr[0] = 1;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
865 pow5_len = 1;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
866 /* Multiply with 5^|n|. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
867 if (abs_n > 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
868 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
869 static mp_limb_t const small_pow5[13 + 1] =
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
870 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
871 1, 5, 25, 125, 625, 3125, 15625, 78125, 390625, 1953125, 9765625,
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
872 48828125, 244140625, 1220703125
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
873 };
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
874 unsigned int n13;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
875 for (n13 = 0; n13 <= abs_n; n13 += 13)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
876 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
877 mp_limb_t digit1 = small_pow5[n13 + 13 <= abs_n ? 13 : abs_n - n13];
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
878 size_t j;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
879 mp_twolimb_t carry = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
880 for (j = 0; j < pow5_len; j++)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
881 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
882 mp_limb_t digit2 = pow5_ptr[j];
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
883 carry += (mp_twolimb_t) digit1 * (mp_twolimb_t) digit2;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
884 pow5_ptr[j] = (mp_limb_t) carry;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
885 carry = carry >> GMP_LIMB_BITS;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
886 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
887 if (carry > 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
888 pow5_ptr[pow5_len++] = (mp_limb_t) carry;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
889 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
890 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
891 s_limbs = abs_s / GMP_LIMB_BITS;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
892 s_bits = abs_s % GMP_LIMB_BITS;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
893 if (n >= 0 ? s >= 0 : s <= 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
894 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
895 /* Multiply with 2^|s|. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
896 if (s_bits > 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
897 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
898 mp_limb_t *ptr = pow5_ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
899 mp_twolimb_t accu = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
900 size_t count;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
901 for (count = pow5_len; count > 0; count--)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
902 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
903 accu += (mp_twolimb_t) *ptr << s_bits;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
904 *ptr++ = (mp_limb_t) accu;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
905 accu = accu >> GMP_LIMB_BITS;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
906 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
907 if (accu > 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
908 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
909 *ptr = (mp_limb_t) accu;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
910 pow5_len++;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
911 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
912 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
913 if (s_limbs > 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
914 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
915 size_t count;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
916 for (count = pow5_len; count > 0;)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
917 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
918 count--;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
919 pow5_ptr[s_limbs + count] = pow5_ptr[count];
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
920 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
921 for (count = s_limbs; count > 0;)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
922 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
923 count--;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
924 pow5_ptr[count] = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
925 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
926 pow5_len += s_limbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
927 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
928 pow5.limbs = pow5_ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
929 pow5.nlimbs = pow5_len;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
930 if (n >= 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
931 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
932 /* Multiply m with pow5. No division needed. */
8838
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
933 z_memory = multiply (m, pow5, &z);
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
934 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
935 else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
936 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
937 /* Divide m by pow5 and round. */
8838
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
938 z_memory = divide (m, pow5, &z);
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
939 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
940 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
941 else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
942 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
943 pow5.limbs = pow5_ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
944 pow5.nlimbs = pow5_len;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
945 if (n >= 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
946 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
947 /* n >= 0, s < 0.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
948 Multiply m with pow5, then divide by 2^|s|. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
949 mpn_t numerator;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
950 mpn_t denominator;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
951 void *tmp_memory;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
952 tmp_memory = multiply (m, pow5, &numerator);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
953 if (tmp_memory == NULL)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
954 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
955 free (pow5_ptr);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
956 free (memory);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
957 return NULL;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
958 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
959 /* Construct 2^|s|. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
960 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
961 mp_limb_t *ptr = pow5_ptr + pow5_len;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
962 size_t i;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
963 for (i = 0; i < s_limbs; i++)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
964 ptr[i] = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
965 ptr[s_limbs] = (mp_limb_t) 1 << s_bits;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
966 denominator.limbs = ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
967 denominator.nlimbs = s_limbs + 1;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
968 }
8838
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
969 z_memory = divide (numerator, denominator, &z);
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
970 free (tmp_memory);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
971 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
972 else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
973 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
974 /* n < 0, s > 0.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
975 Multiply m with 2^s, then divide by pow5. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
976 mpn_t numerator;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
977 mp_limb_t *num_ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
978 num_ptr = (mp_limb_t *) malloc ((m.nlimbs + s_limbs + 1)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
979 * sizeof (mp_limb_t));
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
980 if (num_ptr == NULL)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
981 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
982 free (pow5_ptr);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
983 free (memory);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
984 return NULL;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
985 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
986 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
987 mp_limb_t *destptr = num_ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
988 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
989 size_t i;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
990 for (i = 0; i < s_limbs; i++)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
991 *destptr++ = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
992 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
993 if (s_bits > 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
994 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
995 const mp_limb_t *sourceptr = m.limbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
996 mp_twolimb_t accu = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
997 size_t count;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
998 for (count = m.nlimbs; count > 0; count--)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
999 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1000 accu += (mp_twolimb_t) *sourceptr++ << s;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1001 *destptr++ = (mp_limb_t) accu;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1002 accu = accu >> GMP_LIMB_BITS;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1003 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1004 if (accu > 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1005 *destptr++ = (mp_limb_t) accu;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1006 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1007 else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1008 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1009 const mp_limb_t *sourceptr = m.limbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1010 size_t count;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1011 for (count = m.nlimbs; count > 0; count--)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1012 *destptr++ = *sourceptr++;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1013 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1014 numerator.limbs = num_ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1015 numerator.nlimbs = destptr - num_ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1016 }
8838
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
1017 z_memory = divide (numerator, pow5, &z);
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1018 free (num_ptr);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1019 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1020 }
8838
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
1021 free (pow5_ptr);
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
1022 free (memory);
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
1023
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
1024 /* Here y = round (x * 10^n) = z * 10^extra_zeroes. */
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1025
8838
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
1026 if (z_memory == NULL)
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1027 return NULL;
8838
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
1028 digits = convert_to_decimal (z, extra_zeroes);
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
1029 free (z_memory);
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1030 return digits;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1031 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1032
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1033 /* Assuming x is finite and > 0:
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1034 Return an approximation for n with 10^n <= x < 10^(n+1).
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1035 The approximation is usually the right n, but may be off by 1 sometimes. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1036 static int
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1037 floorlog10l (long double x)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1038 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1039 int exp;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1040 long double y;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1041 double z;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1042 double l;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1043
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1044 /* Split into exponential part and mantissa. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1045 y = frexpl (x, &exp);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1046 if (!(y >= 0.0L && y < 1.0L))
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1047 abort ();
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1048 if (y == 0.0L)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1049 return INT_MIN;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1050 if (y < 0.5L)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1051 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1052 while (y < (1.0L / (1 << (GMP_LIMB_BITS / 2)) / (1 << (GMP_LIMB_BITS / 2))))
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1053 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1054 y *= 1.0L * (1 << (GMP_LIMB_BITS / 2)) * (1 << (GMP_LIMB_BITS / 2));
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1055 exp -= GMP_LIMB_BITS;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1056 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1057 if (y < (1.0L / (1 << 16)))
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1058 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1059 y *= 1.0L * (1 << 16);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1060 exp -= 16;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1061 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1062 if (y < (1.0L / (1 << 8)))
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1063 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1064 y *= 1.0L * (1 << 8);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1065 exp -= 8;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1066 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1067 if (y < (1.0L / (1 << 4)))
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1068 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1069 y *= 1.0L * (1 << 4);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1070 exp -= 4;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1071 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1072 if (y < (1.0L / (1 << 2)))
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1073 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1074 y *= 1.0L * (1 << 2);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1075 exp -= 2;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1076 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1077 if (y < (1.0L / (1 << 1)))
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1078 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1079 y *= 1.0L * (1 << 1);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1080 exp -= 1;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1081 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1082 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1083 if (!(y >= 0.5L && y < 1.0L))
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1084 abort ();
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1085 /* Compute an approximation for l = log2(x) = exp + log2(y). */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1086 l = exp;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1087 z = y;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1088 if (z < 0.70710678118654752444)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1089 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1090 z *= 1.4142135623730950488;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1091 l -= 0.5;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1092 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1093 if (z < 0.8408964152537145431)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1094 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1095 z *= 1.1892071150027210667;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1096 l -= 0.25;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1097 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1098 if (z < 0.91700404320467123175)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1099 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1100 z *= 1.0905077326652576592;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1101 l -= 0.125;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1102 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1103 if (z < 0.9576032806985736469)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1104 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1105 z *= 1.0442737824274138403;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1106 l -= 0.0625;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1107 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1108 /* Now 0.95 <= z <= 1.01. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1109 z = 1 - z;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1110 /* log(1-z) = - z - z^2/2 - z^3/3 - z^4/4 - ...
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1111 Four terms are enough to get an approximation with error < 10^-7. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1112 l -= z * (1.0 + z * (0.5 + z * ((1.0 / 3) + z * 0.25)));
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1113 /* Finally multiply with log(2)/log(10), yields an approximation for
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1114 log10(x). */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1115 l *= 0.30102999566398119523;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1116 /* Round down to the next integer. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1117 return (int) l + (l < 0 ? -1 : 0);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1118 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1119
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1120 #endif
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1121
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
1122 CHAR_T *
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
1123 VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list args)
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1124 {
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
1125 DIRECTIVES d;
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1126 arguments a;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1127
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
1128 if (PRINTF_PARSE (format, &d, &a) < 0)
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1129 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1130 errno = EINVAL;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1131 return NULL;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1132 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1133
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1134 #define CLEANUP() \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1135 free (d.dir); \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1136 if (a.arg) \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1137 free (a.arg);
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1138
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1139 if (printf_fetchargs (args, &a) < 0)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1140 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1141 CLEANUP ();
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1142 errno = EINVAL;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1143 return NULL;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1144 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1145
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1146 {
4879
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1147 size_t buf_neededlength;
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1148 CHAR_T *buf;
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1149 CHAR_T *buf_malloced;
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
1150 const CHAR_T *cp;
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
1151 size_t i;
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
1152 DIRECTIVE *dp;
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1153 /* Output string accumulator. */
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
1154 CHAR_T *result;
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1155 size_t allocated;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1156 size_t length;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1157
4879
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1158 /* Allocate a small buffer that will hold a directive passed to
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1159 sprintf or snprintf. */
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1160 buf_neededlength =
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1161 xsum4 (7, d.max_width_length, d.max_precision_length, 6);
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1162 #if HAVE_ALLOCA
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1163 if (buf_neededlength < 4000 / sizeof (CHAR_T))
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1164 {
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1165 buf = (CHAR_T *) alloca (buf_neededlength * sizeof (CHAR_T));
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1166 buf_malloced = NULL;
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1167 }
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1168 else
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1169 #endif
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1170 {
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1171 size_t buf_memsize = xtimes (buf_neededlength, sizeof (CHAR_T));
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1172 if (size_overflow_p (buf_memsize))
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1173 goto out_of_memory_1;
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1174 buf = (CHAR_T *) malloc (buf_memsize);
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1175 if (buf == NULL)
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1176 goto out_of_memory_1;
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1177 buf_malloced = buf;
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1178 }
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1179
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1180 if (resultbuf != NULL)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1181 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1182 result = resultbuf;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1183 allocated = *lengthp;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1184 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1185 else
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1186 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1187 result = NULL;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1188 allocated = 0;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1189 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1190 length = 0;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1191 /* Invariants:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1192 result is either == resultbuf or == NULL or malloc-allocated.
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1193 If length > 0, then result != NULL. */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1194
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
1195 /* Ensures that allocated >= needed. Aborts through a jump to
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
1196 out_of_memory if needed is SIZE_MAX or otherwise too big. */
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1197 #define ENSURE_ALLOCATION(needed) \
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
1198 if ((needed) > allocated) \
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
1199 { \
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
1200 size_t memory_size; \
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
1201 CHAR_T *memory; \
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
1202 \
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
1203 allocated = (allocated > 0 ? xtimes (allocated, 2) : 12); \
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
1204 if ((needed) > allocated) \
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
1205 allocated = (needed); \
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
1206 memory_size = xtimes (allocated, sizeof (CHAR_T)); \
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
1207 if (size_overflow_p (memory_size)) \
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
1208 goto out_of_memory; \
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
1209 if (result == resultbuf || result == NULL) \
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
1210 memory = (CHAR_T *) malloc (memory_size); \
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
1211 else \
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
1212 memory = (CHAR_T *) realloc (result, memory_size); \
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
1213 if (memory == NULL) \
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
1214 goto out_of_memory; \
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
1215 if (result == resultbuf && length > 0) \
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
1216 memcpy (memory, result, length * sizeof (CHAR_T)); \
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
1217 result = memory; \
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1218 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1219
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1220 for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1221 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1222 if (cp != dp->dir_start)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1223 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1224 size_t n = dp->dir_start - cp;
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
1225 size_t augmented_length = xsum (length, n);
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1226
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
1227 ENSURE_ALLOCATION (augmented_length);
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
1228 memcpy (result + length, cp, n * sizeof (CHAR_T));
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
1229 length = augmented_length;
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1230 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1231 if (i == d.count)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1232 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1233
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1234 /* Execute a single directive. */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1235 if (dp->conversion == '%')
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1236 {
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
1237 size_t augmented_length;
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
1238
4886
e4317f1f2e2c Use size_t instead of ssize_t.
Bruno Haible <bruno@clisp.org>
parents: 4879
diff changeset
1239 if (!(dp->arg_index == ARG_NONE))
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1240 abort ();
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
1241 augmented_length = xsum (length, 1);
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
1242 ENSURE_ALLOCATION (augmented_length);
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1243 result[length] = '%';
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
1244 length = augmented_length;
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1245 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1246 else
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1247 {
4886
e4317f1f2e2c Use size_t instead of ssize_t.
Bruno Haible <bruno@clisp.org>
parents: 4879
diff changeset
1248 if (!(dp->arg_index != ARG_NONE))
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1249 abort ();
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1250
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1251 if (dp->conversion == 'n')
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1252 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1253 switch (a.arg[dp->arg_index].type)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1254 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1255 case TYPE_COUNT_SCHAR_POINTER:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1256 *a.arg[dp->arg_index].a.a_count_schar_pointer = length;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1257 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1258 case TYPE_COUNT_SHORT_POINTER:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1259 *a.arg[dp->arg_index].a.a_count_short_pointer = length;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1260 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1261 case TYPE_COUNT_INT_POINTER:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1262 *a.arg[dp->arg_index].a.a_count_int_pointer = length;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1263 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1264 case TYPE_COUNT_LONGINT_POINTER:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1265 *a.arg[dp->arg_index].a.a_count_longint_pointer = length;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1266 break;
8051
9c2b0396b27c Stylistic change: Use '#if HAVE_*' instead of '#ifdef HAVE_*'.
Bruno Haible <bruno@clisp.org>
parents: 7475
diff changeset
1267 #if HAVE_LONG_LONG_INT
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1268 case TYPE_COUNT_LONGLONGINT_POINTER:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1269 *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1270 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1271 #endif
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1272 default:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1273 abort ();
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1274 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1275 }
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1276 #if (NEED_PRINTF_INFINITE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1277 else if ((dp->conversion == 'f' || dp->conversion == 'F'
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1278 || dp->conversion == 'e' || dp->conversion == 'E'
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1279 || dp->conversion == 'g' || dp->conversion == 'G')
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1280 && (0
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1281 # if NEED_PRINTF_INFINITE
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1282 || (a.arg[dp->arg_index].type == TYPE_DOUBLE
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1283 /* The systems (mingw) which produce wrong output
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1284 for Inf and -Inf also do so for NaN and -0.0.
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1285 Therefore we treat these cases here as well. */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1286 && is_infinite_or_zero (a.arg[dp->arg_index].a.a_double))
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1287 # endif
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1288 # if NEED_PRINTF_LONG_DOUBLE
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1289 || a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1290 # endif
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1291 ))
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1292 {
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1293 arg_type type = a.arg[dp->arg_index].type;
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1294 int flags = dp->flags;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1295 int has_width;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1296 size_t width;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1297 int has_precision;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1298 size_t precision;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1299 size_t tmp_length;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1300 CHAR_T tmpbuf[700];
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1301 CHAR_T *tmp;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1302 CHAR_T *pad_ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1303 CHAR_T *p;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1304
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1305 has_width = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1306 width = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1307 if (dp->width_start != dp->width_end)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1308 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1309 if (dp->width_arg_index != ARG_NONE)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1310 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1311 int arg;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1312
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1313 if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1314 abort ();
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1315 arg = a.arg[dp->width_arg_index].a.a_int;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1316 if (arg < 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1317 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1318 /* "A negative field width is taken as a '-' flag
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1319 followed by a positive field width." */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1320 flags |= FLAG_LEFT;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1321 width = (unsigned int) (-arg);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1322 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1323 else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1324 width = arg;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1325 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1326 else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1327 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1328 const CHAR_T *digitp = dp->width_start;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1329
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1330 do
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1331 width = xsum (xtimes (width, 10), *digitp++ - '0');
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1332 while (digitp != dp->width_end);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1333 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1334 has_width = 1;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1335 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1336
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1337 has_precision = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1338 precision = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1339 if (dp->precision_start != dp->precision_end)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1340 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1341 if (dp->precision_arg_index != ARG_NONE)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1342 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1343 int arg;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1344
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1345 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1346 abort ();
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1347 arg = a.arg[dp->precision_arg_index].a.a_int;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1348 /* "A negative precision is taken as if the precision
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1349 were omitted." */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1350 if (arg >= 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1351 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1352 precision = arg;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1353 has_precision = 1;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1354 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1355 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1356 else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1357 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1358 const CHAR_T *digitp = dp->precision_start + 1;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1359
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1360 precision = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1361 while (digitp != dp->precision_end)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1362 precision = xsum (xtimes (precision, 10), *digitp++ - '0');
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1363 has_precision = 1;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1364 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1365 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1366
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1367 /* POSIX specifies the default precision to be 6 for %f, %F,
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1368 %e, %E, but not for %g, %G. Implementations appear to use
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1369 the same default precision also for %g, %G. */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1370 if (!has_precision)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1371 precision = 6;
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1372
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1373 /* Allocate a temporary buffer of sufficient size. */
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1374 # if NEED_PRINTF_INFINITE && NEED_PRINTF_LONG_DOUBLE
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1375 tmp_length = (type == TYPE_LONGDOUBLE ? LDBL_DIG + 1 : 0);
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1376 # elif NEED_PRINTF_LONG_DOUBLE
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1377 tmp_length = LDBL_DIG + 1;
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1378 # elif NEED_PRINTF_INFINITE
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1379 tmp_length = 0;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1380 # endif
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1381 if (tmp_length < precision)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1382 tmp_length = precision;
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1383 # if NEED_PRINTF_LONG_DOUBLE
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1384 # if NEED_PRINTF_INFINITE
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1385 if (type == TYPE_LONGDOUBLE)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1386 # endif
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1387 if (dp->conversion == 'f' || dp->conversion == 'F')
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1388 {
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1389 long double arg = a.arg[dp->arg_index].a.a_longdouble;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1390 if (!(isnanl (arg) || arg + arg == arg))
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1391 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1392 /* arg is finite and nonzero. */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1393 int exponent = floorlog10l (arg < 0 ? -arg : arg);
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1394 if (exponent >= 0 && tmp_length < exponent + precision)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1395 tmp_length = exponent + precision;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1396 }
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1397 }
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1398 # endif
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1399 /* Account for sign, decimal point etc. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1400 tmp_length = xsum (tmp_length, 12);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1401
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1402 if (tmp_length < width)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1403 tmp_length = width;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1404
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1405 tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1406
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1407 if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T))
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1408 tmp = tmpbuf;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1409 else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1410 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1411 size_t tmp_memsize = xtimes (tmp_length, sizeof (CHAR_T));
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1412
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1413 if (size_overflow_p (tmp_memsize))
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1414 /* Overflow, would lead to out of memory. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1415 goto out_of_memory;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1416 tmp = (CHAR_T *) malloc (tmp_memsize);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1417 if (tmp == NULL)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1418 /* Out of memory. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1419 goto out_of_memory;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1420 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1421
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1422 pad_ptr = NULL;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1423 p = tmp;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1424
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1425 # if NEED_PRINTF_LONG_DOUBLE
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1426 # if NEED_PRINTF_INFINITE
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1427 if (type == TYPE_LONGDOUBLE)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1428 # endif
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1429 {
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1430 long double arg = a.arg[dp->arg_index].a.a_longdouble;
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1431
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1432 if (isnanl (arg))
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1433 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1434 if (dp->conversion >= 'A' && dp->conversion <= 'Z')
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1435 {
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1436 *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1437 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1438 else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1439 {
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1440 *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1441 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1442 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1443 else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1444 {
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1445 int sign = 0;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1446 DECL_LONG_DOUBLE_ROUNDING
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1447
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1448 BEGIN_LONG_DOUBLE_ROUNDING ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1449
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1450 if (signbit (arg)) /* arg < 0.0L or negative zero */
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1451 {
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1452 sign = -1;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1453 arg = -arg;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1454 }
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1455
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1456 if (sign < 0)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1457 *p++ = '-';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1458 else if (flags & FLAG_SHOWSIGN)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1459 *p++ = '+';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1460 else if (flags & FLAG_SPACE)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1461 *p++ = ' ';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1462
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1463 if (arg > 0.0L && arg + arg == arg)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1464 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1465 if (dp->conversion >= 'A' && dp->conversion <= 'Z')
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1466 {
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1467 *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1468 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1469 else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1470 {
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1471 *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1472 }
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1473 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1474 else
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1475 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1476 pad_ptr = p;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1477
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1478 if (dp->conversion == 'f' || dp->conversion == 'F')
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1479 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1480 char *digits;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1481 size_t ndigits;
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1482
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1483 digits =
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1484 scale10_round_decimal_long_double (arg, precision);
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1485 if (digits == NULL)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1486 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1487 END_LONG_DOUBLE_ROUNDING ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1488 goto out_of_memory;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1489 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1490 ndigits = strlen (digits);
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1491
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1492 if (ndigits > precision)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1493 do
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1494 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1495 --ndigits;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1496 *p++ = digits[ndigits];
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1497 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1498 while (ndigits > precision);
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1499 else
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1500 *p++ = '0';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1501 /* Here ndigits <= precision. */
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1502 if ((flags & FLAG_ALT) || precision > 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1503 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1504 *p++ = decimal_point_char ();
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1505 for (; precision > ndigits; precision--)
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1506 *p++ = '0';
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1507 while (ndigits > 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1508 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1509 --ndigits;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1510 *p++ = digits[ndigits];
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1511 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1512 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1513
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1514 free (digits);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1515 }
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1516 else if (dp->conversion == 'e' || dp->conversion == 'E')
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1517 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1518 int exponent;
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1519
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1520 if (arg == 0.0L)
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1521 {
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1522 exponent = 0;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1523 *p++ = '0';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1524 if ((flags & FLAG_ALT) || precision > 0)
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1525 {
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1526 *p++ = decimal_point_char ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1527 for (; precision > 0; precision--)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1528 *p++ = '0';
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1529 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1530 }
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1531 else
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1532 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1533 /* arg > 0.0L. */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1534 int adjusted;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1535 char *digits;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1536 size_t ndigits;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1537
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1538 exponent = floorlog10l (arg);
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1539 adjusted = 0;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1540 for (;;)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1541 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1542 digits =
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1543 scale10_round_decimal_long_double (arg,
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1544 (int)precision - exponent);
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1545 if (digits == NULL)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1546 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1547 END_LONG_DOUBLE_ROUNDING ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1548 goto out_of_memory;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1549 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1550 ndigits = strlen (digits);
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1551
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1552 if (ndigits == precision + 1)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1553 break;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1554 if (ndigits < precision
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1555 || ndigits > precision + 2)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1556 /* The exponent was not guessed
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1557 precisely enough. */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1558 abort ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1559 if (adjusted)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1560 /* None of two values of exponent is
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1561 the right one. Prevent an endless
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1562 loop. */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1563 abort ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1564 free (digits);
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1565 if (ndigits == precision)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1566 exponent -= 1;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1567 else
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1568 exponent += 1;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1569 adjusted = 1;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1570 }
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1571
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1572 /* Here ndigits = precision+1. */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1573 *p++ = digits[--ndigits];
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1574 if ((flags & FLAG_ALT) || precision > 0)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1575 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1576 *p++ = decimal_point_char ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1577 while (ndigits > 0)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1578 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1579 --ndigits;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1580 *p++ = digits[ndigits];
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1581 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1582 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1583
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1584 free (digits);
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1585 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1586
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1587 *p++ = dp->conversion; /* 'e' or 'E' */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1588 # if WIDE_CHAR_VERSION
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1589 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1590 static const wchar_t decimal_format[] =
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1591 { '%', '+', '.', '2', 'd', '\0' };
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1592 SNPRINTF (p, 6 + 1, decimal_format, exponent);
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1593 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1594 # else
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1595 sprintf (p, "%+.2d", exponent);
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1596 # endif
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1597 while (*p != '\0')
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1598 p++;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1599 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1600 else if (dp->conversion == 'g' || dp->conversion == 'G')
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1601 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1602 if (precision == 0)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1603 precision = 1;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1604 /* precision >= 1. */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1605
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1606 if (arg == 0.0L)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1607 /* The exponent is 0, >= -4, < precision.
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1608 Use fixed-point notation. */
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1609 {
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1610 size_t ndigits = precision;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1611 /* Number of trailing zeroes that have to be
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1612 dropped. */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1613 size_t nzeroes =
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1614 (flags & FLAG_ALT ? 0 : precision - 1);
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1615
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1616 --ndigits;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1617 *p++ = '0';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1618 if ((flags & FLAG_ALT) || ndigits > nzeroes)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1619 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1620 *p++ = decimal_point_char ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1621 while (ndigits > nzeroes)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1622 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1623 --ndigits;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1624 *p++ = '0';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1625 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1626 }
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1627 }
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1628 else
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1629 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1630 /* arg > 0.0L. */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1631 int exponent;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1632 int adjusted;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1633 char *digits;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1634 size_t ndigits;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1635 size_t nzeroes;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1636
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1637 exponent = floorlog10l (arg);
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1638 adjusted = 0;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1639 for (;;)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1640 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1641 digits =
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1642 scale10_round_decimal_long_double (arg,
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1643 (int)(precision - 1) - exponent);
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1644 if (digits == NULL)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1645 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1646 END_LONG_DOUBLE_ROUNDING ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1647 goto out_of_memory;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1648 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1649 ndigits = strlen (digits);
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1650
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1651 if (ndigits == precision)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1652 break;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1653 if (ndigits < precision - 1
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1654 || ndigits > precision + 1)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1655 /* The exponent was not guessed
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1656 precisely enough. */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1657 abort ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1658 if (adjusted)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1659 /* None of two values of exponent is
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1660 the right one. Prevent an endless
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1661 loop. */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1662 abort ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1663 free (digits);
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1664 if (ndigits < precision)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1665 exponent -= 1;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1666 else
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1667 exponent += 1;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1668 adjusted = 1;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1669 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1670 /* Here ndigits = precision. */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1671
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1672 /* Determine the number of trailing zeroes
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1673 that have to be dropped. */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1674 nzeroes = 0;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1675 if ((flags & FLAG_ALT) == 0)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1676 while (nzeroes < ndigits
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1677 && digits[nzeroes] == '0')
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1678 nzeroes++;
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1679
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1680 /* The exponent is now determined. */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1681 if (exponent >= -4
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1682 && exponent < (long)precision)
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1683 {
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1684 /* Fixed-point notation:
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1685 max(exponent,0)+1 digits, then the
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1686 decimal point, then the remaining
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1687 digits without trailing zeroes. */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1688 if (exponent >= 0)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1689 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1690 size_t count = exponent + 1;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1691 /* Note: count <= precision = ndigits. */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1692 for (; count > 0; count--)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1693 *p++ = digits[--ndigits];
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1694 if ((flags & FLAG_ALT) || ndigits > nzeroes)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1695 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1696 *p++ = decimal_point_char ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1697 while (ndigits > nzeroes)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1698 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1699 --ndigits;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1700 *p++ = digits[ndigits];
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1701 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1702 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1703 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1704 else
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1705 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1706 size_t count = -exponent - 1;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1707 *p++ = '0';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1708 *p++ = decimal_point_char ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1709 for (; count > 0; count--)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1710 *p++ = '0';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1711 while (ndigits > nzeroes)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1712 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1713 --ndigits;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1714 *p++ = digits[ndigits];
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1715 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1716 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1717 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1718 else
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1719 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1720 /* Exponential notation. */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1721 *p++ = digits[--ndigits];
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1722 if ((flags & FLAG_ALT) || ndigits > nzeroes)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1723 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1724 *p++ = decimal_point_char ();
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1725 while (ndigits > nzeroes)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1726 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1727 --ndigits;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1728 *p++ = digits[ndigits];
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1729 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1730 }
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1731 *p++ = dp->conversion - 'G' + 'E'; /* 'e' or 'E' */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1732 # if WIDE_CHAR_VERSION
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1733 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1734 static const wchar_t decimal_format[] =
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1735 { '%', '+', '.', '2', 'd', '\0' };
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1736 SNPRINTF (p, 6 + 1, decimal_format, exponent);
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1737 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1738 # else
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1739 sprintf (p, "%+.2d", exponent);
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1740 # endif
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1741 while (*p != '\0')
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1742 p++;
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1743 }
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1744
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1745 free (digits);
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1746 }
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1747 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1748 else
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1749 abort ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1750 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1751
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1752 END_LONG_DOUBLE_ROUNDING ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1753 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1754 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1755 # if NEED_PRINTF_INFINITE
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1756 else
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1757 # endif
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1758 # endif
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1759 # if NEED_PRINTF_INFINITE
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1760 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1761 /* Simpler than above: handle only NaN, Infinity, zero. */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1762 double arg = a.arg[dp->arg_index].a.a_double;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1763
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1764 if (isnan (arg))
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1765 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1766 if (dp->conversion >= 'A' && dp->conversion <= 'Z')
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1767 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1768 *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1769 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1770 else
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1771 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1772 *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1773 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1774 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1775 else
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1776 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1777 int sign = 0;
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1778
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1779 if (signbit (arg)) /* arg < 0.0L or negative zero */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1780 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1781 sign = -1;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1782 arg = -arg;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1783 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1784
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1785 if (sign < 0)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1786 *p++ = '-';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1787 else if (flags & FLAG_SHOWSIGN)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1788 *p++ = '+';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1789 else if (flags & FLAG_SPACE)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1790 *p++ = ' ';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1791
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1792 if (arg > 0.0 && arg + arg == arg)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1793 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1794 if (dp->conversion >= 'A' && dp->conversion <= 'Z')
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1795 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1796 *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1797 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1798 else
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1799 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1800 *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1801 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1802 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1803 else
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1804 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1805 if (!(arg == 0.0))
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1806 abort ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1807
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1808 pad_ptr = p;
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1809
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1810 if (dp->conversion == 'f' || dp->conversion == 'F')
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1811 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1812 *p++ = '0';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1813 if ((flags & FLAG_ALT) || precision > 0)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1814 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1815 *p++ = decimal_point_char ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1816 for (; precision > 0; precision--)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1817 *p++ = '0';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1818 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1819 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1820 else if (dp->conversion == 'e' || dp->conversion == 'E')
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1821 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1822 *p++ = '0';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1823 if ((flags & FLAG_ALT) || precision > 0)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1824 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1825 *p++ = decimal_point_char ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1826 for (; precision > 0; precision--)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1827 *p++ = '0';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1828 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1829 *p++ = dp->conversion; /* 'e' or 'E' */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1830 *p++ = '+';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1831 /* Produce the same number of exponent digits as
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1832 the native printf implementation. */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1833 # if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1834 *p++ = '0';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1835 # endif
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1836 *p++ = '0';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1837 *p++ = '0';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1838 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1839 else if (dp->conversion == 'g' || dp->conversion == 'G')
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1840 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1841 *p++ = '0';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1842 if (flags & FLAG_ALT)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1843 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1844 size_t ndigits =
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1845 (precision > 0 ? precision - 1 : 0);
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1846 *p++ = decimal_point_char ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1847 for (; ndigits > 0; --ndigits)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1848 *p++ = '0';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1849 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1850 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1851 else
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1852 abort ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1853 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1854 }
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1855 }
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1856 # endif
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1857
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1858 /* The generated string now extends from tmp to p, with the
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1859 zero padding insertion point being at pad_ptr. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1860 if (has_width && p - tmp < width)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1861 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1862 size_t pad = width - (p - tmp);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1863 CHAR_T *end = p + pad;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1864
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1865 if (flags & FLAG_LEFT)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1866 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1867 /* Pad with spaces on the right. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1868 for (; pad > 0; pad--)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1869 *p++ = ' ';
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1870 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1871 else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1872 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1873 /* Pad with zeroes. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1874 CHAR_T *q = end;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1875
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1876 while (p > pad_ptr)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1877 *--q = *--p;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1878 for (; pad > 0; pad--)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1879 *p++ = '0';
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1880 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1881 else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1882 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1883 /* Pad with spaces on the left. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1884 CHAR_T *q = end;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1885
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1886 while (p > tmp)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1887 *--q = *--p;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1888 for (; pad > 0; pad--)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1889 *p++ = ' ';
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1890 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1891
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1892 p = end;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1893 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1894
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1895 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1896 size_t count = p - tmp;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1897
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1898 if (count >= tmp_length)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1899 /* tmp_length was incorrectly calculated - fix the
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1900 code above! */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1901 abort ();
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1902
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1903 /* Make room for the result. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1904 if (count >= allocated - length)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1905 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1906 size_t n = xsum (length, count);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1907
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1908 ENSURE_ALLOCATION (n);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1909 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1910
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1911 /* Append the result. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1912 memcpy (result + length, tmp, count * sizeof (CHAR_T));
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1913 if (tmp != tmpbuf)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1914 free (tmp);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1915 length += count;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1916 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1917 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1918 #endif
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1919 #if NEED_PRINTF_DIRECTIVE_A && !defined IN_LIBINTL
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1920 else if (dp->conversion == 'a' || dp->conversion == 'A')
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1921 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1922 arg_type type = a.arg[dp->arg_index].type;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1923 int flags = dp->flags;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1924 int has_width;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1925 size_t width;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1926 int has_precision;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1927 size_t precision;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1928 size_t tmp_length;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1929 CHAR_T tmpbuf[700];
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1930 CHAR_T *tmp;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1931 CHAR_T *pad_ptr;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1932 CHAR_T *p;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1933
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1934 has_width = 0;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1935 width = 0;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1936 if (dp->width_start != dp->width_end)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1937 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1938 if (dp->width_arg_index != ARG_NONE)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1939 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1940 int arg;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1941
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1942 if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1943 abort ();
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1944 arg = a.arg[dp->width_arg_index].a.a_int;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1945 if (arg < 0)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1946 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1947 /* "A negative field width is taken as a '-' flag
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1948 followed by a positive field width." */
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1949 flags |= FLAG_LEFT;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1950 width = (unsigned int) (-arg);
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1951 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1952 else
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1953 width = arg;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1954 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1955 else
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1956 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1957 const CHAR_T *digitp = dp->width_start;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1958
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1959 do
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1960 width = xsum (xtimes (width, 10), *digitp++ - '0');
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1961 while (digitp != dp->width_end);
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1962 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1963 has_width = 1;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1964 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1965
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1966 has_precision = 0;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1967 precision = 0;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1968 if (dp->precision_start != dp->precision_end)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1969 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1970 if (dp->precision_arg_index != ARG_NONE)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1971 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1972 int arg;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1973
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1974 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1975 abort ();
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1976 arg = a.arg[dp->precision_arg_index].a.a_int;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1977 /* "A negative precision is taken as if the precision
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1978 were omitted." */
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1979 if (arg >= 0)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1980 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1981 precision = arg;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1982 has_precision = 1;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1983 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1984 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1985 else
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1986 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1987 const CHAR_T *digitp = dp->precision_start + 1;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1988
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1989 precision = 0;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1990 while (digitp != dp->precision_end)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1991 precision = xsum (xtimes (precision, 10), *digitp++ - '0');
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1992 has_precision = 1;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1993 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1994 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1995
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1996 /* Allocate a temporary buffer of sufficient size. */
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1997 if (type == TYPE_LONGDOUBLE)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1998 tmp_length =
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1999 (unsigned int) ((LDBL_DIG + 1)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2000 * 0.831 /* decimal -> hexadecimal */
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2001 )
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2002 + 1; /* turn floor into ceil */
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2003 else
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2004 tmp_length =
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2005 (unsigned int) ((DBL_DIG + 1)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2006 * 0.831 /* decimal -> hexadecimal */
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2007 )
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2008 + 1; /* turn floor into ceil */
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2009 if (tmp_length < precision)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2010 tmp_length = precision;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2011 /* Account for sign, decimal point etc. */
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2012 tmp_length = xsum (tmp_length, 12);
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2013
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2014 if (tmp_length < width)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2015 tmp_length = width;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2016
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2017 tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2018
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2019 if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T))
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2020 tmp = tmpbuf;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2021 else
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2022 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2023 size_t tmp_memsize = xtimes (tmp_length, sizeof (CHAR_T));
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2024
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2025 if (size_overflow_p (tmp_memsize))
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2026 /* Overflow, would lead to out of memory. */
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2027 goto out_of_memory;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2028 tmp = (CHAR_T *) malloc (tmp_memsize);
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2029 if (tmp == NULL)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2030 /* Out of memory. */
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2031 goto out_of_memory;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2032 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2033
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2034 pad_ptr = NULL;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2035 p = tmp;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2036 if (type == TYPE_LONGDOUBLE)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2037 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2038 long double arg = a.arg[dp->arg_index].a.a_longdouble;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2039
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2040 if (isnanl (arg))
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2041 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2042 if (dp->conversion == 'A')
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2043 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2044 *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2045 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2046 else
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2047 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2048 *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2049 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2050 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2051 else
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2052 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2053 int sign = 0;
8531
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents: 8529
diff changeset
2054 DECL_LONG_DOUBLE_ROUNDING
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents: 8529
diff changeset
2055
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents: 8529
diff changeset
2056 BEGIN_LONG_DOUBLE_ROUNDING ();
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2057
8655
9a272158fe43 Faster determination of the sign of a number.
Bruno Haible <bruno@clisp.org>
parents: 8648
diff changeset
2058 if (signbit (arg)) /* arg < 0.0L or negative zero */
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2059 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2060 sign = -1;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2061 arg = -arg;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2062 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2063
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2064 if (sign < 0)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2065 *p++ = '-';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2066 else if (flags & FLAG_SHOWSIGN)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2067 *p++ = '+';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2068 else if (flags & FLAG_SPACE)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2069 *p++ = ' ';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2070
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2071 if (arg > 0.0L && arg + arg == arg)
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2072 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2073 if (dp->conversion == 'A')
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2074 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2075 *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2076 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2077 else
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2078 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2079 *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2080 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2081 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2082 else
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2083 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2084 int exponent;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2085 long double mantissa;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2086
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2087 if (arg > 0.0L)
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2088 mantissa = printf_frexpl (arg, &exponent);
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2089 else
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2090 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2091 exponent = 0;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2092 mantissa = 0.0L;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2093 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2094
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2095 if (has_precision
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2096 && precision < (unsigned int) ((LDBL_DIG + 1) * 0.831) + 1)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2097 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2098 /* Round the mantissa. */
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2099 long double tail = mantissa;
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2100 size_t q;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2101
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2102 for (q = precision; ; q--)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2103 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2104 int digit = (int) tail;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2105 tail -= digit;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2106 if (q == 0)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2107 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2108 if (digit & 1 ? tail >= 0.5L : tail > 0.5L)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2109 tail = 1 - tail;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2110 else
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2111 tail = - tail;
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2112 break;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2113 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2114 tail *= 16.0L;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2115 }
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2116 if (tail != 0.0L)
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2117 for (q = precision; q > 0; q--)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2118 tail *= 0.0625L;
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2119 mantissa += tail;
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2120 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2121
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2122 *p++ = '0';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2123 *p++ = dp->conversion - 'A' + 'X';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2124 pad_ptr = p;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2125 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2126 int digit;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2127
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2128 digit = (int) mantissa;
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2129 mantissa -= digit;
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2130 *p++ = '0' + digit;
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2131 if ((flags & FLAG_ALT)
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2132 || mantissa > 0.0L || precision > 0)
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2133 {
8569
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
2134 *p++ = decimal_point_char ();
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2135 /* This loop terminates because we assume
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2136 that FLT_RADIX is a power of 2. */
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2137 while (mantissa > 0.0L)
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2138 {
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2139 mantissa *= 16.0L;
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2140 digit = (int) mantissa;
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2141 mantissa -= digit;
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2142 *p++ = digit
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2143 + (digit < 10
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2144 ? '0'
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2145 : dp->conversion - 10);
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2146 if (precision > 0)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2147 precision--;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2148 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2149 while (precision > 0)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2150 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2151 *p++ = '0';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2152 precision--;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2153 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2154 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2155 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2156 *p++ = dp->conversion - 'A' + 'P';
8648
359d135f748c Assume 'long double' exists.
Bruno Haible <bruno@clisp.org>
parents: 8569
diff changeset
2157 # if WIDE_CHAR_VERSION
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2158 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2159 static const wchar_t decimal_format[] =
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2160 { '%', '+', 'd', '\0' };
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2161 SNPRINTF (p, 6 + 1, decimal_format, exponent);
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2162 }
8648
359d135f748c Assume 'long double' exists.
Bruno Haible <bruno@clisp.org>
parents: 8569
diff changeset
2163 # else
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2164 sprintf (p, "%+d", exponent);
8648
359d135f748c Assume 'long double' exists.
Bruno Haible <bruno@clisp.org>
parents: 8569
diff changeset
2165 # endif
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2166 while (*p != '\0')
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2167 p++;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2168 }
8531
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents: 8529
diff changeset
2169
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents: 8529
diff changeset
2170 END_LONG_DOUBLE_ROUNDING ();
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2171 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2172 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2173 else
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2174 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2175 double arg = a.arg[dp->arg_index].a.a_double;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2176
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2177 if (isnan (arg))
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2178 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2179 if (dp->conversion == 'A')
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2180 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2181 *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2182 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2183 else
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2184 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2185 *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2186 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2187 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2188 else
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2189 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2190 int sign = 0;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2191
8655
9a272158fe43 Faster determination of the sign of a number.
Bruno Haible <bruno@clisp.org>
parents: 8648
diff changeset
2192 if (signbit (arg)) /* arg < 0.0 or negative zero */
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2193 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2194 sign = -1;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2195 arg = -arg;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2196 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2197
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2198 if (sign < 0)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2199 *p++ = '-';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2200 else if (flags & FLAG_SHOWSIGN)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2201 *p++ = '+';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2202 else if (flags & FLAG_SPACE)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2203 *p++ = ' ';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2204
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2205 if (arg > 0.0 && arg + arg == arg)
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2206 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2207 if (dp->conversion == 'A')
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2208 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2209 *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2210 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2211 else
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2212 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2213 *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2214 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2215 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2216 else
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2217 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2218 int exponent;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2219 double mantissa;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2220
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2221 if (arg > 0.0)
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2222 mantissa = printf_frexp (arg, &exponent);
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2223 else
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2224 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2225 exponent = 0;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2226 mantissa = 0.0;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2227 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2228
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2229 if (has_precision
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2230 && precision < (unsigned int) ((DBL_DIG + 1) * 0.831) + 1)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2231 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2232 /* Round the mantissa. */
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2233 double tail = mantissa;
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2234 size_t q;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2235
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2236 for (q = precision; ; q--)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2237 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2238 int digit = (int) tail;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2239 tail -= digit;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2240 if (q == 0)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2241 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2242 if (digit & 1 ? tail >= 0.5 : tail > 0.5)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2243 tail = 1 - tail;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2244 else
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2245 tail = - tail;
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2246 break;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2247 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2248 tail *= 16.0;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2249 }
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2250 if (tail != 0.0)
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2251 for (q = precision; q > 0; q--)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2252 tail *= 0.0625;
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2253 mantissa += tail;
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2254 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2255
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2256 *p++ = '0';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2257 *p++ = dp->conversion - 'A' + 'X';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2258 pad_ptr = p;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2259 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2260 int digit;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2261
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2262 digit = (int) mantissa;
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2263 mantissa -= digit;
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2264 *p++ = '0' + digit;
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2265 if ((flags & FLAG_ALT)
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2266 || mantissa > 0.0 || precision > 0)
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2267 {
8569
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
2268 *p++ = decimal_point_char ();
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2269 /* This loop terminates because we assume
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2270 that FLT_RADIX is a power of 2. */
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2271 while (mantissa > 0.0)
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2272 {
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2273 mantissa *= 16.0;
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2274 digit = (int) mantissa;
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2275 mantissa -= digit;
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2276 *p++ = digit
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2277 + (digit < 10
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2278 ? '0'
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2279 : dp->conversion - 10);
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2280 if (precision > 0)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2281 precision--;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2282 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2283 while (precision > 0)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2284 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2285 *p++ = '0';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2286 precision--;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2287 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2288 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2289 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2290 *p++ = dp->conversion - 'A' + 'P';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2291 # if WIDE_CHAR_VERSION
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2292 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2293 static const wchar_t decimal_format[] =
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2294 { '%', '+', 'd', '\0' };
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2295 SNPRINTF (p, 6 + 1, decimal_format, exponent);
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2296 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2297 # else
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2298 sprintf (p, "%+d", exponent);
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2299 # endif
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2300 while (*p != '\0')
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2301 p++;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2302 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2303 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2304 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2305 /* The generated string now extends from tmp to p, with the
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2306 zero padding insertion point being at pad_ptr. */
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2307 if (has_width && p - tmp < width)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2308 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2309 size_t pad = width - (p - tmp);
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2310 CHAR_T *end = p + pad;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2311
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2312 if (flags & FLAG_LEFT)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2313 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2314 /* Pad with spaces on the right. */
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2315 for (; pad > 0; pad--)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2316 *p++ = ' ';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2317 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2318 else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2319 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2320 /* Pad with zeroes. */
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2321 CHAR_T *q = end;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2322
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2323 while (p > pad_ptr)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2324 *--q = *--p;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2325 for (; pad > 0; pad--)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2326 *p++ = '0';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2327 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2328 else
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2329 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2330 /* Pad with spaces on the left. */
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2331 CHAR_T *q = end;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2332
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2333 while (p > tmp)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2334 *--q = *--p;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2335 for (; pad > 0; pad--)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2336 *p++ = ' ';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2337 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2338
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2339 p = end;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2340 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2341
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2342 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2343 size_t count = p - tmp;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2344
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2345 if (count >= tmp_length)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2346 /* tmp_length was incorrectly calculated - fix the
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2347 code above! */
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2348 abort ();
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2349
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2350 /* Make room for the result. */
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2351 if (count >= allocated - length)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2352 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2353 size_t n = xsum (length, count);
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2354
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2355 ENSURE_ALLOCATION (n);
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2356 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2357
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2358 /* Append the result. */
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2359 memcpy (result + length, tmp, count * sizeof (CHAR_T));
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2360 if (tmp != tmpbuf)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2361 free (tmp);
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2362 length += count;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2363 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2364 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2365 #endif
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2366 else
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2367 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2368 arg_type type = a.arg[dp->arg_index].type;
8804
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2369 int flags = dp->flags;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2370 #if !USE_SNPRINTF || NEED_PRINTF_FLAG_ZERO
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2371 int has_width;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2372 size_t width;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2373 #endif
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2374 #if NEED_PRINTF_FLAG_ZERO
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2375 int pad_ourselves;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2376 #else
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2377 # define pad_ourselves 0
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2378 #endif
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2379 CHAR_T *fbp;
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2380 unsigned int prefix_count;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2381 int prefixes[2];
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
2382 #if !USE_SNPRINTF
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2383 size_t tmp_length;
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
2384 CHAR_T tmpbuf[700];
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
2385 CHAR_T *tmp;
8804
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2386 #endif
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2387
8804
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2388 #if !USE_SNPRINTF || NEED_PRINTF_FLAG_ZERO
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2389 has_width = 0;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2390 width = 0;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2391 if (dp->width_start != dp->width_end)
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2392 {
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2393 if (dp->width_arg_index != ARG_NONE)
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2394 {
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2395 int arg;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2396
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2397 if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2398 abort ();
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2399 arg = a.arg[dp->width_arg_index].a.a_int;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2400 if (arg < 0)
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2401 {
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2402 /* "A negative field width is taken as a '-' flag
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2403 followed by a positive field width." */
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2404 flags |= FLAG_LEFT;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2405 width = (unsigned int) (-arg);
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2406 }
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2407 else
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2408 width = arg;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2409 }
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2410 else
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2411 {
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2412 const CHAR_T *digitp = dp->width_start;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2413
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2414 do
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2415 width = xsum (xtimes (width, 10), *digitp++ - '0');
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2416 while (digitp != dp->width_end);
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2417 }
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2418 has_width = 1;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2419 }
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2420 #endif
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2421
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2422 #if !USE_SNPRINTF
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2423 /* Allocate a temporary buffer of sufficient size for calling
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2424 sprintf. */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2425 {
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2426 size_t precision;
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2427
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2428 precision = 6;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2429 if (dp->precision_start != dp->precision_end)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2430 {
4886
e4317f1f2e2c Use size_t instead of ssize_t.
Bruno Haible <bruno@clisp.org>
parents: 4879
diff changeset
2431 if (dp->precision_arg_index != ARG_NONE)
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2432 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2433 int arg;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2434
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2435 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2436 abort ();
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2437 arg = a.arg[dp->precision_arg_index].a.a_int;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2438 precision = (arg < 0 ? 0 : arg);
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2439 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2440 else
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2441 {
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
2442 const CHAR_T *digitp = dp->precision_start + 1;
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2443
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2444 precision = 0;
5066
a2cb70e482fc Fix for format strings like "%2.f".
Bruno Haible <bruno@clisp.org>
parents: 4886
diff changeset
2445 while (digitp != dp->precision_end)
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2446 precision = xsum (xtimes (precision, 10), *digitp++ - '0');
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2447 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2448 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2449
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2450 switch (dp->conversion)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2451 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2452
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2453 case 'd': case 'i': case 'u':
8051
9c2b0396b27c Stylistic change: Use '#if HAVE_*' instead of '#ifdef HAVE_*'.
Bruno Haible <bruno@clisp.org>
parents: 7475
diff changeset
2454 # if HAVE_LONG_LONG_INT
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2455 if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2456 tmp_length =
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2457 (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2458 * 0.30103 /* binary -> decimal */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2459 )
6583
eb8d54cb67a4 Fix an incorrect estimation of the sprintf result size.
Bruno Haible <bruno@clisp.org>
parents: 5848
diff changeset
2460 + 1; /* turn floor into ceil */
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2461 else
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2462 # endif
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2463 if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2464 tmp_length =
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2465 (unsigned int) (sizeof (unsigned long) * CHAR_BIT
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2466 * 0.30103 /* binary -> decimal */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2467 )
6583
eb8d54cb67a4 Fix an incorrect estimation of the sprintf result size.
Bruno Haible <bruno@clisp.org>
parents: 5848
diff changeset
2468 + 1; /* turn floor into ceil */
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2469 else
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2470 tmp_length =
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2471 (unsigned int) (sizeof (unsigned int) * CHAR_BIT
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2472 * 0.30103 /* binary -> decimal */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2473 )
6583
eb8d54cb67a4 Fix an incorrect estimation of the sprintf result size.
Bruno Haible <bruno@clisp.org>
parents: 5848
diff changeset
2474 + 1; /* turn floor into ceil */
eb8d54cb67a4 Fix an incorrect estimation of the sprintf result size.
Bruno Haible <bruno@clisp.org>
parents: 5848
diff changeset
2475 if (tmp_length < precision)
eb8d54cb67a4 Fix an incorrect estimation of the sprintf result size.
Bruno Haible <bruno@clisp.org>
parents: 5848
diff changeset
2476 tmp_length = precision;
eb8d54cb67a4 Fix an incorrect estimation of the sprintf result size.
Bruno Haible <bruno@clisp.org>
parents: 5848
diff changeset
2477 /* Multiply by 2, as an estimate for FLAG_GROUP. */
eb8d54cb67a4 Fix an incorrect estimation of the sprintf result size.
Bruno Haible <bruno@clisp.org>
parents: 5848
diff changeset
2478 tmp_length = xsum (tmp_length, tmp_length);
eb8d54cb67a4 Fix an incorrect estimation of the sprintf result size.
Bruno Haible <bruno@clisp.org>
parents: 5848
diff changeset
2479 /* Add 1, to account for a leading sign. */
eb8d54cb67a4 Fix an incorrect estimation of the sprintf result size.
Bruno Haible <bruno@clisp.org>
parents: 5848
diff changeset
2480 tmp_length = xsum (tmp_length, 1);
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2481 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2482
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2483 case 'o':
8051
9c2b0396b27c Stylistic change: Use '#if HAVE_*' instead of '#ifdef HAVE_*'.
Bruno Haible <bruno@clisp.org>
parents: 7475
diff changeset
2484 # if HAVE_LONG_LONG_INT
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2485 if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2486 tmp_length =
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2487 (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2488 * 0.333334 /* binary -> octal */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2489 )
6583
eb8d54cb67a4 Fix an incorrect estimation of the sprintf result size.
Bruno Haible <bruno@clisp.org>
parents: 5848
diff changeset
2490 + 1; /* turn floor into ceil */
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2491 else
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2492 # endif
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2493 if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2494 tmp_length =
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2495 (unsigned int) (sizeof (unsigned long) * CHAR_BIT
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2496 * 0.333334 /* binary -> octal */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2497 )
6583
eb8d54cb67a4 Fix an incorrect estimation of the sprintf result size.
Bruno Haible <bruno@clisp.org>
parents: 5848
diff changeset
2498 + 1; /* turn floor into ceil */
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2499 else
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2500 tmp_length =
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2501 (unsigned int) (sizeof (unsigned int) * CHAR_BIT
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2502 * 0.333334 /* binary -> octal */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2503 )
6583
eb8d54cb67a4 Fix an incorrect estimation of the sprintf result size.
Bruno Haible <bruno@clisp.org>
parents: 5848
diff changeset
2504 + 1; /* turn floor into ceil */
eb8d54cb67a4 Fix an incorrect estimation of the sprintf result size.
Bruno Haible <bruno@clisp.org>
parents: 5848
diff changeset
2505 if (tmp_length < precision)
eb8d54cb67a4 Fix an incorrect estimation of the sprintf result size.
Bruno Haible <bruno@clisp.org>
parents: 5848
diff changeset
2506 tmp_length = precision;
eb8d54cb67a4 Fix an incorrect estimation of the sprintf result size.
Bruno Haible <bruno@clisp.org>
parents: 5848
diff changeset
2507 /* Add 1, to account for a leading sign. */
eb8d54cb67a4 Fix an incorrect estimation of the sprintf result size.
Bruno Haible <bruno@clisp.org>
parents: 5848
diff changeset
2508 tmp_length = xsum (tmp_length, 1);
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2509 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2510
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2511 case 'x': case 'X':
8051
9c2b0396b27c Stylistic change: Use '#if HAVE_*' instead of '#ifdef HAVE_*'.
Bruno Haible <bruno@clisp.org>
parents: 7475
diff changeset
2512 # if HAVE_LONG_LONG_INT
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2513 if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2514 tmp_length =
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2515 (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2516 * 0.25 /* binary -> hexadecimal */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2517 )
6583
eb8d54cb67a4 Fix an incorrect estimation of the sprintf result size.
Bruno Haible <bruno@clisp.org>
parents: 5848
diff changeset
2518 + 1; /* turn floor into ceil */
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2519 else
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2520 # endif
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2521 if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2522 tmp_length =
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2523 (unsigned int) (sizeof (unsigned long) * CHAR_BIT
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2524 * 0.25 /* binary -> hexadecimal */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2525 )
6583
eb8d54cb67a4 Fix an incorrect estimation of the sprintf result size.
Bruno Haible <bruno@clisp.org>
parents: 5848
diff changeset
2526 + 1; /* turn floor into ceil */
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2527 else
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2528 tmp_length =
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2529 (unsigned int) (sizeof (unsigned int) * CHAR_BIT
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2530 * 0.25 /* binary -> hexadecimal */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2531 )
6583
eb8d54cb67a4 Fix an incorrect estimation of the sprintf result size.
Bruno Haible <bruno@clisp.org>
parents: 5848
diff changeset
2532 + 1; /* turn floor into ceil */
eb8d54cb67a4 Fix an incorrect estimation of the sprintf result size.
Bruno Haible <bruno@clisp.org>
parents: 5848
diff changeset
2533 if (tmp_length < precision)
eb8d54cb67a4 Fix an incorrect estimation of the sprintf result size.
Bruno Haible <bruno@clisp.org>
parents: 5848
diff changeset
2534 tmp_length = precision;
eb8d54cb67a4 Fix an incorrect estimation of the sprintf result size.
Bruno Haible <bruno@clisp.org>
parents: 5848
diff changeset
2535 /* Add 2, to account for a leading sign or alternate form. */
eb8d54cb67a4 Fix an incorrect estimation of the sprintf result size.
Bruno Haible <bruno@clisp.org>
parents: 5848
diff changeset
2536 tmp_length = xsum (tmp_length, 2);
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2537 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2538
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2539 case 'f': case 'F':
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2540 if (type == TYPE_LONGDOUBLE)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2541 tmp_length =
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2542 (unsigned int) (LDBL_MAX_EXP
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2543 * 0.30103 /* binary -> decimal */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2544 * 2 /* estimate for FLAG_GROUP */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2545 )
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2546 + 1 /* turn floor into ceil */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2547 + 10; /* sign, decimal point etc. */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2548 else
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2549 tmp_length =
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2550 (unsigned int) (DBL_MAX_EXP
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2551 * 0.30103 /* binary -> decimal */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2552 * 2 /* estimate for FLAG_GROUP */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2553 )
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2554 + 1 /* turn floor into ceil */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2555 + 10; /* sign, decimal point etc. */
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2556 tmp_length = xsum (tmp_length, precision);
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2557 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2558
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2559 case 'e': case 'E': case 'g': case 'G':
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2560 tmp_length =
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2561 12; /* sign, decimal point, exponent etc. */
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2562 tmp_length = xsum (tmp_length, precision);
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2563 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2564
8254
bbea39ab5a58 Fix estimate of size needed for a 'a' or 'A' conversion.
Bruno Haible <bruno@clisp.org>
parents: 8051
diff changeset
2565 case 'a': case 'A':
bbea39ab5a58 Fix estimate of size needed for a 'a' or 'A' conversion.
Bruno Haible <bruno@clisp.org>
parents: 8051
diff changeset
2566 if (type == TYPE_LONGDOUBLE)
bbea39ab5a58 Fix estimate of size needed for a 'a' or 'A' conversion.
Bruno Haible <bruno@clisp.org>
parents: 8051
diff changeset
2567 tmp_length =
bbea39ab5a58 Fix estimate of size needed for a 'a' or 'A' conversion.
Bruno Haible <bruno@clisp.org>
parents: 8051
diff changeset
2568 (unsigned int) (LDBL_DIG
bbea39ab5a58 Fix estimate of size needed for a 'a' or 'A' conversion.
Bruno Haible <bruno@clisp.org>
parents: 8051
diff changeset
2569 * 0.831 /* decimal -> hexadecimal */
bbea39ab5a58 Fix estimate of size needed for a 'a' or 'A' conversion.
Bruno Haible <bruno@clisp.org>
parents: 8051
diff changeset
2570 )
bbea39ab5a58 Fix estimate of size needed for a 'a' or 'A' conversion.
Bruno Haible <bruno@clisp.org>
parents: 8051
diff changeset
2571 + 1; /* turn floor into ceil */
bbea39ab5a58 Fix estimate of size needed for a 'a' or 'A' conversion.
Bruno Haible <bruno@clisp.org>
parents: 8051
diff changeset
2572 else
bbea39ab5a58 Fix estimate of size needed for a 'a' or 'A' conversion.
Bruno Haible <bruno@clisp.org>
parents: 8051
diff changeset
2573 tmp_length =
bbea39ab5a58 Fix estimate of size needed for a 'a' or 'A' conversion.
Bruno Haible <bruno@clisp.org>
parents: 8051
diff changeset
2574 (unsigned int) (DBL_DIG
bbea39ab5a58 Fix estimate of size needed for a 'a' or 'A' conversion.
Bruno Haible <bruno@clisp.org>
parents: 8051
diff changeset
2575 * 0.831 /* decimal -> hexadecimal */
bbea39ab5a58 Fix estimate of size needed for a 'a' or 'A' conversion.
Bruno Haible <bruno@clisp.org>
parents: 8051
diff changeset
2576 )
bbea39ab5a58 Fix estimate of size needed for a 'a' or 'A' conversion.
Bruno Haible <bruno@clisp.org>
parents: 8051
diff changeset
2577 + 1; /* turn floor into ceil */
bbea39ab5a58 Fix estimate of size needed for a 'a' or 'A' conversion.
Bruno Haible <bruno@clisp.org>
parents: 8051
diff changeset
2578 if (tmp_length < precision)
bbea39ab5a58 Fix estimate of size needed for a 'a' or 'A' conversion.
Bruno Haible <bruno@clisp.org>
parents: 8051
diff changeset
2579 tmp_length = precision;
bbea39ab5a58 Fix estimate of size needed for a 'a' or 'A' conversion.
Bruno Haible <bruno@clisp.org>
parents: 8051
diff changeset
2580 /* Account for sign, decimal point etc. */
bbea39ab5a58 Fix estimate of size needed for a 'a' or 'A' conversion.
Bruno Haible <bruno@clisp.org>
parents: 8051
diff changeset
2581 tmp_length = xsum (tmp_length, 12);
bbea39ab5a58 Fix estimate of size needed for a 'a' or 'A' conversion.
Bruno Haible <bruno@clisp.org>
parents: 8051
diff changeset
2582 break;
bbea39ab5a58 Fix estimate of size needed for a 'a' or 'A' conversion.
Bruno Haible <bruno@clisp.org>
parents: 8051
diff changeset
2583
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2584 case 'c':
8051
9c2b0396b27c Stylistic change: Use '#if HAVE_*' instead of '#ifdef HAVE_*'.
Bruno Haible <bruno@clisp.org>
parents: 7475
diff changeset
2585 # if HAVE_WINT_T && !WIDE_CHAR_VERSION
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2586 if (type == TYPE_WIDE_CHAR)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2587 tmp_length = MB_CUR_MAX;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2588 else
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2589 # endif
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2590 tmp_length = 1;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2591 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2592
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2593 case 's':
8051
9c2b0396b27c Stylistic change: Use '#if HAVE_*' instead of '#ifdef HAVE_*'.
Bruno Haible <bruno@clisp.org>
parents: 7475
diff changeset
2594 # if HAVE_WCHAR_T
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2595 if (type == TYPE_WIDE_STRING)
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2596 {
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2597 tmp_length =
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2598 local_wcslen (a.arg[dp->arg_index].a.a_wide_string);
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2599
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2600 # if !WIDE_CHAR_VERSION
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2601 tmp_length = xtimes (tmp_length, MB_CUR_MAX);
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
2602 # endif
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2603 }
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2604 else
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2605 # endif
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2606 tmp_length = strlen (a.arg[dp->arg_index].a.a_string);
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2607 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2608
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2609 case 'p':
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2610 tmp_length =
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2611 (unsigned int) (sizeof (void *) * CHAR_BIT
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2612 * 0.25 /* binary -> hexadecimal */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2613 )
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2614 + 1 /* turn floor into ceil */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2615 + 2; /* account for leading 0x */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2616 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2617
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2618 default:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2619 abort ();
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2620 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2621
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2622 if (tmp_length < width)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2623 tmp_length = width;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2624
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2625 tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2626 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2627
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
2628 if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T))
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2629 tmp = tmpbuf;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2630 else
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2631 {
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2632 size_t tmp_memsize = xtimes (tmp_length, sizeof (CHAR_T));
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2633
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2634 if (size_overflow_p (tmp_memsize))
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2635 /* Overflow, would lead to out of memory. */
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2636 goto out_of_memory;
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2637 tmp = (CHAR_T *) malloc (tmp_memsize);
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2638 if (tmp == NULL)
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2639 /* Out of memory. */
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2640 goto out_of_memory;
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2641 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2642 #endif
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2643
8804
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2644 /* Decide whether to perform the padding ourselves. */
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2645 #if NEED_PRINTF_FLAG_ZERO
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2646 switch (dp->conversion)
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2647 {
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2648 case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2649 case 'a': case 'A':
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2650 pad_ourselves = 1;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2651 break;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2652 default:
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2653 pad_ourselves = 0;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2654 break;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2655 }
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2656 #endif
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2657
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2658 /* Construct the format string for calling snprintf or
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2659 sprintf. */
8804
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2660 fbp = buf;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2661 *fbp++ = '%';
8803
6c1d98929550 Work around lack of support of grouping flag.
Bruno Haible <bruno@clisp.org>
parents: 8664
diff changeset
2662 #if NEED_PRINTF_FLAG_GROUPING
6c1d98929550 Work around lack of support of grouping flag.
Bruno Haible <bruno@clisp.org>
parents: 8664
diff changeset
2663 /* The underlying implementation doesn't support the ' flag.
6c1d98929550 Work around lack of support of grouping flag.
Bruno Haible <bruno@clisp.org>
parents: 8664
diff changeset
2664 Produce no grouping characters in this case; this is
6c1d98929550 Work around lack of support of grouping flag.
Bruno Haible <bruno@clisp.org>
parents: 8664
diff changeset
2665 acceptable because the grouping is locale dependent. */
6c1d98929550 Work around lack of support of grouping flag.
Bruno Haible <bruno@clisp.org>
parents: 8664
diff changeset
2666 #else
8804
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2667 if (flags & FLAG_GROUP)
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2668 *fbp++ = '\'';
8803
6c1d98929550 Work around lack of support of grouping flag.
Bruno Haible <bruno@clisp.org>
parents: 8664
diff changeset
2669 #endif
8804
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2670 if (flags & FLAG_LEFT)
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2671 *fbp++ = '-';
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2672 if (flags & FLAG_SHOWSIGN)
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2673 *fbp++ = '+';
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2674 if (flags & FLAG_SPACE)
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2675 *fbp++ = ' ';
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2676 if (flags & FLAG_ALT)
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2677 *fbp++ = '#';
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2678 if (!pad_ourselves)
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2679 {
8804
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2680 if (flags & FLAG_ZERO)
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2681 *fbp++ = '0';
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2682 if (dp->width_start != dp->width_end)
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2683 {
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2684 size_t n = dp->width_end - dp->width_start;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2685 memcpy (fbp, dp->width_start, n * sizeof (CHAR_T));
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2686 fbp += n;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2687 }
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2688 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2689 if (dp->precision_start != dp->precision_end)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2690 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2691 size_t n = dp->precision_end - dp->precision_start;
8804
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2692 memcpy (fbp, dp->precision_start, n * sizeof (CHAR_T));
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2693 fbp += n;
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2694 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2695
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2696 switch (type)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2697 {
8051
9c2b0396b27c Stylistic change: Use '#if HAVE_*' instead of '#ifdef HAVE_*'.
Bruno Haible <bruno@clisp.org>
parents: 7475
diff changeset
2698 #if HAVE_LONG_LONG_INT
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2699 case TYPE_LONGLONGINT:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2700 case TYPE_ULONGLONGINT:
8830
abc2bcb16721 Support output of 64-bit numbers on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8804
diff changeset
2701 # if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
abc2bcb16721 Support output of 64-bit numbers on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8804
diff changeset
2702 *fbp++ = 'I';
abc2bcb16721 Support output of 64-bit numbers on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8804
diff changeset
2703 *fbp++ = '6';
abc2bcb16721 Support output of 64-bit numbers on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8804
diff changeset
2704 *fbp++ = '4';
abc2bcb16721 Support output of 64-bit numbers on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8804
diff changeset
2705 break;
abc2bcb16721 Support output of 64-bit numbers on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8804
diff changeset
2706 # else
8804
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2707 *fbp++ = 'l';
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2708 /*FALLTHROUGH*/
8830
abc2bcb16721 Support output of 64-bit numbers on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8804
diff changeset
2709 # endif
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2710 #endif
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2711 case TYPE_LONGINT:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2712 case TYPE_ULONGINT:
8051
9c2b0396b27c Stylistic change: Use '#if HAVE_*' instead of '#ifdef HAVE_*'.
Bruno Haible <bruno@clisp.org>
parents: 7475
diff changeset
2713 #if HAVE_WINT_T
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2714 case TYPE_WIDE_CHAR:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2715 #endif
8051
9c2b0396b27c Stylistic change: Use '#if HAVE_*' instead of '#ifdef HAVE_*'.
Bruno Haible <bruno@clisp.org>
parents: 7475
diff changeset
2716 #if HAVE_WCHAR_T
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2717 case TYPE_WIDE_STRING:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2718 #endif
8804
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2719 *fbp++ = 'l';
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2720 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2721 case TYPE_LONGDOUBLE:
8804
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2722 *fbp++ = 'L';
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2723 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2724 default:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2725 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2726 }
8664
40c507f55b0f Implement the %F directive if the system doesn't implement it correctly.
Bruno Haible <bruno@clisp.org>
parents: 8655
diff changeset
2727 #if NEED_PRINTF_DIRECTIVE_F
40c507f55b0f Implement the %F directive if the system doesn't implement it correctly.
Bruno Haible <bruno@clisp.org>
parents: 8655
diff changeset
2728 if (dp->conversion == 'F')
8804
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2729 *fbp = 'f';
8664
40c507f55b0f Implement the %F directive if the system doesn't implement it correctly.
Bruno Haible <bruno@clisp.org>
parents: 8655
diff changeset
2730 else
40c507f55b0f Implement the %F directive if the system doesn't implement it correctly.
Bruno Haible <bruno@clisp.org>
parents: 8655
diff changeset
2731 #endif
8804
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2732 *fbp = dp->conversion;
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
2733 #if USE_SNPRINTF
8804
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2734 fbp[1] = '%';
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2735 fbp[2] = 'n';
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2736 fbp[3] = '\0';
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2737 #else
8804
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2738 fbp[1] = '\0';
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2739 #endif
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2740
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2741 /* Construct the arguments for calling snprintf or sprintf. */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2742 prefix_count = 0;
8804
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2743 if (!pad_ourselves && dp->width_arg_index != ARG_NONE)
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2744 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2745 if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2746 abort ();
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2747 prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2748 }
4886
e4317f1f2e2c Use size_t instead of ssize_t.
Bruno Haible <bruno@clisp.org>
parents: 4879
diff changeset
2749 if (dp->precision_arg_index != ARG_NONE)
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2750 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2751 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2752 abort ();
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2753 prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2754 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2755
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
2756 #if USE_SNPRINTF
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2757 /* Prepare checking whether snprintf returns the count
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2758 via %n. */
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2759 ENSURE_ALLOCATION (xsum (length, 1));
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2760 result[length] = '\0';
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2761 #endif
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2762
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2763 for (;;)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2764 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2765 size_t maxlen;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2766 int count;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2767 int retcount;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2768
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2769 maxlen = allocated - length;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2770 count = -1;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2771 retcount = 0;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2772
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
2773 #if USE_SNPRINTF
8468
336e69863755 Fix endless loop when the given allocated size was > INT_MAX.
Bruno Haible <bruno@clisp.org>
parents: 8465
diff changeset
2774 /* SNPRINTF can fail if maxlen > INT_MAX. */
336e69863755 Fix endless loop when the given allocated size was > INT_MAX.
Bruno Haible <bruno@clisp.org>
parents: 8465
diff changeset
2775 if (maxlen > INT_MAX)
336e69863755 Fix endless loop when the given allocated size was > INT_MAX.
Bruno Haible <bruno@clisp.org>
parents: 8465
diff changeset
2776 goto overflow;
4704
b7a1b14802c8 Correct cpp indentation.
Jim Meyering <jim@meyering.net>
parents: 4589
diff changeset
2777 # define SNPRINTF_BUF(arg) \
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2778 switch (prefix_count) \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2779 { \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2780 case 0: \
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
2781 retcount = SNPRINTF (result + length, maxlen, buf, \
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2782 arg, &count); \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2783 break; \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2784 case 1: \
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
2785 retcount = SNPRINTF (result + length, maxlen, buf, \
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2786 prefixes[0], arg, &count); \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2787 break; \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2788 case 2: \
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
2789 retcount = SNPRINTF (result + length, maxlen, buf, \
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2790 prefixes[0], prefixes[1], arg, \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2791 &count); \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2792 break; \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2793 default: \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2794 abort (); \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2795 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2796 #else
4704
b7a1b14802c8 Correct cpp indentation.
Jim Meyering <jim@meyering.net>
parents: 4589
diff changeset
2797 # define SNPRINTF_BUF(arg) \
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2798 switch (prefix_count) \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2799 { \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2800 case 0: \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2801 count = sprintf (tmp, buf, arg); \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2802 break; \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2803 case 1: \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2804 count = sprintf (tmp, buf, prefixes[0], arg); \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2805 break; \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2806 case 2: \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2807 count = sprintf (tmp, buf, prefixes[0], prefixes[1],\
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2808 arg); \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2809 break; \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2810 default: \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2811 abort (); \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2812 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2813 #endif
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2814
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2815 switch (type)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2816 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2817 case TYPE_SCHAR:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2818 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2819 int arg = a.arg[dp->arg_index].a.a_schar;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2820 SNPRINTF_BUF (arg);
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2821 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2822 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2823 case TYPE_UCHAR:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2824 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2825 unsigned int arg = a.arg[dp->arg_index].a.a_uchar;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2826 SNPRINTF_BUF (arg);
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2827 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2828 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2829 case TYPE_SHORT:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2830 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2831 int arg = a.arg[dp->arg_index].a.a_short;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2832 SNPRINTF_BUF (arg);
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2833 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2834 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2835 case TYPE_USHORT:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2836 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2837 unsigned int arg = a.arg[dp->arg_index].a.a_ushort;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2838 SNPRINTF_BUF (arg);
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2839 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2840 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2841 case TYPE_INT:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2842 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2843 int arg = a.arg[dp->arg_index].a.a_int;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2844 SNPRINTF_BUF (arg);
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2845 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2846 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2847 case TYPE_UINT:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2848 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2849 unsigned int arg = a.arg[dp->arg_index].a.a_uint;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2850 SNPRINTF_BUF (arg);
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2851 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2852 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2853 case TYPE_LONGINT:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2854 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2855 long int arg = a.arg[dp->arg_index].a.a_longint;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2856 SNPRINTF_BUF (arg);
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2857 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2858 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2859 case TYPE_ULONGINT:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2860 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2861 unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2862 SNPRINTF_BUF (arg);
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2863 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2864 break;
8051
9c2b0396b27c Stylistic change: Use '#if HAVE_*' instead of '#ifdef HAVE_*'.
Bruno Haible <bruno@clisp.org>
parents: 7475
diff changeset
2865 #if HAVE_LONG_LONG_INT
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2866 case TYPE_LONGLONGINT:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2867 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2868 long long int arg = a.arg[dp->arg_index].a.a_longlongint;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2869 SNPRINTF_BUF (arg);
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2870 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2871 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2872 case TYPE_ULONGLONGINT:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2873 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2874 unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2875 SNPRINTF_BUF (arg);
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2876 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2877 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2878 #endif
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2879 case TYPE_DOUBLE:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2880 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2881 double arg = a.arg[dp->arg_index].a.a_double;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2882 SNPRINTF_BUF (arg);
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2883 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2884 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2885 case TYPE_LONGDOUBLE:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2886 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2887 long double arg = a.arg[dp->arg_index].a.a_longdouble;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2888 SNPRINTF_BUF (arg);
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2889 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2890 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2891 case TYPE_CHAR:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2892 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2893 int arg = a.arg[dp->arg_index].a.a_char;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2894 SNPRINTF_BUF (arg);
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2895 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2896 break;
8051
9c2b0396b27c Stylistic change: Use '#if HAVE_*' instead of '#ifdef HAVE_*'.
Bruno Haible <bruno@clisp.org>
parents: 7475
diff changeset
2897 #if HAVE_WINT_T
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2898 case TYPE_WIDE_CHAR:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2899 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2900 wint_t arg = a.arg[dp->arg_index].a.a_wide_char;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2901 SNPRINTF_BUF (arg);
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2902 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2903 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2904 #endif
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2905 case TYPE_STRING:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2906 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2907 const char *arg = a.arg[dp->arg_index].a.a_string;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2908 SNPRINTF_BUF (arg);
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2909 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2910 break;
8051
9c2b0396b27c Stylistic change: Use '#if HAVE_*' instead of '#ifdef HAVE_*'.
Bruno Haible <bruno@clisp.org>
parents: 7475
diff changeset
2911 #if HAVE_WCHAR_T
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2912 case TYPE_WIDE_STRING:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2913 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2914 const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2915 SNPRINTF_BUF (arg);
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2916 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2917 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2918 #endif
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2919 case TYPE_POINTER:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2920 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2921 void *arg = a.arg[dp->arg_index].a.a_pointer;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2922 SNPRINTF_BUF (arg);
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2923 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2924 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2925 default:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2926 abort ();
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2927 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2928
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
2929 #if USE_SNPRINTF
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2930 /* Portability: Not all implementations of snprintf()
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2931 are ISO C 99 compliant. Determine the number of
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2932 bytes that snprintf() has produced or would have
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2933 produced. */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2934 if (count >= 0)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2935 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2936 /* Verify that snprintf() has NUL-terminated its
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2937 result. */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2938 if (count < maxlen && result[length + count] != '\0')
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2939 abort ();
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2940 /* Portability hack. */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2941 if (retcount > count)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2942 count = retcount;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2943 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2944 else
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2945 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2946 /* snprintf() doesn't understand the '%n'
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2947 directive. */
8804
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2948 if (fbp[1] != '\0')
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2949 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2950 /* Don't use the '%n' directive; instead, look
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2951 at the snprintf() return value. */
8804
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2952 fbp[1] = '\0';
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2953 continue;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2954 }
4801
83746ec4d74a Portability to HP-UX 10, found by Jim Meyering.
Bruno Haible <bruno@clisp.org>
parents: 4704
diff changeset
2955 else
83746ec4d74a Portability to HP-UX 10, found by Jim Meyering.
Bruno Haible <bruno@clisp.org>
parents: 4704
diff changeset
2956 {
83746ec4d74a Portability to HP-UX 10, found by Jim Meyering.
Bruno Haible <bruno@clisp.org>
parents: 4704
diff changeset
2957 /* Look at the snprintf() return value. */
83746ec4d74a Portability to HP-UX 10, found by Jim Meyering.
Bruno Haible <bruno@clisp.org>
parents: 4704
diff changeset
2958 if (retcount < 0)
83746ec4d74a Portability to HP-UX 10, found by Jim Meyering.
Bruno Haible <bruno@clisp.org>
parents: 4704
diff changeset
2959 {
83746ec4d74a Portability to HP-UX 10, found by Jim Meyering.
Bruno Haible <bruno@clisp.org>
parents: 4704
diff changeset
2960 /* HP-UX 10.20 snprintf() is doubly deficient:
83746ec4d74a Portability to HP-UX 10, found by Jim Meyering.
Bruno Haible <bruno@clisp.org>
parents: 4704
diff changeset
2961 It doesn't understand the '%n' directive,
83746ec4d74a Portability to HP-UX 10, found by Jim Meyering.
Bruno Haible <bruno@clisp.org>
parents: 4704
diff changeset
2962 *and* it returns -1 (rather than the length
83746ec4d74a Portability to HP-UX 10, found by Jim Meyering.
Bruno Haible <bruno@clisp.org>
parents: 4704
diff changeset
2963 that would have been required) when the
83746ec4d74a Portability to HP-UX 10, found by Jim Meyering.
Bruno Haible <bruno@clisp.org>
parents: 4704
diff changeset
2964 buffer is too small. */
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2965 size_t bigger_need =
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2966 xsum (xtimes (allocated, 2), 12);
4801
83746ec4d74a Portability to HP-UX 10, found by Jim Meyering.
Bruno Haible <bruno@clisp.org>
parents: 4704
diff changeset
2967 ENSURE_ALLOCATION (bigger_need);
83746ec4d74a Portability to HP-UX 10, found by Jim Meyering.
Bruno Haible <bruno@clisp.org>
parents: 4704
diff changeset
2968 continue;
83746ec4d74a Portability to HP-UX 10, found by Jim Meyering.
Bruno Haible <bruno@clisp.org>
parents: 4704
diff changeset
2969 }
83746ec4d74a Portability to HP-UX 10, found by Jim Meyering.
Bruno Haible <bruno@clisp.org>
parents: 4704
diff changeset
2970 else
83746ec4d74a Portability to HP-UX 10, found by Jim Meyering.
Bruno Haible <bruno@clisp.org>
parents: 4704
diff changeset
2971 count = retcount;
83746ec4d74a Portability to HP-UX 10, found by Jim Meyering.
Bruno Haible <bruno@clisp.org>
parents: 4704
diff changeset
2972 }
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2973 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2974 #endif
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2975
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2976 /* Attempt to handle failure. */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2977 if (count < 0)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2978 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2979 if (!(result == resultbuf || result == NULL))
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2980 free (result);
4879
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
2981 if (buf_malloced != NULL)
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
2982 free (buf_malloced);
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2983 CLEANUP ();
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2984 errno = EINVAL;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2985 return NULL;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2986 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2987
8837
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
2988 /* Make room for the result. */
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
2989 if (count >= maxlen)
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
2990 {
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
2991 /* Need at least count bytes. But allocate
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
2992 proportionally, to avoid looping eternally if
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
2993 snprintf() reports a too small count. */
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
2994 size_t n =
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
2995 xmax (xsum (length, count), xtimes (allocated, 2));
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
2996
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
2997 ENSURE_ALLOCATION (n);
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
2998 #if USE_SNPRINTF
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
2999 continue;
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
3000 #else
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
3001 maxlen = allocated - length;
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
3002 #endif
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
3003 }
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
3004
8804
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3005 /* Perform padding. */
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3006 #if NEED_PRINTF_FLAG_ZERO
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3007 if (pad_ourselves && has_width && count < width)
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3008 {
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3009 # if USE_SNPRINTF
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3010 /* Make room for the result. */
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3011 if (width >= maxlen)
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3012 {
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3013 /* Need at least width bytes. But allocate
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3014 proportionally, to avoid looping eternally if
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3015 snprintf() reports a too small count. */
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3016 size_t n =
8837
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
3017 xmax (xsum (length + 1, width),
8804
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3018 xtimes (allocated, 2));
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3019
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3020 length += count;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3021 ENSURE_ALLOCATION (n);
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3022 length -= count;
8837
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
3023 maxlen = allocated - length; /* > width */
8804
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3024 }
8837
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
3025 /* Here width < maxlen. */
8804
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3026 # endif
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3027 {
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3028 # if USE_SNPRINTF
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3029 CHAR_T * const rp = result + length;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3030 # else
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3031 CHAR_T * const rp = tmp;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3032 # endif
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3033 CHAR_T *p = rp + count;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3034 size_t pad = width - count;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3035 CHAR_T *end = p + pad;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3036 CHAR_T *pad_ptr = (*rp == '-' ? rp + 1 : rp);
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3037 /* No zero-padding of "inf" and "nan". */
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3038 if ((*pad_ptr >= 'A' && *pad_ptr <= 'Z')
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3039 || (*pad_ptr >= 'a' && *pad_ptr <= 'z'))
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3040 pad_ptr = NULL;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3041 /* The generated string now extends from rp to p,
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3042 with the zero padding insertion point being at
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3043 pad_ptr. */
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3044
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3045 if (flags & FLAG_LEFT)
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3046 {
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3047 /* Pad with spaces on the right. */
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3048 for (; pad > 0; pad--)
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3049 *p++ = ' ';
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3050 }
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3051 else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3052 {
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3053 /* Pad with zeroes. */
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3054 CHAR_T *q = end;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3055
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3056 while (p > pad_ptr)
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3057 *--q = *--p;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3058 for (; pad > 0; pad--)
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3059 *p++ = '0';
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3060 }
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3061 else
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3062 {
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3063 /* Pad with spaces on the left. */
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3064 CHAR_T *q = end;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3065
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3066 while (p > rp)
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3067 *--q = *--p;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3068 for (; pad > 0; pad--)
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3069 *p++ = ' ';
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3070 }
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3071
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3072 count = width; /* = count + pad = end - rp */
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3073 }
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3074 }
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3075 #endif
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3076
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
3077 #if !USE_SNPRINTF
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3078 if (count >= tmp_length)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3079 /* tmp_length was incorrectly calculated - fix the
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3080 code above! */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3081 abort ();
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3082 #endif
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3083
8837
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
3084 /* Here still count < maxlen. */
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3085
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
3086 #if USE_SNPRINTF
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3087 /* The snprintf() result did fit. */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3088 #else
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3089 /* Append the sprintf() result. */
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
3090 memcpy (result + length, tmp, count * sizeof (CHAR_T));
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3091 if (tmp != tmpbuf)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3092 free (tmp);
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3093 #endif
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3094
8664
40c507f55b0f Implement the %F directive if the system doesn't implement it correctly.
Bruno Haible <bruno@clisp.org>
parents: 8655
diff changeset
3095 #if NEED_PRINTF_DIRECTIVE_F
40c507f55b0f Implement the %F directive if the system doesn't implement it correctly.
Bruno Haible <bruno@clisp.org>
parents: 8655
diff changeset
3096 if (dp->conversion == 'F')
40c507f55b0f Implement the %F directive if the system doesn't implement it correctly.
Bruno Haible <bruno@clisp.org>
parents: 8655
diff changeset
3097 {
40c507f55b0f Implement the %F directive if the system doesn't implement it correctly.
Bruno Haible <bruno@clisp.org>
parents: 8655
diff changeset
3098 /* Convert the %f result to upper case for %F. */
40c507f55b0f Implement the %F directive if the system doesn't implement it correctly.
Bruno Haible <bruno@clisp.org>
parents: 8655
diff changeset
3099 CHAR_T *rp = result + length;
40c507f55b0f Implement the %F directive if the system doesn't implement it correctly.
Bruno Haible <bruno@clisp.org>
parents: 8655
diff changeset
3100 size_t rc;
40c507f55b0f Implement the %F directive if the system doesn't implement it correctly.
Bruno Haible <bruno@clisp.org>
parents: 8655
diff changeset
3101 for (rc = count; rc > 0; rc--, rp++)
40c507f55b0f Implement the %F directive if the system doesn't implement it correctly.
Bruno Haible <bruno@clisp.org>
parents: 8655
diff changeset
3102 if (*rp >= 'a' && *rp <= 'z')
40c507f55b0f Implement the %F directive if the system doesn't implement it correctly.
Bruno Haible <bruno@clisp.org>
parents: 8655
diff changeset
3103 *rp = *rp - 'a' + 'A';
40c507f55b0f Implement the %F directive if the system doesn't implement it correctly.
Bruno Haible <bruno@clisp.org>
parents: 8655
diff changeset
3104 }
40c507f55b0f Implement the %F directive if the system doesn't implement it correctly.
Bruno Haible <bruno@clisp.org>
parents: 8655
diff changeset
3105 #endif
40c507f55b0f Implement the %F directive if the system doesn't implement it correctly.
Bruno Haible <bruno@clisp.org>
parents: 8655
diff changeset
3106
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3107 length += count;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3108 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3109 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3110 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3111 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3112 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3113
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3114 /* Add the final NUL. */
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
3115 ENSURE_ALLOCATION (xsum (length, 1));
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3116 result[length] = '\0';
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3117
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3118 if (result != resultbuf && length + 1 < allocated)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3119 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3120 /* Shrink the allocated memory if possible. */
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
3121 CHAR_T *memory;
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3122
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
3123 memory = (CHAR_T *) realloc (result, (length + 1) * sizeof (CHAR_T));
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3124 if (memory != NULL)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3125 result = memory;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3126 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3127
4879
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
3128 if (buf_malloced != NULL)
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
3129 free (buf_malloced);
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3130 CLEANUP ();
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3131 *lengthp = length;
7218
0fd12ba5cfc6 Do the INT_MAX check only where size_t is converted to 'int'.
Bruno Haible <bruno@clisp.org>
parents: 6583
diff changeset
3132 /* Note that we can produce a big string of a length > INT_MAX. POSIX
0fd12ba5cfc6 Do the INT_MAX check only where size_t is converted to 'int'.
Bruno Haible <bruno@clisp.org>
parents: 6583
diff changeset
3133 says that snprintf() fails with errno = EOVERFLOW in this case, but
0fd12ba5cfc6 Do the INT_MAX check only where size_t is converted to 'int'.
Bruno Haible <bruno@clisp.org>
parents: 6583
diff changeset
3134 that's only because snprintf() returns an 'int'. This function does
0fd12ba5cfc6 Do the INT_MAX check only where size_t is converted to 'int'.
Bruno Haible <bruno@clisp.org>
parents: 6583
diff changeset
3135 not have this limitation. */
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3136 return result;
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
3137
8468
336e69863755 Fix endless loop when the given allocated size was > INT_MAX.
Bruno Haible <bruno@clisp.org>
parents: 8465
diff changeset
3138 overflow:
336e69863755 Fix endless loop when the given allocated size was > INT_MAX.
Bruno Haible <bruno@clisp.org>
parents: 8465
diff changeset
3139 if (!(result == resultbuf || result == NULL))
336e69863755 Fix endless loop when the given allocated size was > INT_MAX.
Bruno Haible <bruno@clisp.org>
parents: 8465
diff changeset
3140 free (result);
336e69863755 Fix endless loop when the given allocated size was > INT_MAX.
Bruno Haible <bruno@clisp.org>
parents: 8465
diff changeset
3141 if (buf_malloced != NULL)
336e69863755 Fix endless loop when the given allocated size was > INT_MAX.
Bruno Haible <bruno@clisp.org>
parents: 8465
diff changeset
3142 free (buf_malloced);
336e69863755 Fix endless loop when the given allocated size was > INT_MAX.
Bruno Haible <bruno@clisp.org>
parents: 8465
diff changeset
3143 CLEANUP ();
336e69863755 Fix endless loop when the given allocated size was > INT_MAX.
Bruno Haible <bruno@clisp.org>
parents: 8465
diff changeset
3144 errno = EOVERFLOW;
336e69863755 Fix endless loop when the given allocated size was > INT_MAX.
Bruno Haible <bruno@clisp.org>
parents: 8465
diff changeset
3145 return NULL;
336e69863755 Fix endless loop when the given allocated size was > INT_MAX.
Bruno Haible <bruno@clisp.org>
parents: 8465
diff changeset
3146
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
3147 out_of_memory:
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
3148 if (!(result == resultbuf || result == NULL))
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
3149 free (result);
4879
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
3150 if (buf_malloced != NULL)
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
3151 free (buf_malloced);
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
3152 out_of_memory_1:
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
3153 CLEANUP ();
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
3154 errno = ENOMEM;
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
3155 return NULL;
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3156 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3157 }
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
3158
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
3159 #undef SNPRINTF
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
3160 #undef USE_SNPRINTF
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
3161 #undef PRINTF_PARSE
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
3162 #undef DIRECTIVES
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
3163 #undef DIRECTIVE
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
3164 #undef CHAR_T
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
3165 #undef VASNPRINTF