annotate lib/vasnprintf.c @ 8915:f15c03805bd9

Fix possible compilation error.
author Bruno Haible <bruno@clisp.org>
date Wed, 06 Jun 2007 01:36:14 +0000
parents 9e203d8ade65
children 353e81af4858
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
8860
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
56 #if NEED_PRINTF_LONG_DOUBLE && !defined IN_LIBINTL
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
57 # include <math.h>
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
58 # include "float+.h"
8915
f15c03805bd9 Fix possible compilation error.
Bruno Haible <bruno@clisp.org>
parents: 8865
diff changeset
59 # include "fpucw.h"
8860
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
60 #endif
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
61
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
62 #if NEED_PRINTF_INFINITE_DOUBLE && !defined IN_LIBINTL
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
63 # include <math.h>
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
64 # include "isnan.h"
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
65 #endif
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
66
8860
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
67 #if NEED_PRINTF_INFINITE_LONG_DOUBLE && !defined IN_LIBINTL
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
68 # include <math.h>
8860
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
69 # include "isnanl-nolibm.h"
8915
f15c03805bd9 Fix possible compilation error.
Bruno Haible <bruno@clisp.org>
parents: 8865
diff changeset
70 # include "fpucw.h"
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
71 #endif
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
72
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
73 #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
74 # include <math.h>
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
75 # include "isnan.h"
8526
67e9a647f2fa Fix includes.
Bruno Haible <bruno@clisp.org>
parents: 8487
diff changeset
76 # include "printf-frexp.h"
8648
359d135f748c Assume 'long double' exists.
Bruno Haible <bruno@clisp.org>
parents: 8569
diff changeset
77 # include "isnanl-nolibm.h"
359d135f748c Assume 'long double' exists.
Bruno Haible <bruno@clisp.org>
parents: 8569
diff changeset
78 # include "printf-frexpl.h"
359d135f748c Assume 'long double' exists.
Bruno Haible <bruno@clisp.org>
parents: 8569
diff changeset
79 # include "fpucw.h"
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
80 #endif
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
81
8468
336e69863755 Fix endless loop when the given allocated size was > INT_MAX.
Bruno Haible <bruno@clisp.org>
parents: 8465
diff changeset
82 /* 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
83 #ifndef EOVERFLOW
336e69863755 Fix endless loop when the given allocated size was > INT_MAX.
Bruno Haible <bruno@clisp.org>
parents: 8465
diff changeset
84 # define EOVERFLOW E2BIG
336e69863755 Fix endless loop when the given allocated size was > INT_MAX.
Bruno Haible <bruno@clisp.org>
parents: 8465
diff changeset
85 #endif
336e69863755 Fix endless loop when the given allocated size was > INT_MAX.
Bruno Haible <bruno@clisp.org>
parents: 8465
diff changeset
86
8051
9c2b0396b27c Stylistic change: Use '#if HAVE_*' instead of '#ifdef HAVE_*'.
Bruno Haible <bruno@clisp.org>
parents: 7475
diff changeset
87 #if HAVE_WCHAR_T
9c2b0396b27c Stylistic change: Use '#if HAVE_*' instead of '#ifdef HAVE_*'.
Bruno Haible <bruno@clisp.org>
parents: 7475
diff changeset
88 # 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
89 # 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
90 # else
6cc4874a100b Work around the lack of wcslen() on Solaris 2.5.1.
Bruno Haible <bruno@clisp.org>
parents: 4444
diff changeset
91 /* 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
92 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
93 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
94 twice in the same compilation unit. */
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
95 # ifndef local_wcslen_defined
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
96 # 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
97 static size_t
6cc4874a100b Work around the lack of wcslen() on Solaris 2.5.1.
Bruno Haible <bruno@clisp.org>
parents: 4444
diff changeset
98 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
99 {
6cc4874a100b Work around the lack of wcslen() on Solaris 2.5.1.
Bruno Haible <bruno@clisp.org>
parents: 4444
diff changeset
100 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
101
6cc4874a100b Work around the lack of wcslen() on Solaris 2.5.1.
Bruno Haible <bruno@clisp.org>
parents: 4444
diff changeset
102 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
103 ;
6cc4874a100b Work around the lack of wcslen() on Solaris 2.5.1.
Bruno Haible <bruno@clisp.org>
parents: 4444
diff changeset
104 return ptr - s;
6cc4874a100b Work around the lack of wcslen() on Solaris 2.5.1.
Bruno Haible <bruno@clisp.org>
parents: 4444
diff changeset
105 }
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
106 # endif
4523
6cc4874a100b Work around the lack of wcslen() on Solaris 2.5.1.
Bruno Haible <bruno@clisp.org>
parents: 4444
diff changeset
107 # endif
6cc4874a100b Work around the lack of wcslen() on Solaris 2.5.1.
Bruno Haible <bruno@clisp.org>
parents: 4444
diff changeset
108 #endif
6cc4874a100b Work around the lack of wcslen() on Solaris 2.5.1.
Bruno Haible <bruno@clisp.org>
parents: 4444
diff changeset
109
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
110 #if WIDE_CHAR_VERSION
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
111 # define VASNPRINTF vasnwprintf
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
112 # define CHAR_T wchar_t
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
113 # define DIRECTIVE wchar_t_directive
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
114 # define DIRECTIVES wchar_t_directives
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
115 # define PRINTF_PARSE wprintf_parse
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
116 # define USE_SNPRINTF 1
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
117 # if HAVE_DECL__SNWPRINTF
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
118 /* 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
119 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
120 # define SNPRINTF _snwprintf
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
121 # else
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
122 /* Unix. */
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
123 # define SNPRINTF swprintf
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
124 # endif
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
125 #else
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
126 # define VASNPRINTF vasnprintf
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
127 # define CHAR_T char
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
128 # define DIRECTIVE char_directive
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
129 # define DIRECTIVES char_directives
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
130 # define PRINTF_PARSE printf_parse
8831
d3f907c33d15 Work around broken snprintf function on BeOS.
Bruno Haible <bruno@clisp.org>
parents: 8830
diff changeset
131 # /* 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
132 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
133 size argument is >= 0x3000000. */
d3f907c33d15 Work around broken snprintf function on BeOS.
Bruno Haible <bruno@clisp.org>
parents: 8830
diff changeset
134 # 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
135 # define USE_SNPRINTF 1
d3f907c33d15 Work around broken snprintf function on BeOS.
Bruno Haible <bruno@clisp.org>
parents: 8830
diff changeset
136 # else
d3f907c33d15 Work around broken snprintf function on BeOS.
Bruno Haible <bruno@clisp.org>
parents: 8830
diff changeset
137 # define USE_SNPRINTF 0
d3f907c33d15 Work around broken snprintf function on BeOS.
Bruno Haible <bruno@clisp.org>
parents: 8830
diff changeset
138 # endif
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
139 # if HAVE_DECL__SNPRINTF
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
140 /* Windows. */
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
141 # define SNPRINTF _snprintf
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
142 # else
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
143 /* Unix. */
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
144 # define SNPRINTF snprintf
8417
ee40afd85f2c Avoid an endless recursion.
Bruno Haible <bruno@clisp.org>
parents: 8400
diff changeset
145 /* 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
146 # undef snprintf
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
147 # endif
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
148 #endif
8424
ec3450ce9889 Use the system's sprintf function.
Bruno Haible <bruno@clisp.org>
parents: 8417
diff changeset
149 /* 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
150 #undef sprintf
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
151
8569
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
152 #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
153 /* 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
154 # 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
155 # 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
156 static char
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
157 decimal_point_char ()
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
158 {
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
159 const char *point;
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
160 /* 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
161 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
162 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
163 is rarely multithread-safe. */
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
164 # 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
165 point = nl_langinfo (RADIXCHAR);
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
166 # elif 1
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
167 char pointbuf[5];
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
168 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
169 point = &pointbuf[1];
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
170 # else
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
171 point = localeconv () -> decimal_point;
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
172 # endif
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
173 /* 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
174 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
175 }
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
176 # endif
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
177 #endif
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
178
8860
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
179 #if NEED_PRINTF_INFINITE_DOUBLE && !defined IN_LIBINTL
8840
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 /* 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
182 static int
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
183 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
184 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
185 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
186 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
187
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
188 #endif
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
189
8860
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
190 #if NEED_PRINTF_INFINITE_LONG_DOUBLE && !defined IN_LIBINTL
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
191
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
192 /* Equivalent to !isfinite(x), but does not require libm. */
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
193 static int
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
194 is_infinitel (long double x)
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
195 {
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
196 return isnanl (x) || (x + x == x && x != 0.0L);
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
197 }
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
198
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
199 #endif
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
200
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
201 #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
202
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
203 /* 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
204 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
205 (and slower) algorithms. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
206
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
207 typedef unsigned int mp_limb_t;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
208 # define GMP_LIMB_BITS 32
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
209 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
210
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
211 typedef unsigned long long mp_twolimb_t;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
212 # define GMP_TWOLIMB_BITS 64
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
213 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
214
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
215 /* Representation of a bignum >= 0. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
216 typedef struct
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
217 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
218 size_t nlimbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
219 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
220 } mpn_t;
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 /* Compute the product of two bignums >= 0.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
223 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
224 allocation failure. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
225 static void *
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
226 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
227 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
228 const mp_limb_t *p1;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
229 const mp_limb_t *p2;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
230 size_t len1;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
231 size_t len2;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
232
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
233 if (src1.nlimbs <= src2.nlimbs)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
234 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
235 len1 = src1.nlimbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
236 p1 = src1.limbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
237 len2 = src2.nlimbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
238 p2 = src2.limbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
239 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
240 else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
241 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
242 len1 = src2.nlimbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
243 p1 = src2.limbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
244 len2 = src1.nlimbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
245 p2 = src1.limbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
246 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
247 /* Now 0 <= len1 <= len2. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
248 if (len1 == 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
249 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
250 /* src1 or src2 is zero. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
251 dest->nlimbs = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
252 dest->limbs = (mp_limb_t *) malloc (1);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
253 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
254 else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
255 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
256 /* Here 1 <= len1 <= len2. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
257 size_t dlen;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
258 mp_limb_t *dp;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
259 size_t k, i, j;
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 dlen = len1 + len2;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
262 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
263 if (dp == NULL)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
264 return NULL;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
265 for (k = len2; k > 0; )
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
266 dp[--k] = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
267 for (i = 0; i < len1; i++)
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 mp_limb_t digit1 = p1[i];
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
270 mp_twolimb_t carry = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
271 for (j = 0; j < len2; j++)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
272 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
273 mp_limb_t digit2 = p2[j];
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
274 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
275 carry += dp[i + j];
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
276 dp[i + j] = (mp_limb_t) carry;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
277 carry = carry >> GMP_LIMB_BITS;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
278 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
279 dp[i + len2] = (mp_limb_t) carry;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
280 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
281 /* Normalise. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
282 while (dlen > 0 && dp[dlen - 1] == 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
283 dlen--;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
284 dest->nlimbs = dlen;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
285 dest->limbs = dp;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
286 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
287 return dest->limbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
288 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
289
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
290 /* 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
291 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
292 the remainder.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
293 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
294 q is incremented.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
295 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
296 allocation failure. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
297 static void *
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
298 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
299 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
300 /* Algorithm:
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
301 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
302 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
303 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
304 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
305 r:=0, j:=m,
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
306 while j>0 do
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
307 {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
308 = 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
309 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
310 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
311 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
312 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
313 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
314 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
315 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
316 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
317 Compute q* :
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
318 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
319 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
320 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
321 and c3 := b[n-2] * q*.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
322 {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
323 occurred. Furthermore 0 <= c3 < beta^2.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
324 If there was overflow and
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
325 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
326 the next test can be skipped.}
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
327 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
328 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
329 If q* > 0:
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
330 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
331 [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
332 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
333 u := u + q* * b[i],
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
334 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
335 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
336 r[n+j]:=r[n+j]-u.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
337 {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
338 < q* + 1 <= beta,
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
339 the carry u does not overflow.}
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
340 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
341 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
342 Set q[j] := q*.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
343 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
344 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
345 rest r.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
346 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
347 Finally, round-to-even:
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
348 Shift r left by 1 bit.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
349 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
350 */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
351 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
352 size_t a_len = a.nlimbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
353 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
354 size_t b_len = b.nlimbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
355 mp_limb_t *roomptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
356 mp_limb_t *tmp_roomptr = NULL;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
357 mp_limb_t *q_ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
358 size_t q_len;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
359 mp_limb_t *r_ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
360 size_t r_len;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
361
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
362 /* Allocate room for a_len+2 digits.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
363 (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
364 final rounding of q.) */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
365 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
366 if (roomptr == NULL)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
367 return NULL;
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 /* Normalise a. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
370 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
371 a_len--;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
372
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
373 /* Normalise b. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
374 for (;;)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
375 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
376 if (b_len == 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
377 /* Division by zero. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
378 abort ();
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
379 if (b_ptr[b_len - 1] == 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
380 b_len--;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
381 else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
382 break;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
383 }
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 /* 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
386
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
387 if (a_len < b_len)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
388 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
389 /* 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
390 r_ptr = roomptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
391 r_len = a_len;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
392 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
393 q_ptr = roomptr + a_len;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
394 q_len = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
395 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
396 else if (b_len == 1)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
397 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
398 /* n=1: single precision division.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
399 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
400 r_ptr = roomptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
401 q_ptr = roomptr + 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 mp_limb_t den = b_ptr[0];
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
404 mp_limb_t remainder = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
405 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
406 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
407 size_t count;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
408 for (count = a_len; count > 0; count--)
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 mp_twolimb_t num =
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
411 ((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
412 *--destptr = num / den;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
413 remainder = num % den;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
414 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
415 /* Normalise and store r. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
416 if (remainder > 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
417 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
418 r_ptr[0] = remainder;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
419 r_len = 1;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
420 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
421 else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
422 r_len = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
423 /* Normalise q. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
424 q_len = a_len;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
425 if (q_ptr[q_len - 1] == 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
426 q_len--;
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 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
429 else
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 /* n>1: multiple precision division.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
432 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
433 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
434 /* Determine s. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
435 size_t s;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
436 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
437 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
438 s = 31;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
439 if (msd >= 0x10000)
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 msd = msd >> 16;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
442 s -= 16;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
443 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
444 if (msd >= 0x100)
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 msd = msd >> 8;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
447 s -= 8;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
448 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
449 if (msd >= 0x10)
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 msd = msd >> 4;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
452 s -= 4;
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 if (msd >= 0x4)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
455 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
456 msd = msd >> 2;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
457 s -= 2;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
458 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
459 if (msd >= 0x2)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
460 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
461 msd = msd >> 1;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
462 s -= 1;
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 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
465 /* 0 <= s < GMP_LIMB_BITS.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
466 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
467 if (s > 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
468 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
469 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
470 if (tmp_roomptr == NULL)
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 free (roomptr);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
473 return NULL;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
474 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
475 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
476 const mp_limb_t *sourceptr = b_ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
477 mp_limb_t *destptr = tmp_roomptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
478 mp_twolimb_t accu = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
479 size_t count;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
480 for (count = b_len; count > 0; count--)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
481 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
482 accu += (mp_twolimb_t) *sourceptr++ << s;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
483 *destptr++ = (mp_limb_t) accu;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
484 accu = accu >> GMP_LIMB_BITS;
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 /* 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
487 if (accu != 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
488 abort ();
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
489 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
490 b_ptr = tmp_roomptr;
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 /* 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
493 Memory layout:
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
494 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
495 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
496 r_ptr = roomptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
497 if (s == 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
498 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
499 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
500 r_ptr[a_len] = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
501 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
502 else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
503 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
504 const mp_limb_t *sourceptr = a_ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
505 mp_limb_t *destptr = r_ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
506 mp_twolimb_t accu = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
507 size_t count;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
508 for (count = a_len; count > 0; count--)
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 accu += (mp_twolimb_t) *sourceptr++ << s;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
511 *destptr++ = (mp_limb_t) accu;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
512 accu = accu >> GMP_LIMB_BITS;
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 *destptr++ = (mp_limb_t) accu;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
515 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
516 q_ptr = roomptr + b_len;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
517 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
518 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
519 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
520 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
521 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
522 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
523 ((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
524 /* Division loop, traversed m-n+1 times.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
525 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
526 for (;;)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
527 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
528 mp_limb_t q_star;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
529 mp_limb_t c1;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
530 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
531 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
532 /* 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
533 mp_twolimb_t num =
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
534 ((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
535 | r_ptr[j + b_len - 1];
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
536 q_star = num / b_msd;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
537 c1 = num % b_msd;
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 else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
540 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
541 /* 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
542 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
543 /* 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
544 <==> 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
545 <==> 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
546 {<= beta !}.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
547 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
548 (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
549 <==> 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
550 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
551 || (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
552 /* 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
553 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
554 carry. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
555 goto subtract;
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 /* q_star = q*,
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
558 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
559 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
560 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
561 ((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
562 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
563 (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
564 /* 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
565 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
566 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
567 this can happen only twice. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
568 if (c3 > c2)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
569 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
570 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
571 if (c3 - c2 > b_msdd)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
572 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
573 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
574 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
575 if (q_star > 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
576 subtract:
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 /* Subtract r := r - b * q* * beta^j. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
579 mp_limb_t cr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
580 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
581 const mp_limb_t *sourceptr = b_ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
582 mp_limb_t *destptr = r_ptr + j;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
583 mp_twolimb_t carry = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
584 size_t count;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
585 for (count = b_len; count > 0; count--)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
586 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
587 /* Here 0 <= carry <= q*. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
588 carry =
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
589 carry
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
590 + (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
591 + (mp_limb_t) ~(*destptr);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
592 /* Here 0 <= carry <= beta*q* + beta-1. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
593 *destptr++ = ~(mp_limb_t) carry;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
594 carry = carry >> GMP_LIMB_BITS; /* <= q* */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
595 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
596 cr = (mp_limb_t) carry;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
597 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
598 /* 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
599 r_ptr[j + b_len]. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
600 if (cr > r_ptr[j + b_len])
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 /* Subtraction gave a carry. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
603 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
604 /* Add b back. */
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 const mp_limb_t *sourceptr = b_ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
607 mp_limb_t *destptr = r_ptr + j;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
608 mp_limb_t carry = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
609 size_t count;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
610 for (count = b_len; count > 0; count--)
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 mp_limb_t source1 = *sourceptr++;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
613 mp_limb_t source2 = *destptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
614 *destptr++ = source1 + source2 + carry;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
615 carry =
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
616 (carry
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
617 ? source1 >= (mp_limb_t) ~source2
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
618 : source1 > (mp_limb_t) ~source2);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
619 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
620 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
621 /* 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
622 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
623 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
624 /* 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
625 q_ptr[j] = q_star;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
626 if (j == 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
627 break;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
628 j--;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
629 }
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 r_len = b_len;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
632 /* Normalise q. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
633 if (q_ptr[q_len - 1] == 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
634 q_len--;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
635 # 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
636 b is shifted left by s bits. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
637 /* Shift r right by s bits. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
638 if (s > 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
639 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
640 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
641 mp_twolimb_t accu = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
642 size_t count;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
643 for (count = r_len; count > 0; count--)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
644 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
645 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
646 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
647 *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
648 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
649 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
650 # endif
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
651 /* Normalise r. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
652 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
653 r_len--;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
654 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
655 /* Compare r << 1 with b. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
656 if (r_len > b_len)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
657 goto increment_q;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
658 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
659 size_t i;
8835
c06bc412ffc3 Fix small bug in 'divide' function.
Bruno Haible <bruno@clisp.org>
parents: 8832
diff changeset
660 for (i = b_len;;)
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
661 {
8835
c06bc412ffc3 Fix small bug in 'divide' function.
Bruno Haible <bruno@clisp.org>
parents: 8832
diff changeset
662 mp_limb_t r_i =
c06bc412ffc3 Fix small bug in 'divide' function.
Bruno Haible <bruno@clisp.org>
parents: 8832
diff changeset
663 (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
664 | (i < r_len ? r_ptr[i] << 1 : 0);
c06bc412ffc3 Fix small bug in 'divide' function.
Bruno Haible <bruno@clisp.org>
parents: 8832
diff changeset
665 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
666 if (r_i > b_i)
c06bc412ffc3 Fix small bug in 'divide' function.
Bruno Haible <bruno@clisp.org>
parents: 8832
diff changeset
667 goto increment_q;
c06bc412ffc3 Fix small bug in 'divide' function.
Bruno Haible <bruno@clisp.org>
parents: 8832
diff changeset
668 if (r_i < b_i)
c06bc412ffc3 Fix small bug in 'divide' function.
Bruno Haible <bruno@clisp.org>
parents: 8832
diff changeset
669 goto keep_q;
c06bc412ffc3 Fix small bug in 'divide' function.
Bruno Haible <bruno@clisp.org>
parents: 8832
diff changeset
670 if (i == 0)
c06bc412ffc3 Fix small bug in 'divide' function.
Bruno Haible <bruno@clisp.org>
parents: 8832
diff changeset
671 break;
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
672 i--;
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 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
675 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
676 /* q is odd. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
677 increment_q:
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
678 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
679 size_t i;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
680 for (i = 0; i < q_len; i++)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
681 if (++(q_ptr[i]) != 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
682 goto keep_q;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
683 q_ptr[q_len++] = 1;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
684 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
685 keep_q:
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
686 if (tmp_roomptr != NULL)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
687 free (tmp_roomptr);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
688 q->limbs = q_ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
689 q->nlimbs = q_len;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
690 return roomptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
691 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
692
8838
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
693 /* 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
694 representation.
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
695 Destroys the contents of a.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
696 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
697 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
698 of memory allocation failure. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
699 static char *
8838
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
700 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
701 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
702 mp_limb_t *a_ptr = a.limbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
703 size_t a_len = a.nlimbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
704 /* 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
705 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
706 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
707 if (c_ptr != NULL)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
708 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
709 char *d_ptr = c_ptr;
8838
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
710 for (; extra_zeroes > 0; extra_zeroes--)
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
711 *d_ptr++ = '0';
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
712 while (a_len > 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
713 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
714 /* Divide a by 10^9, in-place. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
715 mp_limb_t remainder = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
716 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
717 size_t count;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
718 for (count = a_len; count > 0; count--)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
719 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
720 mp_twolimb_t num =
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
721 ((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
722 *ptr = num / 1000000000;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
723 remainder = num % 1000000000;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
724 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
725 /* Store the remainder as 9 decimal digits. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
726 for (count = 9; count > 0; count--)
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 *d_ptr++ = '0' + (remainder % 10);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
729 remainder = remainder / 10;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
730 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
731 /* Normalize a. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
732 if (a_ptr[a_len - 1] == 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
733 a_len--;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
734 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
735 /* Remove leading zeroes. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
736 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
737 d_ptr--;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
738 /* But keep at least one zero. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
739 if (d_ptr == c_ptr)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
740 *d_ptr++ = '0';
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
741 /* Terminate the string. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
742 *d_ptr = '\0';
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
743 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
744 return c_ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
745 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
746
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
747 /* Assuming x is finite and >= 0:
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
748 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
749 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
750 allocation failure. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
751 static void *
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
752 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
753 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
754 mpn_t m;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
755 int exp;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
756 long double y;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
757 size_t i;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
758
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
759 /* Allocate memory for result. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
760 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
761 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
762 if (m.limbs == NULL)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
763 return NULL;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
764 /* Split into exponential part and mantissa. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
765 y = frexpl (x, &exp);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
766 if (!(y >= 0.0L && y < 1.0L))
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
767 abort ();
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
768 /* 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
769 latter is an integer. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
770 /* 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
771 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
772 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
773 '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
774 doesn't matter). */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
775 # 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
776 # 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
777 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
778 mp_limb_t hi, lo;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
779 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
780 hi = (int) y;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
781 y -= hi;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
782 if (!(y >= 0.0L && y < 1.0L))
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
783 abort ();
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
784 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
785 lo = (int) y;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
786 y -= lo;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
787 if (!(y >= 0.0L && y < 1.0L))
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
788 abort ();
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
789 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
790 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
791 # else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
792 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
793 mp_limb_t d;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
794 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
795 d = (int) y;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
796 y -= d;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
797 if (!(y >= 0.0L && y < 1.0L))
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
798 abort ();
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
799 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
800 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
801 # endif
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
802 # endif
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
803 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
804 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
805 mp_limb_t hi, lo;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
806 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
807 hi = (int) y;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
808 y -= hi;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
809 if (!(y >= 0.0L && y < 1.0L))
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
810 abort ();
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
811 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
812 lo = (int) y;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
813 y -= lo;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
814 if (!(y >= 0.0L && y < 1.0L))
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
815 abort ();
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
816 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
817 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
818 if (!(y == 0.0L))
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
819 abort ();
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
820 /* Normalise. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
821 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
822 m.nlimbs--;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
823 *mp = m;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
824 *ep = exp - LDBL_MANT_BIT;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
825 return m.limbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
826 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
827
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
828 /* 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
829 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
830 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
831 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
832 of memory allocation failure. */
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
833 static char *
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
834 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
835 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
836 int e;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
837 mpn_t m;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
838 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
839 int s;
8838
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
840 size_t extra_zeroes;
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
841 unsigned int abs_n;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
842 unsigned int abs_s;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
843 mp_limb_t *pow5_ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
844 size_t pow5_len;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
845 unsigned int s_limbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
846 unsigned int s_bits;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
847 mpn_t pow5;
8838
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
848 mpn_t z;
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
849 void *z_memory;
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
850 char *digits;
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
851
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
852 if (memory == NULL)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
853 return NULL;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
854 /* x = 2^e * m, hence
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
855 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
856 = round (2^s * 5^n * m). */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
857 s = e + n;
8838
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
858 extra_zeroes = 0;
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
859 /* 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
860 if (s > 0 && n > 0)
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
861 {
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
862 extra_zeroes = (s < n ? s : n);
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
863 s -= extra_zeroes;
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
864 n -= extra_zeroes;
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
865 }
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
866 /* 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
867 Before converting to decimal, we need to compute
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
868 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
869 /* 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
870 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
871 abs_n = (n >= 0 ? n : -n);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
872 abs_s = (s >= 0 ? s : -s);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
873 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
874 + abs_s / GMP_LIMB_BITS + 1)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
875 * sizeof (mp_limb_t));
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
876 if (pow5_ptr == NULL)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
877 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
878 free (memory);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
879 return NULL;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
880 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
881 /* Initialize with 1. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
882 pow5_ptr[0] = 1;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
883 pow5_len = 1;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
884 /* Multiply with 5^|n|. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
885 if (abs_n > 0)
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 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
888 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
889 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
890 48828125, 244140625, 1220703125
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
891 };
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
892 unsigned int n13;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
893 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
894 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
895 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
896 size_t j;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
897 mp_twolimb_t carry = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
898 for (j = 0; j < pow5_len; j++)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
899 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
900 mp_limb_t digit2 = pow5_ptr[j];
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
901 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
902 pow5_ptr[j] = (mp_limb_t) carry;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
903 carry = carry >> GMP_LIMB_BITS;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
904 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
905 if (carry > 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
906 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
907 }
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 s_limbs = abs_s / GMP_LIMB_BITS;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
910 s_bits = abs_s % GMP_LIMB_BITS;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
911 if (n >= 0 ? s >= 0 : s <= 0)
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 /* Multiply with 2^|s|. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
914 if (s_bits > 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
915 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
916 mp_limb_t *ptr = pow5_ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
917 mp_twolimb_t accu = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
918 size_t count;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
919 for (count = pow5_len; count > 0; 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 accu += (mp_twolimb_t) *ptr << s_bits;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
922 *ptr++ = (mp_limb_t) accu;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
923 accu = accu >> GMP_LIMB_BITS;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
924 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
925 if (accu > 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
926 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
927 *ptr = (mp_limb_t) accu;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
928 pow5_len++;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
929 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
930 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
931 if (s_limbs > 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
932 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
933 size_t count;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
934 for (count = pow5_len; count > 0;)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
935 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
936 count--;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
937 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
938 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
939 for (count = s_limbs; count > 0;)
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 count--;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
942 pow5_ptr[count] = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
943 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
944 pow5_len += s_limbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
945 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
946 pow5.limbs = pow5_ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
947 pow5.nlimbs = pow5_len;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
948 if (n >= 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
949 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
950 /* Multiply m with pow5. No division needed. */
8838
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
951 z_memory = multiply (m, pow5, &z);
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
952 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
953 else
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 /* Divide m by pow5 and round. */
8838
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
956 z_memory = divide (m, pow5, &z);
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
957 }
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 else
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 pow5.limbs = pow5_ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
962 pow5.nlimbs = pow5_len;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
963 if (n >= 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
964 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
965 /* n >= 0, s < 0.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
966 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
967 mpn_t numerator;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
968 mpn_t denominator;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
969 void *tmp_memory;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
970 tmp_memory = multiply (m, pow5, &numerator);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
971 if (tmp_memory == NULL)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
972 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
973 free (pow5_ptr);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
974 free (memory);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
975 return NULL;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
976 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
977 /* Construct 2^|s|. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
978 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
979 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
980 size_t i;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
981 for (i = 0; i < s_limbs; i++)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
982 ptr[i] = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
983 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
984 denominator.limbs = ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
985 denominator.nlimbs = s_limbs + 1;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
986 }
8838
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
987 z_memory = divide (numerator, denominator, &z);
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
988 free (tmp_memory);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
989 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
990 else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
991 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
992 /* n < 0, s > 0.
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
993 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
994 mpn_t numerator;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
995 mp_limb_t *num_ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
996 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
997 * sizeof (mp_limb_t));
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
998 if (num_ptr == NULL)
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 free (pow5_ptr);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1001 free (memory);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1002 return NULL;
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 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1005 mp_limb_t *destptr = num_ptr;
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 size_t i;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1008 for (i = 0; i < s_limbs; i++)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1009 *destptr++ = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1010 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1011 if (s_bits > 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1012 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1013 const mp_limb_t *sourceptr = m.limbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1014 mp_twolimb_t accu = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1015 size_t count;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1016 for (count = m.nlimbs; count > 0; count--)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1017 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1018 accu += (mp_twolimb_t) *sourceptr++ << s;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1019 *destptr++ = (mp_limb_t) accu;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1020 accu = accu >> GMP_LIMB_BITS;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1021 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1022 if (accu > 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1023 *destptr++ = (mp_limb_t) accu;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1024 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1025 else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1026 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1027 const mp_limb_t *sourceptr = m.limbs;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1028 size_t count;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1029 for (count = m.nlimbs; count > 0; count--)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1030 *destptr++ = *sourceptr++;
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 numerator.limbs = num_ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1033 numerator.nlimbs = destptr - num_ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1034 }
8838
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
1035 z_memory = divide (numerator, pow5, &z);
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1036 free (num_ptr);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1037 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1038 }
8838
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
1039 free (pow5_ptr);
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
1040 free (memory);
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
1041
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
1042 /* 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
1043
8838
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
1044 if (z_memory == NULL)
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1045 return NULL;
8838
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
1046 digits = convert_to_decimal (z, extra_zeroes);
db95bdbeb72c Optimize the case of huge precision.
Bruno Haible <bruno@clisp.org>
parents: 8837
diff changeset
1047 free (z_memory);
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1048 return digits;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1049 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1050
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1051 /* Assuming x is finite and > 0:
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1052 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
1053 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
1054 static int
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1055 floorlog10l (long double x)
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 int exp;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1058 long double y;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1059 double z;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1060 double l;
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 /* Split into exponential part and mantissa. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1063 y = frexpl (x, &exp);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1064 if (!(y >= 0.0L && y < 1.0L))
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1065 abort ();
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1066 if (y == 0.0L)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1067 return INT_MIN;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1068 if (y < 0.5L)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1069 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1070 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
1071 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1072 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
1073 exp -= GMP_LIMB_BITS;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1074 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1075 if (y < (1.0L / (1 << 16)))
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 y *= 1.0L * (1 << 16);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1078 exp -= 16;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1079 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1080 if (y < (1.0L / (1 << 8)))
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 y *= 1.0L * (1 << 8);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1083 exp -= 8;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1084 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1085 if (y < (1.0L / (1 << 4)))
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1086 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1087 y *= 1.0L * (1 << 4);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1088 exp -= 4;
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 if (y < (1.0L / (1 << 2)))
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1091 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1092 y *= 1.0L * (1 << 2);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1093 exp -= 2;
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 if (y < (1.0L / (1 << 1)))
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1096 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1097 y *= 1.0L * (1 << 1);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1098 exp -= 1;
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 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1101 if (!(y >= 0.5L && y < 1.0L))
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1102 abort ();
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1103 /* 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
1104 l = exp;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1105 z = y;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1106 if (z < 0.70710678118654752444)
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 z *= 1.4142135623730950488;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1109 l -= 0.5;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1110 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1111 if (z < 0.8408964152537145431)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1112 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1113 z *= 1.1892071150027210667;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1114 l -= 0.25;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1115 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1116 if (z < 0.91700404320467123175)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1117 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1118 z *= 1.0905077326652576592;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1119 l -= 0.125;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1120 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1121 if (z < 0.9576032806985736469)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1122 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1123 z *= 1.0442737824274138403;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1124 l -= 0.0625;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1125 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1126 /* Now 0.95 <= z <= 1.01. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1127 z = 1 - z;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1128 /* 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
1129 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
1130 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
1131 /* 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
1132 log10(x). */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1133 l *= 0.30102999566398119523;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1134 /* Round down to the next integer. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1135 return (int) l + (l < 0 ? -1 : 0);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1136 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1137
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1138 #endif
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1139
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
1140 CHAR_T *
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
1141 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
1142 {
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
1143 DIRECTIVES d;
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1144 arguments a;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1145
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
1146 if (PRINTF_PARSE (format, &d, &a) < 0)
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1147 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1148 errno = EINVAL;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1149 return NULL;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1150 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1151
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1152 #define CLEANUP() \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1153 free (d.dir); \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1154 if (a.arg) \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1155 free (a.arg);
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1156
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1157 if (printf_fetchargs (args, &a) < 0)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1158 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1159 CLEANUP ();
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1160 errno = EINVAL;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1161 return NULL;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1162 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1163
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1164 {
4879
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1165 size_t buf_neededlength;
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1166 CHAR_T *buf;
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1167 CHAR_T *buf_malloced;
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
1168 const CHAR_T *cp;
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
1169 size_t i;
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
1170 DIRECTIVE *dp;
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1171 /* Output string accumulator. */
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
1172 CHAR_T *result;
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1173 size_t allocated;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1174 size_t length;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1175
4879
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1176 /* 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
1177 sprintf or snprintf. */
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1178 buf_neededlength =
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1179 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
1180 #if HAVE_ALLOCA
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1181 if (buf_neededlength < 4000 / sizeof (CHAR_T))
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1182 {
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1183 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
1184 buf_malloced = NULL;
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1185 }
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1186 else
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1187 #endif
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1188 {
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1189 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
1190 if (size_overflow_p (buf_memsize))
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1191 goto out_of_memory_1;
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1192 buf = (CHAR_T *) malloc (buf_memsize);
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1193 if (buf == NULL)
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1194 goto out_of_memory_1;
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1195 buf_malloced = buf;
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1196 }
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
1197
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1198 if (resultbuf != NULL)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1199 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1200 result = resultbuf;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1201 allocated = *lengthp;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1202 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1203 else
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1204 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1205 result = NULL;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1206 allocated = 0;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1207 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1208 length = 0;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1209 /* Invariants:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1210 result is either == resultbuf or == NULL or malloc-allocated.
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1211 If length > 0, then result != NULL. */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1212
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
1213 /* 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
1214 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
1215 #define ENSURE_ALLOCATION(needed) \
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
1216 if ((needed) > allocated) \
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
1217 { \
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
1218 size_t memory_size; \
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
1219 CHAR_T *memory; \
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
1220 \
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
1221 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
1222 if ((needed) > allocated) \
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
1223 allocated = (needed); \
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
1224 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
1225 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
1226 goto out_of_memory; \
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
1227 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
1228 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
1229 else \
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
1230 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
1231 if (memory == NULL) \
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
1232 goto out_of_memory; \
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
1233 if (result == resultbuf && length > 0) \
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
1234 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
1235 result = memory; \
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1236 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1237
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1238 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
1239 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1240 if (cp != dp->dir_start)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1241 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1242 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
1243 size_t augmented_length = xsum (length, n);
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1244
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
1245 ENSURE_ALLOCATION (augmented_length);
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
1246 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
1247 length = augmented_length;
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1248 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1249 if (i == d.count)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1250 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1251
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1252 /* Execute a single directive. */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1253 if (dp->conversion == '%')
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1254 {
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
1255 size_t augmented_length;
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
1256
4886
e4317f1f2e2c Use size_t instead of ssize_t.
Bruno Haible <bruno@clisp.org>
parents: 4879
diff changeset
1257 if (!(dp->arg_index == ARG_NONE))
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1258 abort ();
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
1259 augmented_length = xsum (length, 1);
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
1260 ENSURE_ALLOCATION (augmented_length);
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1261 result[length] = '%';
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
1262 length = augmented_length;
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1263 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1264 else
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1265 {
4886
e4317f1f2e2c Use size_t instead of ssize_t.
Bruno Haible <bruno@clisp.org>
parents: 4879
diff changeset
1266 if (!(dp->arg_index != ARG_NONE))
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1267 abort ();
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1268
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1269 if (dp->conversion == 'n')
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1270 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1271 switch (a.arg[dp->arg_index].type)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1272 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1273 case TYPE_COUNT_SCHAR_POINTER:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1274 *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
1275 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1276 case TYPE_COUNT_SHORT_POINTER:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1277 *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
1278 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1279 case TYPE_COUNT_INT_POINTER:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1280 *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
1281 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1282 case TYPE_COUNT_LONGINT_POINTER:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1283 *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
1284 break;
8051
9c2b0396b27c Stylistic change: Use '#if HAVE_*' instead of '#ifdef HAVE_*'.
Bruno Haible <bruno@clisp.org>
parents: 7475
diff changeset
1285 #if HAVE_LONG_LONG_INT
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1286 case TYPE_COUNT_LONGLONGINT_POINTER:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1287 *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
1288 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1289 #endif
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1290 default:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1291 abort ();
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1292 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1293 }
8860
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
1294 #if (NEED_PRINTF_INFINITE_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || 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
1295 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
1296 || dp->conversion == 'e' || dp->conversion == 'E'
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1297 || 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
1298 && (0
8860
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
1299 # if NEED_PRINTF_INFINITE_DOUBLE
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1300 || (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
1301 /* The systems (mingw) which produce wrong output
8865
9e203d8ade65 Stricter check for printf result for NaN arguments.
Bruno Haible <bruno@clisp.org>
parents: 8860
diff changeset
1302 for Inf, -Inf, and NaN also do so for -0.0.
9e203d8ade65 Stricter check for printf result for NaN arguments.
Bruno Haible <bruno@clisp.org>
parents: 8860
diff changeset
1303 Therefore we treat this case here as well. */
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1304 && 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
1305 # endif
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1306 # 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
1307 || a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
8860
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
1308 # elif NEED_PRINTF_INFINITE_LONG_DOUBLE
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
1309 || (a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
8865
9e203d8ade65 Stricter check for printf result for NaN arguments.
Bruno Haible <bruno@clisp.org>
parents: 8860
diff changeset
1310 /* Some systems produce wrong output for Inf,
9e203d8ade65 Stricter check for printf result for NaN arguments.
Bruno Haible <bruno@clisp.org>
parents: 8860
diff changeset
1311 -Inf, and NaN. */
8860
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
1312 && is_infinitel (a.arg[dp->arg_index].a.a_longdouble))
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1313 # endif
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1314 ))
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1315 {
8860
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
1316 # if NEED_PRINTF_INFINITE_DOUBLE && (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE)
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1317 arg_type type = a.arg[dp->arg_index].type;
8846
6fe000202977 Fix a warning in last patch.
Bruno Haible <bruno@clisp.org>
parents: 8840
diff changeset
1318 # endif
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1319 int flags = dp->flags;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1320 int has_width;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1321 size_t width;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1322 int has_precision;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1323 size_t precision;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1324 size_t tmp_length;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1325 CHAR_T tmpbuf[700];
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1326 CHAR_T *tmp;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1327 CHAR_T *pad_ptr;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1328 CHAR_T *p;
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 has_width = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1331 width = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1332 if (dp->width_start != 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 if (dp->width_arg_index != ARG_NONE)
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 int arg;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1337
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1338 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
1339 abort ();
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1340 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
1341 if (arg < 0)
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 /* "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
1344 followed by a positive field width." */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1345 flags |= FLAG_LEFT;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1346 width = (unsigned int) (-arg);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1347 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1348 else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1349 width = arg;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1350 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1351 else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1352 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1353 const CHAR_T *digitp = dp->width_start;
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 do
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1356 width = xsum (xtimes (width, 10), *digitp++ - '0');
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1357 while (digitp != dp->width_end);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1358 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1359 has_width = 1;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1360 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1361
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1362 has_precision = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1363 precision = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1364 if (dp->precision_start != dp->precision_end)
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 if (dp->precision_arg_index != ARG_NONE)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1367 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1368 int arg;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1369
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1370 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
1371 abort ();
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1372 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
1373 /* "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
1374 were omitted." */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1375 if (arg >= 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1376 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1377 precision = arg;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1378 has_precision = 1;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1379 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1380 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1381 else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1382 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1383 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
1384
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1385 precision = 0;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1386 while (digitp != dp->precision_end)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1387 precision = xsum (xtimes (precision, 10), *digitp++ - '0');
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1388 has_precision = 1;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1389 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1390 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1391
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1392 /* 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
1393 %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
1394 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
1395 if (!has_precision)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1396 precision = 6;
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1397
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1398 /* Allocate a temporary buffer of sufficient size. */
8860
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
1399 # if NEED_PRINTF_INFINITE_DOUBLE && NEED_PRINTF_LONG_DOUBLE
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1400 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
1401 # elif NEED_PRINTF_LONG_DOUBLE
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1402 tmp_length = LDBL_DIG + 1;
8860
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
1403 # else
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1404 tmp_length = 0;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1405 # endif
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1406 if (tmp_length < precision)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1407 tmp_length = precision;
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1408 # if NEED_PRINTF_LONG_DOUBLE
8860
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
1409 # if NEED_PRINTF_INFINITE_DOUBLE
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1410 if (type == TYPE_LONGDOUBLE)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1411 # endif
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1412 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
1413 {
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1414 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
1415 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
1416 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1417 /* 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
1418 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
1419 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
1420 tmp_length = exponent + precision;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1421 }
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1422 }
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1423 # endif
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1424 /* Account for sign, decimal point etc. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1425 tmp_length = xsum (tmp_length, 12);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1426
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1427 if (tmp_length < width)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1428 tmp_length = width;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1429
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1430 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
1431
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1432 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
1433 tmp = tmpbuf;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1434 else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1435 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1436 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
1437
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1438 if (size_overflow_p (tmp_memsize))
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1439 /* Overflow, would lead to out of memory. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1440 goto out_of_memory;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1441 tmp = (CHAR_T *) malloc (tmp_memsize);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1442 if (tmp == NULL)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1443 /* Out of memory. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1444 goto out_of_memory;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1445 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1446
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1447 pad_ptr = NULL;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1448 p = tmp;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1449
8860
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
1450 # if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
1451 # if NEED_PRINTF_INFINITE_DOUBLE
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1452 if (type == TYPE_LONGDOUBLE)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1453 # endif
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1454 {
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1455 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
1456
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1457 if (isnanl (arg))
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1458 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1459 if (dp->conversion >= 'A' && dp->conversion <= 'Z')
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1460 {
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1461 *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1462 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1463 else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1464 {
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1465 *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1466 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1467 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1468 else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1469 {
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1470 int sign = 0;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1471 DECL_LONG_DOUBLE_ROUNDING
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 BEGIN_LONG_DOUBLE_ROUNDING ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1474
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1475 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
1476 {
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1477 sign = -1;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1478 arg = -arg;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1479 }
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1480
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1481 if (sign < 0)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1482 *p++ = '-';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1483 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
1484 *p++ = '+';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1485 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
1486 *p++ = ' ';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1487
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1488 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
1489 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1490 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
1491 {
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1492 *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1493 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1494 else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1495 {
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1496 *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1497 }
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1498 }
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 {
8860
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
1501 # if NEED_PRINTF_LONG_DOUBLE
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1502 pad_ptr = p;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1503
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1504 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
1505 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1506 char *digits;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1507 size_t ndigits;
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1508
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1509 digits =
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1510 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
1511 if (digits == NULL)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1512 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1513 END_LONG_DOUBLE_ROUNDING ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1514 goto out_of_memory;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1515 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1516 ndigits = strlen (digits);
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1517
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1518 if (ndigits > precision)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1519 do
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1520 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1521 --ndigits;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1522 *p++ = digits[ndigits];
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1523 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1524 while (ndigits > precision);
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1525 else
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1526 *p++ = '0';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1527 /* Here ndigits <= precision. */
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1528 if ((flags & FLAG_ALT) || precision > 0)
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 *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
1531 for (; precision > ndigits; precision--)
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1532 *p++ = '0';
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1533 while (ndigits > 0)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1534 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1535 --ndigits;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1536 *p++ = digits[ndigits];
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1537 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1538 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1539
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1540 free (digits);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1541 }
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1542 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
1543 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1544 int exponent;
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1545
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1546 if (arg == 0.0L)
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1547 {
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1548 exponent = 0;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1549 *p++ = '0';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1550 if ((flags & FLAG_ALT) || precision > 0)
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1551 {
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1552 *p++ = decimal_point_char ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1553 for (; precision > 0; precision--)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1554 *p++ = '0';
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1555 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1556 }
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1557 else
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1558 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1559 /* arg > 0.0L. */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1560 int adjusted;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1561 char *digits;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1562 size_t ndigits;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1563
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1564 exponent = floorlog10l (arg);
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1565 adjusted = 0;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1566 for (;;)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1567 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1568 digits =
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1569 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
1570 (int)precision - exponent);
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1571 if (digits == NULL)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1572 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1573 END_LONG_DOUBLE_ROUNDING ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1574 goto out_of_memory;
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 ndigits = strlen (digits);
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1577
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1578 if (ndigits == precision + 1)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1579 break;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1580 if (ndigits < precision
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1581 || ndigits > precision + 2)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1582 /* 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
1583 precisely enough. */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1584 abort ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1585 if (adjusted)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1586 /* 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
1587 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
1588 loop. */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1589 abort ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1590 free (digits);
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1591 if (ndigits == precision)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1592 exponent -= 1;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1593 else
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1594 exponent += 1;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1595 adjusted = 1;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1596 }
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1597
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1598 /* Here ndigits = precision+1. */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1599 *p++ = digits[--ndigits];
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1600 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
1601 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1602 *p++ = decimal_point_char ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1603 while (ndigits > 0)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1604 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1605 --ndigits;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1606 *p++ = digits[ndigits];
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1607 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1608 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1609
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1610 free (digits);
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1611 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1612
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1613 *p++ = dp->conversion; /* 'e' or 'E' */
8860
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
1614 # if WIDE_CHAR_VERSION
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1615 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1616 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
1617 { '%', '+', '.', '2', 'd', '\0' };
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1618 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
1619 }
8860
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
1620 # else
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1621 sprintf (p, "%+.2d", exponent);
8860
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
1622 # endif
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1623 while (*p != '\0')
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1624 p++;
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 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
1627 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1628 if (precision == 0)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1629 precision = 1;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1630 /* precision >= 1. */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1631
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1632 if (arg == 0.0L)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1633 /* 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
1634 Use fixed-point notation. */
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1635 {
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1636 size_t ndigits = precision;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1637 /* 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
1638 dropped. */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1639 size_t nzeroes =
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1640 (flags & FLAG_ALT ? 0 : precision - 1);
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1641
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1642 --ndigits;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1643 *p++ = '0';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1644 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
1645 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1646 *p++ = decimal_point_char ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1647 while (ndigits > nzeroes)
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;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1650 *p++ = '0';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1651 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1652 }
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1653 }
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1654 else
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1655 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1656 /* arg > 0.0L. */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1657 int exponent;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1658 int adjusted;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1659 char *digits;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1660 size_t ndigits;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1661 size_t nzeroes;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1662
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1663 exponent = floorlog10l (arg);
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1664 adjusted = 0;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1665 for (;;)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1666 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1667 digits =
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1668 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
1669 (int)(precision - 1) - exponent);
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1670 if (digits == NULL)
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 END_LONG_DOUBLE_ROUNDING ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1673 goto out_of_memory;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1674 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1675 ndigits = strlen (digits);
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1676
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1677 if (ndigits == precision)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1678 break;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1679 if (ndigits < precision - 1
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1680 || ndigits > precision + 1)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1681 /* 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
1682 precisely enough. */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1683 abort ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1684 if (adjusted)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1685 /* 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
1686 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
1687 loop. */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1688 abort ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1689 free (digits);
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1690 if (ndigits < precision)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1691 exponent -= 1;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1692 else
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1693 exponent += 1;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1694 adjusted = 1;
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 /* Here ndigits = precision. */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1697
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1698 /* 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
1699 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
1700 nzeroes = 0;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1701 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
1702 while (nzeroes < ndigits
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1703 && digits[nzeroes] == '0')
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1704 nzeroes++;
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1705
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1706 /* 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
1707 if (exponent >= -4
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1708 && exponent < (long)precision)
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1709 {
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1710 /* Fixed-point notation:
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1711 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
1712 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
1713 digits without trailing zeroes. */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1714 if (exponent >= 0)
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 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
1717 /* Note: count <= precision = ndigits. */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1718 for (; count > 0; count--)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1719 *p++ = digits[--ndigits];
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1720 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
1721 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1722 *p++ = decimal_point_char ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1723 while (ndigits > nzeroes)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1724 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1725 --ndigits;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1726 *p++ = digits[ndigits];
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1727 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1728 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1729 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1730 else
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1731 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1732 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
1733 *p++ = '0';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1734 *p++ = decimal_point_char ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1735 for (; count > 0; count--)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1736 *p++ = '0';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1737 while (ndigits > nzeroes)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1738 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1739 --ndigits;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1740 *p++ = digits[ndigits];
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1741 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1742 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1743 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1744 else
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1745 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1746 /* Exponential notation. */
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1747 *p++ = digits[--ndigits];
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1748 if ((flags & FLAG_ALT) || ndigits > nzeroes)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1749 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1750 *p++ = decimal_point_char ();
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1751 while (ndigits > nzeroes)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1752 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1753 --ndigits;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1754 *p++ = digits[ndigits];
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1755 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1756 }
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1757 *p++ = dp->conversion - 'G' + 'E'; /* 'e' or 'E' */
8860
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
1758 # if WIDE_CHAR_VERSION
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1759 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1760 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
1761 { '%', '+', '.', '2', 'd', '\0' };
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1762 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
1763 }
8860
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
1764 # else
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1765 sprintf (p, "%+.2d", exponent);
8860
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
1766 # endif
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1767 while (*p != '\0')
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1768 p++;
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1769 }
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1770
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1771 free (digits);
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1772 }
8840
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 else
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1775 abort ();
8860
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
1776 # else
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
1777 /* arg is finite. */
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
1778 abort ();
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
1779 # endif
8840
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
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1782 END_LONG_DOUBLE_ROUNDING ();
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 }
8860
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
1785 # if NEED_PRINTF_INFINITE_DOUBLE
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1786 else
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1787 # endif
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1788 # endif
8860
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
1789 # if NEED_PRINTF_INFINITE_DOUBLE
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1790 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1791 /* 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
1792 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
1793
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1794 if (isnan (arg))
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 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
1797 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1798 *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
1799 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1800 else
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1801 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1802 *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
1803 }
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 else
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1806 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1807 int sign = 0;
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1808
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1809 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
1810 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1811 sign = -1;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1812 arg = -arg;
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1813 }
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 if (sign < 0)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1816 *p++ = '-';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1817 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
1818 *p++ = '+';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1819 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
1820 *p++ = ' ';
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 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
1823 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1824 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
1825 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1826 *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
1827 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1828 else
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1829 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1830 *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1831 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1832 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1833 else
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1834 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1835 if (!(arg == 0.0))
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1836 abort ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1837
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1838 pad_ptr = p;
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1839
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1840 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
1841 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1842 *p++ = '0';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1843 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
1844 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1845 *p++ = decimal_point_char ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1846 for (; precision > 0; precision--)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1847 *p++ = '0';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1848 }
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 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
1851 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1852 *p++ = '0';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1853 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
1854 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1855 *p++ = decimal_point_char ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1856 for (; precision > 0; precision--)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1857 *p++ = '0';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1858 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1859 *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
1860 *p++ = '+';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1861 /* 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
1862 the native printf implementation. */
8860
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
1863 # if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1864 *p++ = '0';
8860
771a56a41b5b Fix *printf result for NaN, Inf on AIX, Solaris, OSF/1.
Bruno Haible <bruno@clisp.org>
parents: 8846
diff changeset
1865 # endif
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1866 *p++ = '0';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1867 *p++ = '0';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1868 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1869 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
1870 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1871 *p++ = '0';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1872 if (flags & FLAG_ALT)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1873 {
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1874 size_t ndigits =
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1875 (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
1876 *p++ = decimal_point_char ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1877 for (; ndigits > 0; --ndigits)
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1878 *p++ = '0';
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1879 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1880 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1881 else
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1882 abort ();
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1883 }
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1884 }
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1885 }
8840
792e05ae7ac8 Fix *printf result for NaN, Inf, -0.0 on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8838
diff changeset
1886 # endif
8832
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1887
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1888 /* 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
1889 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
1890 if (has_width && p - tmp < width)
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 size_t pad = width - (p - tmp);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1893 CHAR_T *end = p + pad;
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 if (flags & FLAG_LEFT)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1896 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1897 /* Pad with spaces on the right. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1898 for (; pad > 0; pad--)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1899 *p++ = ' ';
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1900 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1901 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
1902 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1903 /* Pad with zeroes. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1904 CHAR_T *q = end;
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 while (p > pad_ptr)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1907 *--q = *--p;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1908 for (; pad > 0; pad--)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1909 *p++ = '0';
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 else
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1912 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1913 /* Pad with spaces on the left. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1914 CHAR_T *q = end;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1915
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1916 while (p > tmp)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1917 *--q = *--p;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1918 for (; pad > 0; pad--)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1919 *p++ = ' ';
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1920 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1921
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1922 p = end;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1923 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1924
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1925 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1926 size_t count = p - tmp;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1927
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1928 if (count >= tmp_length)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1929 /* tmp_length was incorrectly calculated - fix the
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1930 code above! */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1931 abort ();
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1932
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1933 /* Make room for the result. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1934 if (count >= allocated - length)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1935 {
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1936 size_t n = xsum (length, count);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1937
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1938 ENSURE_ALLOCATION (n);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1939 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1940
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1941 /* Append the result. */
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1942 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
1943 if (tmp != tmpbuf)
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1944 free (tmp);
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1945 length += count;
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1946 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1947 }
1466c973f476 Add support for 'long double' number output.
Bruno Haible <bruno@clisp.org>
parents: 8831
diff changeset
1948 #endif
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1949 #if NEED_PRINTF_DIRECTIVE_A && !defined IN_LIBINTL
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1950 else if (dp->conversion == 'a' || dp->conversion == 'A')
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 arg_type type = a.arg[dp->arg_index].type;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1953 int flags = dp->flags;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1954 int has_width;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1955 size_t width;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1956 int has_precision;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1957 size_t precision;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1958 size_t tmp_length;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1959 CHAR_T tmpbuf[700];
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1960 CHAR_T *tmp;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1961 CHAR_T *pad_ptr;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1962 CHAR_T *p;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1963
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1964 has_width = 0;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1965 width = 0;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1966 if (dp->width_start != dp->width_end)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1967 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1968 if (dp->width_arg_index != ARG_NONE)
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 int arg;
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 if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1973 abort ();
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1974 arg = a.arg[dp->width_arg_index].a.a_int;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1975 if (arg < 0)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1976 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1977 /* "A negative field width is taken as a '-' flag
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1978 followed by a positive field width." */
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1979 flags |= FLAG_LEFT;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1980 width = (unsigned int) (-arg);
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1981 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1982 else
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1983 width = arg;
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->width_start;
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 do
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1990 width = xsum (xtimes (width, 10), *digitp++ - '0');
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1991 while (digitp != dp->width_end);
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1992 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1993 has_width = 1;
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 has_precision = 0;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1997 precision = 0;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1998 if (dp->precision_start != dp->precision_end)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
1999 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2000 if (dp->precision_arg_index != ARG_NONE)
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 int arg;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2003
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2004 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2005 abort ();
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2006 arg = a.arg[dp->precision_arg_index].a.a_int;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2007 /* "A negative precision is taken as if the precision
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2008 were omitted." */
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2009 if (arg >= 0)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2010 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2011 precision = arg;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2012 has_precision = 1;
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 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2015 else
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 const CHAR_T *digitp = dp->precision_start + 1;
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 precision = 0;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2020 while (digitp != dp->precision_end)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2021 precision = xsum (xtimes (precision, 10), *digitp++ - '0');
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2022 has_precision = 1;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2023 }
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
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2026 /* Allocate a temporary buffer of sufficient size. */
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2027 if (type == TYPE_LONGDOUBLE)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2028 tmp_length =
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2029 (unsigned int) ((LDBL_DIG + 1)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2030 * 0.831 /* decimal -> hexadecimal */
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2031 )
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2032 + 1; /* turn floor into ceil */
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2033 else
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2034 tmp_length =
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2035 (unsigned int) ((DBL_DIG + 1)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2036 * 0.831 /* decimal -> hexadecimal */
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 + 1; /* turn floor into ceil */
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2039 if (tmp_length < precision)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2040 tmp_length = precision;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2041 /* Account for sign, decimal point etc. */
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2042 tmp_length = xsum (tmp_length, 12);
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 if (tmp_length < width)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2045 tmp_length = width;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2046
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2047 tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2048
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2049 if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T))
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2050 tmp = tmpbuf;
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 size_t tmp_memsize = xtimes (tmp_length, sizeof (CHAR_T));
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2054
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2055 if (size_overflow_p (tmp_memsize))
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2056 /* Overflow, would lead to out of memory. */
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2057 goto out_of_memory;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2058 tmp = (CHAR_T *) malloc (tmp_memsize);
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2059 if (tmp == NULL)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2060 /* Out of memory. */
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2061 goto out_of_memory;
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 pad_ptr = NULL;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2065 p = tmp;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2066 if (type == TYPE_LONGDOUBLE)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2067 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2068 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
2069
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2070 if (isnanl (arg))
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2071 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2072 if (dp->conversion == 'A')
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2073 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2074 *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2075 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2076 else
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2077 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2078 *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2079 }
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 else
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2082 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2083 int sign = 0;
8531
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents: 8529
diff changeset
2084 DECL_LONG_DOUBLE_ROUNDING
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents: 8529
diff changeset
2085
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents: 8529
diff changeset
2086 BEGIN_LONG_DOUBLE_ROUNDING ();
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2087
8655
9a272158fe43 Faster determination of the sign of a number.
Bruno Haible <bruno@clisp.org>
parents: 8648
diff changeset
2088 if (signbit (arg)) /* arg < 0.0L or negative zero */
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2089 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2090 sign = -1;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2091 arg = -arg;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2092 }
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 if (sign < 0)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2095 *p++ = '-';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2096 else if (flags & FLAG_SHOWSIGN)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2097 *p++ = '+';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2098 else if (flags & FLAG_SPACE)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2099 *p++ = ' ';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2100
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2101 if (arg > 0.0L && arg + arg == arg)
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2102 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2103 if (dp->conversion == 'A')
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2104 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2105 *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2106 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2107 else
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2108 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2109 *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2110 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2111 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2112 else
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 int exponent;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2115 long double mantissa;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2116
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2117 if (arg > 0.0L)
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2118 mantissa = printf_frexpl (arg, &exponent);
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2119 else
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 exponent = 0;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2122 mantissa = 0.0L;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2123 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2124
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2125 if (has_precision
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2126 && precision < (unsigned int) ((LDBL_DIG + 1) * 0.831) + 1)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2127 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2128 /* Round the mantissa. */
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2129 long double tail = mantissa;
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2130 size_t q;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2131
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2132 for (q = precision; ; q--)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2133 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2134 int digit = (int) tail;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2135 tail -= digit;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2136 if (q == 0)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2137 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2138 if (digit & 1 ? tail >= 0.5L : tail > 0.5L)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2139 tail = 1 - tail;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2140 else
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2141 tail = - tail;
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2142 break;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2143 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2144 tail *= 16.0L;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2145 }
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2146 if (tail != 0.0L)
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2147 for (q = precision; q > 0; q--)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2148 tail *= 0.0625L;
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2149 mantissa += tail;
8335
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
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2152 *p++ = '0';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2153 *p++ = dp->conversion - 'A' + 'X';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2154 pad_ptr = p;
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 int digit;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2157
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2158 digit = (int) mantissa;
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2159 mantissa -= digit;
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2160 *p++ = '0' + digit;
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2161 if ((flags & FLAG_ALT)
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2162 || mantissa > 0.0L || precision > 0)
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2163 {
8569
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
2164 *p++ = decimal_point_char ();
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2165 /* This loop terminates because we assume
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2166 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
2167 while (mantissa > 0.0L)
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2168 {
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2169 mantissa *= 16.0L;
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2170 digit = (int) mantissa;
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2171 mantissa -= digit;
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2172 *p++ = digit
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2173 + (digit < 10
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2174 ? '0'
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2175 : dp->conversion - 10);
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2176 if (precision > 0)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2177 precision--;
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 while (precision > 0)
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++ = '0';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2182 precision--;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2183 }
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 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2186 *p++ = dp->conversion - 'A' + 'P';
8648
359d135f748c Assume 'long double' exists.
Bruno Haible <bruno@clisp.org>
parents: 8569
diff changeset
2187 # if WIDE_CHAR_VERSION
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2188 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2189 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
2190 { '%', '+', 'd', '\0' };
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2191 SNPRINTF (p, 6 + 1, decimal_format, exponent);
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2192 }
8648
359d135f748c Assume 'long double' exists.
Bruno Haible <bruno@clisp.org>
parents: 8569
diff changeset
2193 # else
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2194 sprintf (p, "%+d", exponent);
8648
359d135f748c Assume 'long double' exists.
Bruno Haible <bruno@clisp.org>
parents: 8569
diff changeset
2195 # endif
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2196 while (*p != '\0')
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2197 p++;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2198 }
8531
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents: 8529
diff changeset
2199
52719799a90e New module 'fpucw'.
Bruno Haible <bruno@clisp.org>
parents: 8529
diff changeset
2200 END_LONG_DOUBLE_ROUNDING ();
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2201 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2202 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2203 else
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2204 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2205 double arg = a.arg[dp->arg_index].a.a_double;
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 (isnan (arg))
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 if (dp->conversion == 'A')
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 *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
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 else
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 *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2216 }
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 else
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2219 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2220 int sign = 0;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2221
8655
9a272158fe43 Faster determination of the sign of a number.
Bruno Haible <bruno@clisp.org>
parents: 8648
diff changeset
2222 if (signbit (arg)) /* arg < 0.0 or negative zero */
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2223 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2224 sign = -1;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2225 arg = -arg;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2226 }
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 if (sign < 0)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2229 *p++ = '-';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2230 else if (flags & FLAG_SHOWSIGN)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2231 *p++ = '+';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2232 else if (flags & FLAG_SPACE)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2233 *p++ = ' ';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2234
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2235 if (arg > 0.0 && arg + arg == arg)
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2236 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2237 if (dp->conversion == 'A')
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2238 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2239 *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2240 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2241 else
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2242 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2243 *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2244 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2245 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2246 else
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 int exponent;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2249 double mantissa;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2250
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2251 if (arg > 0.0)
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2252 mantissa = printf_frexp (arg, &exponent);
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2253 else
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 exponent = 0;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2256 mantissa = 0.0;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2257 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2258
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2259 if (has_precision
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2260 && precision < (unsigned int) ((DBL_DIG + 1) * 0.831) + 1)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2261 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2262 /* Round the mantissa. */
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2263 double tail = mantissa;
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2264 size_t q;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2265
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2266 for (q = precision; ; q--)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2267 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2268 int digit = (int) tail;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2269 tail -= digit;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2270 if (q == 0)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2271 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2272 if (digit & 1 ? tail >= 0.5 : tail > 0.5)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2273 tail = 1 - tail;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2274 else
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2275 tail = - tail;
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2276 break;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2277 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2278 tail *= 16.0;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2279 }
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2280 if (tail != 0.0)
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2281 for (q = precision; q > 0; q--)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2282 tail *= 0.0625;
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2283 mantissa += tail;
8335
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
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2286 *p++ = '0';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2287 *p++ = dp->conversion - 'A' + 'X';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2288 pad_ptr = p;
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 int digit;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2291
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2292 digit = (int) mantissa;
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2293 mantissa -= digit;
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2294 *p++ = '0' + digit;
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2295 if ((flags & FLAG_ALT)
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2296 || mantissa > 0.0 || precision > 0)
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2297 {
8569
378e85482afa Use multithread-safe primitives for determining the decimal point character.
Bruno Haible <bruno@clisp.org>
parents: 8554
diff changeset
2298 *p++ = decimal_point_char ();
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2299 /* This loop terminates because we assume
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2300 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
2301 while (mantissa > 0.0)
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2302 {
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2303 mantissa *= 16.0;
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2304 digit = (int) mantissa;
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2305 mantissa -= digit;
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2306 *p++ = digit
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2307 + (digit < 10
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2308 ? '0'
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2309 : dp->conversion - 10);
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2310 if (precision > 0)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2311 precision--;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2312 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2313 while (precision > 0)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2314 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2315 *p++ = '0';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2316 precision--;
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 }
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 *p++ = dp->conversion - 'A' + 'P';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2321 # if WIDE_CHAR_VERSION
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 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
2324 { '%', '+', 'd', '\0' };
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2325 SNPRINTF (p, 6 + 1, decimal_format, exponent);
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2326 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2327 # else
8343
19a934efd02c Oops, fix a couple of bugs in last commit.
Bruno Haible <bruno@clisp.org>
parents: 8335
diff changeset
2328 sprintf (p, "%+d", exponent);
8335
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2329 # endif
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2330 while (*p != '\0')
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2331 p++;
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 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2334 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2335 /* 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
2336 zero padding insertion point being at pad_ptr. */
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2337 if (has_width && p - tmp < width)
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 size_t pad = width - (p - tmp);
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2340 CHAR_T *end = p + pad;
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 if (flags & FLAG_LEFT)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2343 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2344 /* Pad with spaces on the right. */
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2345 for (; pad > 0; pad--)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2346 *p++ = ' ';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2347 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2348 else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
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 /* Pad with zeroes. */
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2351 CHAR_T *q = end;
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 while (p > pad_ptr)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2354 *--q = *--p;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2355 for (; pad > 0; pad--)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2356 *p++ = '0';
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 else
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2359 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2360 /* Pad with spaces on the left. */
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2361 CHAR_T *q = end;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2362
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2363 while (p > tmp)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2364 *--q = *--p;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2365 for (; pad > 0; pad--)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2366 *p++ = ' ';
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2367 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2368
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2369 p = end;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2370 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2371
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2372 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2373 size_t count = p - tmp;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2374
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2375 if (count >= tmp_length)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2376 /* tmp_length was incorrectly calculated - fix the
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2377 code above! */
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2378 abort ();
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2379
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2380 /* Make room for the result. */
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2381 if (count >= allocated - length)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2382 {
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2383 size_t n = xsum (length, count);
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2384
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2385 ENSURE_ALLOCATION (n);
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2386 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2387
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2388 /* Append the result. */
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2389 memcpy (result + length, tmp, count * sizeof (CHAR_T));
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2390 if (tmp != tmpbuf)
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2391 free (tmp);
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2392 length += count;
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2393 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2394 }
2c9de3b6ba5b New module 'vasnprintf-posix'.
Bruno Haible <bruno@clisp.org>
parents: 8254
diff changeset
2395 #endif
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2396 else
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2397 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2398 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
2399 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
2400 #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
2401 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
2402 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
2403 #endif
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2404 #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
2405 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
2406 #else
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2407 # 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
2408 #endif
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2409 CHAR_T *fbp;
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2410 unsigned int prefix_count;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2411 int prefixes[2];
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
2412 #if !USE_SNPRINTF
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2413 size_t tmp_length;
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
2414 CHAR_T tmpbuf[700];
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
2415 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
2416 #endif
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2417
8804
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2418 #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
2419 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
2420 width = 0;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2421 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
2422 {
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2423 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
2424 {
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2425 int arg;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2426
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2427 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
2428 abort ();
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2429 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
2430 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
2431 {
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2432 /* "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
2433 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
2434 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
2435 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
2436 }
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2437 else
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2438 width = arg;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2439 }
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2440 else
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2441 {
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2442 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
2443
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2444 do
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2445 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
2446 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
2447 }
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2448 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
2449 }
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2450 #endif
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2451
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2452 #if !USE_SNPRINTF
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2453 /* Allocate a temporary buffer of sufficient size for calling
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2454 sprintf. */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2455 {
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2456 size_t precision;
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2457
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2458 precision = 6;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2459 if (dp->precision_start != dp->precision_end)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2460 {
4886
e4317f1f2e2c Use size_t instead of ssize_t.
Bruno Haible <bruno@clisp.org>
parents: 4879
diff changeset
2461 if (dp->precision_arg_index != ARG_NONE)
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2462 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2463 int arg;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2464
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2465 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2466 abort ();
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2467 arg = a.arg[dp->precision_arg_index].a.a_int;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2468 precision = (arg < 0 ? 0 : arg);
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2469 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2470 else
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2471 {
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
2472 const CHAR_T *digitp = dp->precision_start + 1;
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2473
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2474 precision = 0;
5066
a2cb70e482fc Fix for format strings like "%2.f".
Bruno Haible <bruno@clisp.org>
parents: 4886
diff changeset
2475 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
2476 precision = xsum (xtimes (precision, 10), *digitp++ - '0');
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2477 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2478 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2479
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2480 switch (dp->conversion)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2481 {
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 '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
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.30103 /* binary -> decimal */
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.30103 /* binary -> decimal */
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.30103 /* binary -> decimal */
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 /* 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
2508 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
2509 /* 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
2510 tmp_length = xsum (tmp_length, 1);
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2511 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2512
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2513 case 'o':
8051
9c2b0396b27c Stylistic change: Use '#if HAVE_*' instead of '#ifdef HAVE_*'.
Bruno Haible <bruno@clisp.org>
parents: 7475
diff changeset
2514 # if HAVE_LONG_LONG_INT
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2515 if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2516 tmp_length =
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2517 (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2518 * 0.333334 /* binary -> octal */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2519 )
6583
eb8d54cb67a4 Fix an incorrect estimation of the sprintf result size.
Bruno Haible <bruno@clisp.org>
parents: 5848
diff changeset
2520 + 1; /* turn floor into ceil */
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2521 else
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2522 # endif
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2523 if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2524 tmp_length =
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2525 (unsigned int) (sizeof (unsigned long) * CHAR_BIT
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2526 * 0.333334 /* binary -> octal */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2527 )
6583
eb8d54cb67a4 Fix an incorrect estimation of the sprintf result size.
Bruno Haible <bruno@clisp.org>
parents: 5848
diff changeset
2528 + 1; /* turn floor into ceil */
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2529 else
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2530 tmp_length =
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2531 (unsigned int) (sizeof (unsigned int) * CHAR_BIT
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2532 * 0.333334 /* binary -> octal */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2533 )
6583
eb8d54cb67a4 Fix an incorrect estimation of the sprintf result size.
Bruno Haible <bruno@clisp.org>
parents: 5848
diff changeset
2534 + 1; /* turn floor into ceil */
eb8d54cb67a4 Fix an incorrect estimation of the sprintf result size.
Bruno Haible <bruno@clisp.org>
parents: 5848
diff changeset
2535 if (tmp_length < precision)
eb8d54cb67a4 Fix an incorrect estimation of the sprintf result size.
Bruno Haible <bruno@clisp.org>
parents: 5848
diff changeset
2536 tmp_length = precision;
eb8d54cb67a4 Fix an incorrect estimation of the sprintf result size.
Bruno Haible <bruno@clisp.org>
parents: 5848
diff changeset
2537 /* 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
2538 tmp_length = xsum (tmp_length, 1);
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2539 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2540
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2541 case 'x': case 'X':
8051
9c2b0396b27c Stylistic change: Use '#if HAVE_*' instead of '#ifdef HAVE_*'.
Bruno Haible <bruno@clisp.org>
parents: 7475
diff changeset
2542 # if HAVE_LONG_LONG_INT
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2543 if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2544 tmp_length =
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2545 (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2546 * 0.25 /* binary -> hexadecimal */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2547 )
6583
eb8d54cb67a4 Fix an incorrect estimation of the sprintf result size.
Bruno Haible <bruno@clisp.org>
parents: 5848
diff changeset
2548 + 1; /* turn floor into ceil */
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2549 else
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2550 # endif
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2551 if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2552 tmp_length =
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2553 (unsigned int) (sizeof (unsigned long) * CHAR_BIT
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2554 * 0.25 /* binary -> hexadecimal */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2555 )
6583
eb8d54cb67a4 Fix an incorrect estimation of the sprintf result size.
Bruno Haible <bruno@clisp.org>
parents: 5848
diff changeset
2556 + 1; /* turn floor into ceil */
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2557 else
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2558 tmp_length =
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2559 (unsigned int) (sizeof (unsigned int) * CHAR_BIT
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2560 * 0.25 /* binary -> hexadecimal */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2561 )
6583
eb8d54cb67a4 Fix an incorrect estimation of the sprintf result size.
Bruno Haible <bruno@clisp.org>
parents: 5848
diff changeset
2562 + 1; /* turn floor into ceil */
eb8d54cb67a4 Fix an incorrect estimation of the sprintf result size.
Bruno Haible <bruno@clisp.org>
parents: 5848
diff changeset
2563 if (tmp_length < precision)
eb8d54cb67a4 Fix an incorrect estimation of the sprintf result size.
Bruno Haible <bruno@clisp.org>
parents: 5848
diff changeset
2564 tmp_length = precision;
eb8d54cb67a4 Fix an incorrect estimation of the sprintf result size.
Bruno Haible <bruno@clisp.org>
parents: 5848
diff changeset
2565 /* 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
2566 tmp_length = xsum (tmp_length, 2);
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2567 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2568
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2569 case 'f': case 'F':
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2570 if (type == TYPE_LONGDOUBLE)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2571 tmp_length =
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2572 (unsigned int) (LDBL_MAX_EXP
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2573 * 0.30103 /* binary -> decimal */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2574 * 2 /* estimate for FLAG_GROUP */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2575 )
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2576 + 1 /* turn floor into ceil */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2577 + 10; /* sign, decimal point etc. */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2578 else
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2579 tmp_length =
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2580 (unsigned int) (DBL_MAX_EXP
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2581 * 0.30103 /* binary -> decimal */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2582 * 2 /* estimate for FLAG_GROUP */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2583 )
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2584 + 1 /* turn floor into ceil */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2585 + 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
2586 tmp_length = xsum (tmp_length, precision);
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2587 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2588
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2589 case 'e': case 'E': case 'g': case 'G':
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2590 tmp_length =
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2591 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
2592 tmp_length = xsum (tmp_length, precision);
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2593 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2594
8254
bbea39ab5a58 Fix estimate of size needed for a 'a' or 'A' conversion.
Bruno Haible <bruno@clisp.org>
parents: 8051
diff changeset
2595 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
2596 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
2597 tmp_length =
bbea39ab5a58 Fix estimate of size needed for a 'a' or 'A' conversion.
Bruno Haible <bruno@clisp.org>
parents: 8051
diff changeset
2598 (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
2599 * 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
2600 )
bbea39ab5a58 Fix estimate of size needed for a 'a' or 'A' conversion.
Bruno Haible <bruno@clisp.org>
parents: 8051
diff changeset
2601 + 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
2602 else
bbea39ab5a58 Fix estimate of size needed for a 'a' or 'A' conversion.
Bruno Haible <bruno@clisp.org>
parents: 8051
diff changeset
2603 tmp_length =
bbea39ab5a58 Fix estimate of size needed for a 'a' or 'A' conversion.
Bruno Haible <bruno@clisp.org>
parents: 8051
diff changeset
2604 (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
2605 * 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
2606 )
bbea39ab5a58 Fix estimate of size needed for a 'a' or 'A' conversion.
Bruno Haible <bruno@clisp.org>
parents: 8051
diff changeset
2607 + 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
2608 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
2609 tmp_length = precision;
bbea39ab5a58 Fix estimate of size needed for a 'a' or 'A' conversion.
Bruno Haible <bruno@clisp.org>
parents: 8051
diff changeset
2610 /* 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
2611 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
2612 break;
bbea39ab5a58 Fix estimate of size needed for a 'a' or 'A' conversion.
Bruno Haible <bruno@clisp.org>
parents: 8051
diff changeset
2613
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2614 case 'c':
8051
9c2b0396b27c Stylistic change: Use '#if HAVE_*' instead of '#ifdef HAVE_*'.
Bruno Haible <bruno@clisp.org>
parents: 7475
diff changeset
2615 # if HAVE_WINT_T && !WIDE_CHAR_VERSION
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2616 if (type == TYPE_WIDE_CHAR)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2617 tmp_length = MB_CUR_MAX;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2618 else
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2619 # endif
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2620 tmp_length = 1;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2621 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2622
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2623 case 's':
8051
9c2b0396b27c Stylistic change: Use '#if HAVE_*' instead of '#ifdef HAVE_*'.
Bruno Haible <bruno@clisp.org>
parents: 7475
diff changeset
2624 # if HAVE_WCHAR_T
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2625 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
2626 {
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2627 tmp_length =
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2628 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
2629
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2630 # if !WIDE_CHAR_VERSION
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2631 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
2632 # endif
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2633 }
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2634 else
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2635 # endif
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2636 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
2637 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2638
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2639 case 'p':
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2640 tmp_length =
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2641 (unsigned int) (sizeof (void *) * CHAR_BIT
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2642 * 0.25 /* binary -> hexadecimal */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2643 )
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2644 + 1 /* turn floor into ceil */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2645 + 2; /* account for leading 0x */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2646 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2647
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2648 default:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2649 abort ();
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2650 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2651
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2652 if (tmp_length < width)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2653 tmp_length = width;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2654
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2655 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
2656 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2657
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
2658 if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T))
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2659 tmp = tmpbuf;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2660 else
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2661 {
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2662 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
2663
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2664 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
2665 /* 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
2666 goto out_of_memory;
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2667 tmp = (CHAR_T *) malloc (tmp_memsize);
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2668 if (tmp == NULL)
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2669 /* Out of memory. */
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2670 goto out_of_memory;
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2671 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2672 #endif
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2673
8804
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2674 /* 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
2675 #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
2676 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
2677 {
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2678 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
2679 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
2680 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
2681 break;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2682 default:
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2683 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
2684 break;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2685 }
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2686 #endif
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 /* Construct the format string for calling snprintf or
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2689 sprintf. */
8804
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2690 fbp = buf;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2691 *fbp++ = '%';
8803
6c1d98929550 Work around lack of support of grouping flag.
Bruno Haible <bruno@clisp.org>
parents: 8664
diff changeset
2692 #if NEED_PRINTF_FLAG_GROUPING
6c1d98929550 Work around lack of support of grouping flag.
Bruno Haible <bruno@clisp.org>
parents: 8664
diff changeset
2693 /* 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
2694 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
2695 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
2696 #else
8804
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2697 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
2698 *fbp++ = '\'';
8803
6c1d98929550 Work around lack of support of grouping flag.
Bruno Haible <bruno@clisp.org>
parents: 8664
diff changeset
2699 #endif
8804
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2700 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
2701 *fbp++ = '-';
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2702 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
2703 *fbp++ = '+';
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2704 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
2705 *fbp++ = ' ';
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2706 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
2707 *fbp++ = '#';
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2708 if (!pad_ourselves)
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2709 {
8804
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2710 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
2711 *fbp++ = '0';
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2712 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
2713 {
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2714 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
2715 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
2716 fbp += n;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2717 }
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2718 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2719 if (dp->precision_start != dp->precision_end)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2720 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2721 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
2722 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
2723 fbp += n;
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2724 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2725
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2726 switch (type)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2727 {
8051
9c2b0396b27c Stylistic change: Use '#if HAVE_*' instead of '#ifdef HAVE_*'.
Bruno Haible <bruno@clisp.org>
parents: 7475
diff changeset
2728 #if HAVE_LONG_LONG_INT
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2729 case TYPE_LONGLONGINT:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2730 case TYPE_ULONGLONGINT:
8830
abc2bcb16721 Support output of 64-bit numbers on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8804
diff changeset
2731 # 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
2732 *fbp++ = 'I';
abc2bcb16721 Support output of 64-bit numbers on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8804
diff changeset
2733 *fbp++ = '6';
abc2bcb16721 Support output of 64-bit numbers on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8804
diff changeset
2734 *fbp++ = '4';
abc2bcb16721 Support output of 64-bit numbers on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8804
diff changeset
2735 break;
abc2bcb16721 Support output of 64-bit numbers on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8804
diff changeset
2736 # else
8804
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2737 *fbp++ = 'l';
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2738 /*FALLTHROUGH*/
8830
abc2bcb16721 Support output of 64-bit numbers on mingw.
Bruno Haible <bruno@clisp.org>
parents: 8804
diff changeset
2739 # endif
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2740 #endif
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2741 case TYPE_LONGINT:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2742 case TYPE_ULONGINT:
8051
9c2b0396b27c Stylistic change: Use '#if HAVE_*' instead of '#ifdef HAVE_*'.
Bruno Haible <bruno@clisp.org>
parents: 7475
diff changeset
2743 #if HAVE_WINT_T
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2744 case TYPE_WIDE_CHAR:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2745 #endif
8051
9c2b0396b27c Stylistic change: Use '#if HAVE_*' instead of '#ifdef HAVE_*'.
Bruno Haible <bruno@clisp.org>
parents: 7475
diff changeset
2746 #if HAVE_WCHAR_T
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2747 case TYPE_WIDE_STRING:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2748 #endif
8804
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2749 *fbp++ = 'l';
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2750 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2751 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
2752 *fbp++ = 'L';
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2753 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2754 default:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2755 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2756 }
8664
40c507f55b0f Implement the %F directive if the system doesn't implement it correctly.
Bruno Haible <bruno@clisp.org>
parents: 8655
diff changeset
2757 #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
2758 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
2759 *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
2760 else
40c507f55b0f Implement the %F directive if the system doesn't implement it correctly.
Bruno Haible <bruno@clisp.org>
parents: 8655
diff changeset
2761 #endif
8804
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2762 *fbp = dp->conversion;
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
2763 #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
2764 fbp[1] = '%';
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2765 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
2766 fbp[3] = '\0';
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2767 #else
8804
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2768 fbp[1] = '\0';
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2769 #endif
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2770
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2771 /* Construct the arguments for calling snprintf or sprintf. */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2772 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
2773 if (!pad_ourselves && dp->width_arg_index != ARG_NONE)
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2774 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2775 if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2776 abort ();
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2777 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
2778 }
4886
e4317f1f2e2c Use size_t instead of ssize_t.
Bruno Haible <bruno@clisp.org>
parents: 4879
diff changeset
2779 if (dp->precision_arg_index != ARG_NONE)
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2780 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2781 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2782 abort ();
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2783 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
2784 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2785
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
2786 #if USE_SNPRINTF
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2787 /* Prepare checking whether snprintf returns the count
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2788 via %n. */
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2789 ENSURE_ALLOCATION (xsum (length, 1));
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2790 result[length] = '\0';
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2791 #endif
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2792
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2793 for (;;)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2794 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2795 size_t maxlen;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2796 int count;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2797 int retcount;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2798
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2799 maxlen = allocated - length;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2800 count = -1;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2801 retcount = 0;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2802
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
2803 #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
2804 /* 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
2805 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
2806 goto overflow;
4704
b7a1b14802c8 Correct cpp indentation.
Jim Meyering <jim@meyering.net>
parents: 4589
diff changeset
2807 # define SNPRINTF_BUF(arg) \
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2808 switch (prefix_count) \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2809 { \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2810 case 0: \
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
2811 retcount = SNPRINTF (result + length, maxlen, buf, \
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2812 arg, &count); \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2813 break; \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2814 case 1: \
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
2815 retcount = SNPRINTF (result + length, maxlen, buf, \
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2816 prefixes[0], arg, &count); \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2817 break; \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2818 case 2: \
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
2819 retcount = SNPRINTF (result + length, maxlen, buf, \
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2820 prefixes[0], prefixes[1], arg, \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2821 &count); \
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 default: \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2824 abort (); \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2825 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2826 #else
4704
b7a1b14802c8 Correct cpp indentation.
Jim Meyering <jim@meyering.net>
parents: 4589
diff changeset
2827 # define SNPRINTF_BUF(arg) \
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2828 switch (prefix_count) \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2829 { \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2830 case 0: \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2831 count = sprintf (tmp, buf, arg); \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2832 break; \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2833 case 1: \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2834 count = sprintf (tmp, buf, prefixes[0], arg); \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2835 break; \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2836 case 2: \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2837 count = sprintf (tmp, buf, prefixes[0], prefixes[1],\
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2838 arg); \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2839 break; \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2840 default: \
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2841 abort (); \
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 #endif
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2844
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2845 switch (type)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2846 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2847 case TYPE_SCHAR:
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 int arg = a.arg[dp->arg_index].a.a_schar;
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_UCHAR:
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 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
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_SHORT:
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 int arg = a.arg[dp->arg_index].a.a_short;
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;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2865 case TYPE_USHORT:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2866 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2867 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
2868 SNPRINTF_BUF (arg);
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2869 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2870 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2871 case TYPE_INT:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2872 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2873 int arg = a.arg[dp->arg_index].a.a_int;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2874 SNPRINTF_BUF (arg);
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2875 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2876 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2877 case TYPE_UINT:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2878 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2879 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
2880 SNPRINTF_BUF (arg);
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2881 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2882 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2883 case TYPE_LONGINT:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2884 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2885 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
2886 SNPRINTF_BUF (arg);
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2887 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2888 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2889 case TYPE_ULONGINT:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2890 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2891 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
2892 SNPRINTF_BUF (arg);
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2893 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2894 break;
8051
9c2b0396b27c Stylistic change: Use '#if HAVE_*' instead of '#ifdef HAVE_*'.
Bruno Haible <bruno@clisp.org>
parents: 7475
diff changeset
2895 #if HAVE_LONG_LONG_INT
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2896 case TYPE_LONGLONGINT:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2897 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2898 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
2899 SNPRINTF_BUF (arg);
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2900 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2901 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2902 case TYPE_ULONGLONGINT:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2903 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2904 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
2905 SNPRINTF_BUF (arg);
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 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2908 #endif
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2909 case TYPE_DOUBLE:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2910 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2911 double arg = a.arg[dp->arg_index].a.a_double;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2912 SNPRINTF_BUF (arg);
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 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2915 case TYPE_LONGDOUBLE:
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 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
2918 SNPRINTF_BUF (arg);
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2919 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2920 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2921 case TYPE_CHAR:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2922 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2923 int arg = a.arg[dp->arg_index].a.a_char;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2924 SNPRINTF_BUF (arg);
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2925 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2926 break;
8051
9c2b0396b27c Stylistic change: Use '#if HAVE_*' instead of '#ifdef HAVE_*'.
Bruno Haible <bruno@clisp.org>
parents: 7475
diff changeset
2927 #if HAVE_WINT_T
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2928 case TYPE_WIDE_CHAR:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2929 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2930 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
2931 SNPRINTF_BUF (arg);
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2932 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2933 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2934 #endif
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2935 case TYPE_STRING:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2936 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2937 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
2938 SNPRINTF_BUF (arg);
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2939 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2940 break;
8051
9c2b0396b27c Stylistic change: Use '#if HAVE_*' instead of '#ifdef HAVE_*'.
Bruno Haible <bruno@clisp.org>
parents: 7475
diff changeset
2941 #if HAVE_WCHAR_T
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2942 case TYPE_WIDE_STRING:
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 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
2945 SNPRINTF_BUF (arg);
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2946 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2947 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2948 #endif
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2949 case TYPE_POINTER:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2950 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2951 void *arg = a.arg[dp->arg_index].a.a_pointer;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2952 SNPRINTF_BUF (arg);
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2953 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2954 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2955 default:
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2956 abort ();
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2957 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2958
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
2959 #if USE_SNPRINTF
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2960 /* Portability: Not all implementations of snprintf()
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2961 are ISO C 99 compliant. Determine the number of
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2962 bytes that snprintf() has produced or would have
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2963 produced. */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2964 if (count >= 0)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2965 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2966 /* Verify that snprintf() has NUL-terminated its
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2967 result. */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2968 if (count < maxlen && result[length + count] != '\0')
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2969 abort ();
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2970 /* Portability hack. */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2971 if (retcount > count)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2972 count = retcount;
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 else
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 /* snprintf() doesn't understand the '%n'
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2977 directive. */
8804
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
2978 if (fbp[1] != '\0')
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2979 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2980 /* Don't use the '%n' directive; instead, look
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2981 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
2982 fbp[1] = '\0';
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2983 continue;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
2984 }
4801
83746ec4d74a Portability to HP-UX 10, found by Jim Meyering.
Bruno Haible <bruno@clisp.org>
parents: 4704
diff changeset
2985 else
83746ec4d74a Portability to HP-UX 10, found by Jim Meyering.
Bruno Haible <bruno@clisp.org>
parents: 4704
diff changeset
2986 {
83746ec4d74a Portability to HP-UX 10, found by Jim Meyering.
Bruno Haible <bruno@clisp.org>
parents: 4704
diff changeset
2987 /* 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
2988 if (retcount < 0)
83746ec4d74a Portability to HP-UX 10, found by Jim Meyering.
Bruno Haible <bruno@clisp.org>
parents: 4704
diff changeset
2989 {
83746ec4d74a Portability to HP-UX 10, found by Jim Meyering.
Bruno Haible <bruno@clisp.org>
parents: 4704
diff changeset
2990 /* 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
2991 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
2992 *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
2993 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
2994 buffer is too small. */
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2995 size_t bigger_need =
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
2996 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
2997 ENSURE_ALLOCATION (bigger_need);
83746ec4d74a Portability to HP-UX 10, found by Jim Meyering.
Bruno Haible <bruno@clisp.org>
parents: 4704
diff changeset
2998 continue;
83746ec4d74a Portability to HP-UX 10, found by Jim Meyering.
Bruno Haible <bruno@clisp.org>
parents: 4704
diff changeset
2999 }
83746ec4d74a Portability to HP-UX 10, found by Jim Meyering.
Bruno Haible <bruno@clisp.org>
parents: 4704
diff changeset
3000 else
83746ec4d74a Portability to HP-UX 10, found by Jim Meyering.
Bruno Haible <bruno@clisp.org>
parents: 4704
diff changeset
3001 count = retcount;
83746ec4d74a Portability to HP-UX 10, found by Jim Meyering.
Bruno Haible <bruno@clisp.org>
parents: 4704
diff changeset
3002 }
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3003 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3004 #endif
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3005
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3006 /* Attempt to handle failure. */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3007 if (count < 0)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3008 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3009 if (!(result == resultbuf || result == NULL))
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3010 free (result);
4879
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
3011 if (buf_malloced != NULL)
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
3012 free (buf_malloced);
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3013 CLEANUP ();
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3014 errno = EINVAL;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3015 return NULL;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3016 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3017
8837
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
3018 /* Make room for the result. */
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
3019 if (count >= maxlen)
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
3020 {
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
3021 /* 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
3022 proportionally, to avoid looping eternally if
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
3023 snprintf() reports a too small count. */
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
3024 size_t n =
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
3025 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
3026
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
3027 ENSURE_ALLOCATION (n);
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
3028 #if USE_SNPRINTF
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
3029 continue;
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
3030 #else
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
3031 maxlen = allocated - length;
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
3032 #endif
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
3033 }
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
3034
8804
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3035 /* Perform padding. */
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3036 #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
3037 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
3038 {
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3039 # 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
3040 /* 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
3041 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
3042 {
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3043 /* 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
3044 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
3045 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
3046 size_t n =
8837
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
3047 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
3048 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
3049
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3050 length += count;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3051 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
3052 length -= count;
8837
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
3053 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
3054 }
8837
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
3055 /* 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
3056 # endif
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3057 {
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3058 # 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
3059 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
3060 # else
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3061 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
3062 # endif
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3063 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
3064 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
3065 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
3066 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
3067 /* 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
3068 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
3069 || (*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
3070 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
3071 /* 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
3072 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
3073 pad_ptr. */
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 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
3076 {
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3077 /* 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
3078 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
3079 *p++ = ' ';
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3080 }
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3081 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
3082 {
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3083 /* 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
3084 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
3085
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3086 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
3087 *--q = *--p;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3088 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
3089 *p++ = '0';
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3090 }
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3091 else
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3092 {
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3093 /* 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
3094 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
3095
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3096 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
3097 *--q = *--p;
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3098 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
3099 *p++ = ' ';
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3100 }
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3101
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3102 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
3103 }
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3104 }
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3105 #endif
6ce313658b4d Work around an incorrect implementation of the 0 flag on most platforms.
Bruno Haible <bruno@clisp.org>
parents: 8803
diff changeset
3106
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
3107 #if !USE_SNPRINTF
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3108 if (count >= tmp_length)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3109 /* tmp_length was incorrectly calculated - fix the
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3110 code above! */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3111 abort ();
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3112 #endif
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3113
8837
6d6277df29a9 Fix logic bug introduced on 2007-05-06.
Bruno Haible <bruno@clisp.org>
parents: 8835
diff changeset
3114 /* Here still count < maxlen. */
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3115
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
3116 #if USE_SNPRINTF
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3117 /* The snprintf() result did fit. */
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3118 #else
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3119 /* Append the sprintf() result. */
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
3120 memcpy (result + length, tmp, count * sizeof (CHAR_T));
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3121 if (tmp != tmpbuf)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3122 free (tmp);
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3123 #endif
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3124
8664
40c507f55b0f Implement the %F directive if the system doesn't implement it correctly.
Bruno Haible <bruno@clisp.org>
parents: 8655
diff changeset
3125 #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
3126 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
3127 {
40c507f55b0f Implement the %F directive if the system doesn't implement it correctly.
Bruno Haible <bruno@clisp.org>
parents: 8655
diff changeset
3128 /* 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
3129 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
3130 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
3131 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
3132 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
3133 *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
3134 }
40c507f55b0f Implement the %F directive if the system doesn't implement it correctly.
Bruno Haible <bruno@clisp.org>
parents: 8655
diff changeset
3135 #endif
40c507f55b0f Implement the %F directive if the system doesn't implement it correctly.
Bruno Haible <bruno@clisp.org>
parents: 8655
diff changeset
3136
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3137 length += count;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3138 break;
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3139 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3140 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3141 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3142 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3143
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3144 /* Add the final NUL. */
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
3145 ENSURE_ALLOCATION (xsum (length, 1));
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3146 result[length] = '\0';
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3147
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3148 if (result != resultbuf && length + 1 < allocated)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3149 {
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3150 /* 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
3151 CHAR_T *memory;
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3152
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
3153 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
3154 if (memory != NULL)
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3155 result = memory;
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
4879
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
3158 if (buf_malloced != NULL)
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
3159 free (buf_malloced);
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3160 CLEANUP ();
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3161 *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
3162 /* 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
3163 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
3164 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
3165 not have this limitation. */
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3166 return result;
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
3167
8468
336e69863755 Fix endless loop when the given allocated size was > INT_MAX.
Bruno Haible <bruno@clisp.org>
parents: 8465
diff changeset
3168 overflow:
336e69863755 Fix endless loop when the given allocated size was > INT_MAX.
Bruno Haible <bruno@clisp.org>
parents: 8465
diff changeset
3169 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
3170 free (result);
336e69863755 Fix endless loop when the given allocated size was > INT_MAX.
Bruno Haible <bruno@clisp.org>
parents: 8465
diff changeset
3171 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
3172 free (buf_malloced);
336e69863755 Fix endless loop when the given allocated size was > INT_MAX.
Bruno Haible <bruno@clisp.org>
parents: 8465
diff changeset
3173 CLEANUP ();
336e69863755 Fix endless loop when the given allocated size was > INT_MAX.
Bruno Haible <bruno@clisp.org>
parents: 8465
diff changeset
3174 errno = EOVERFLOW;
336e69863755 Fix endless loop when the given allocated size was > INT_MAX.
Bruno Haible <bruno@clisp.org>
parents: 8465
diff changeset
3175 return NULL;
336e69863755 Fix endless loop when the given allocated size was > INT_MAX.
Bruno Haible <bruno@clisp.org>
parents: 8465
diff changeset
3176
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
3177 out_of_memory:
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
3178 if (!(result == resultbuf || result == NULL))
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
3179 free (result);
4879
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
3180 if (buf_malloced != NULL)
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
3181 free (buf_malloced);
9b96adbed643 Avoid alloca with too large size.
Bruno Haible <bruno@clisp.org>
parents: 4872
diff changeset
3182 out_of_memory_1:
4872
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
3183 CLEANUP ();
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
3184 errno = ENOMEM;
c5afc99b8ce5 Use xsize.h to protect against memory size overflows.
Bruno Haible <bruno@clisp.org>
parents: 4871
diff changeset
3185 return NULL;
4224
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3186 }
83eabea25586 New modules vasnprintf and vasprintf.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3187 }
4871
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
3188
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
3189 #undef SNPRINTF
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
3190 #undef USE_SNPRINTF
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
3191 #undef PRINTF_PARSE
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
3192 #undef DIRECTIVES
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
3193 #undef DIRECTIVE
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
3194 #undef CHAR_T
87df35000dab Merge support for wide characters, from GNU gettext.
Bruno Haible <bruno@clisp.org>
parents: 4801
diff changeset
3195 #undef VASNPRINTF