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