Branch data Line data Source code
1 : : /* vsprintf with automatic memory allocation.
2 : : Copyright (C) 1999, 2002-2012 Free Software Foundation, Inc.
3 : :
4 : : This program is free software; you can redistribute it and/or modify
5 : : it under the terms of the GNU General Public License as published by
6 : : the Free Software Foundation; either version 3, or (at your option)
7 : : any later version.
8 : :
9 : : This program is distributed in the hope that it will be useful,
10 : : but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : : GNU General Public License for more details.
13 : :
14 : : You should have received a copy of the GNU General Public License along
15 : : with this program; if not, see <http://www.gnu.org/licenses/>. */
16 : :
17 : : /* This file can be parametrized with the following macros:
18 : : VASNPRINTF The name of the function being defined.
19 : : FCHAR_T The element type of the format string.
20 : : DCHAR_T The element type of the destination (result) string.
21 : : FCHAR_T_ONLY_ASCII Set to 1 to enable verification that all characters
22 : : in the format string are ASCII. MUST be set if
23 : : FCHAR_T and DCHAR_T are not the same type.
24 : : DIRECTIVE Structure denoting a format directive.
25 : : Depends on FCHAR_T.
26 : : DIRECTIVES Structure denoting the set of format directives of a
27 : : format string. Depends on FCHAR_T.
28 : : PRINTF_PARSE Function that parses a format string.
29 : : Depends on FCHAR_T.
30 : : DCHAR_CPY memcpy like function for DCHAR_T[] arrays.
31 : : DCHAR_SET memset like function for DCHAR_T[] arrays.
32 : : DCHAR_MBSNLEN mbsnlen like function for DCHAR_T[] arrays.
33 : : SNPRINTF The system's snprintf (or similar) function.
34 : : This may be either snprintf or swprintf.
35 : : TCHAR_T The element type of the argument and result string
36 : : of the said SNPRINTF function. This may be either
37 : : char or wchar_t. The code exploits that
38 : : sizeof (TCHAR_T) | sizeof (DCHAR_T) and
39 : : alignof (TCHAR_T) <= alignof (DCHAR_T).
40 : : DCHAR_IS_TCHAR Set to 1 if DCHAR_T and TCHAR_T are the same type.
41 : : DCHAR_CONV_FROM_ENCODING A function to convert from char[] to DCHAR[].
42 : : DCHAR_IS_UINT8_T Set to 1 if DCHAR_T is uint8_t.
43 : : DCHAR_IS_UINT16_T Set to 1 if DCHAR_T is uint16_t.
44 : : DCHAR_IS_UINT32_T Set to 1 if DCHAR_T is uint32_t. */
45 : :
46 : : /* Tell glibc's <stdio.h> to provide a prototype for snprintf().
47 : : This must come before <config.h> because <config.h> may include
48 : : <features.h>, and once <features.h> has been included, it's too late. */
49 : : #ifndef _GNU_SOURCE
50 : : # define _GNU_SOURCE 1
51 : : #endif
52 : :
53 : : #ifndef VASNPRINTF
54 : : # include <config.h>
55 : : #endif
56 : : #ifndef IN_LIBINTL
57 : : # include <alloca.h>
58 : : #endif
59 : :
60 : : /* Specification. */
61 : : #ifndef VASNPRINTF
62 : : # if WIDE_CHAR_VERSION
63 : : # include "vasnwprintf.h"
64 : : # else
65 : : # include "vasnprintf.h"
66 : : # endif
67 : : #endif
68 : :
69 : : #include <locale.h> /* localeconv() */
70 : : #include <stdio.h> /* snprintf(), sprintf() */
71 : : #include <stdlib.h> /* abort(), malloc(), realloc(), free() */
72 : : #include <string.h> /* memcpy(), strlen() */
73 : : #include <errno.h> /* errno */
74 : : #include <limits.h> /* CHAR_BIT */
75 : : #include <float.h> /* DBL_MAX_EXP, LDBL_MAX_EXP */
76 : : #if HAVE_NL_LANGINFO
77 : : # include <langinfo.h>
78 : : #endif
79 : : #ifndef VASNPRINTF
80 : : # if WIDE_CHAR_VERSION
81 : : # include "wprintf-parse.h"
82 : : # else
83 : : # include "printf-parse.h"
84 : : # endif
85 : : #endif
86 : :
87 : : /* Checked size_t computations. */
88 : : #include "xsize.h"
89 : :
90 : : #include "verify.h"
91 : :
92 : : #if (NEED_PRINTF_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL
93 : : # include <math.h>
94 : : # include "float+.h"
95 : : #endif
96 : :
97 : : #if (NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL
98 : : # include <math.h>
99 : : # include "isnand-nolibm.h"
100 : : #endif
101 : :
102 : : #if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE) && !defined IN_LIBINTL
103 : : # include <math.h>
104 : : # include "isnanl-nolibm.h"
105 : : # include "fpucw.h"
106 : : #endif
107 : :
108 : : #if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL
109 : : # include <math.h>
110 : : # include "isnand-nolibm.h"
111 : : # include "printf-frexp.h"
112 : : #endif
113 : :
114 : : #if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL
115 : : # include <math.h>
116 : : # include "isnanl-nolibm.h"
117 : : # include "printf-frexpl.h"
118 : : # include "fpucw.h"
119 : : #endif
120 : :
121 : : /* Default parameters. */
122 : : #ifndef VASNPRINTF
123 : : # if WIDE_CHAR_VERSION
124 : : # define VASNPRINTF vasnwprintf
125 : : # define FCHAR_T wchar_t
126 : : # define DCHAR_T wchar_t
127 : : # define TCHAR_T wchar_t
128 : : # define DCHAR_IS_TCHAR 1
129 : : # define DIRECTIVE wchar_t_directive
130 : : # define DIRECTIVES wchar_t_directives
131 : : # define PRINTF_PARSE wprintf_parse
132 : : # define DCHAR_CPY wmemcpy
133 : : # define DCHAR_SET wmemset
134 : : # else
135 : : # define VASNPRINTF vasnprintf
136 : : # define FCHAR_T char
137 : : # define DCHAR_T char
138 : : # define TCHAR_T char
139 : : # define DCHAR_IS_TCHAR 1
140 : : # define DIRECTIVE char_directive
141 : : # define DIRECTIVES char_directives
142 : : # define PRINTF_PARSE printf_parse
143 : : # define DCHAR_CPY memcpy
144 : : # define DCHAR_SET memset
145 : : # endif
146 : : #endif
147 : : #if WIDE_CHAR_VERSION
148 : : /* TCHAR_T is wchar_t. */
149 : : # define USE_SNPRINTF 1
150 : : # if HAVE_DECL__SNWPRINTF
151 : : /* On Windows, the function swprintf() has a different signature than
152 : : on Unix; we use the function _snwprintf() or - on mingw - snwprintf()
153 : : instead. The mingw function snwprintf() has fewer bugs than the
154 : : MSVCRT function _snwprintf(), so prefer that. */
155 : : # if defined __MINGW32__
156 : : # define SNPRINTF snwprintf
157 : : # else
158 : : # define SNPRINTF _snwprintf
159 : : # endif
160 : : # else
161 : : /* Unix. */
162 : : # define SNPRINTF swprintf
163 : : # endif
164 : : #else
165 : : /* TCHAR_T is char. */
166 : : /* Use snprintf if it exists under the name 'snprintf' or '_snprintf'.
167 : : But don't use it on BeOS, since BeOS snprintf produces no output if the
168 : : size argument is >= 0x3000000.
169 : : Also don't use it on Linux libc5, since there snprintf with size = 1
170 : : writes any output without bounds, like sprintf. */
171 : : # if (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF) && !defined __BEOS__ && !(__GNU_LIBRARY__ == 1)
172 : : # define USE_SNPRINTF 1
173 : : # else
174 : : # define USE_SNPRINTF 0
175 : : # endif
176 : : # if HAVE_DECL__SNPRINTF
177 : : /* Windows. The mingw function snprintf() has fewer bugs than the MSVCRT
178 : : function _snprintf(), so prefer that. */
179 : : # if defined __MINGW32__
180 : : # define SNPRINTF snprintf
181 : : /* Here we need to call the native snprintf, not rpl_snprintf. */
182 : : # undef snprintf
183 : : # else
184 : : # define SNPRINTF _snprintf
185 : : # endif
186 : : # else
187 : : /* Unix. */
188 : : # define SNPRINTF snprintf
189 : : /* Here we need to call the native snprintf, not rpl_snprintf. */
190 : : # undef snprintf
191 : : # endif
192 : : #endif
193 : : /* Here we need to call the native sprintf, not rpl_sprintf. */
194 : : #undef sprintf
195 : :
196 : : /* GCC >= 4.0 with -Wall emits unjustified "... may be used uninitialized"
197 : : warnings in this file. Use -Dlint to suppress them. */
198 : : #ifdef lint
199 : : # define IF_LINT(Code) Code
200 : : #else
201 : : # define IF_LINT(Code) /* empty */
202 : : #endif
203 : :
204 : : /* Avoid some warnings from "gcc -Wshadow".
205 : : This file doesn't use the exp() and remainder() functions. */
206 : : #undef exp
207 : : #define exp expo
208 : : #undef remainder
209 : : #define remainder rem
210 : :
211 : : #if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && !WIDE_CHAR_VERSION
212 : : # if (HAVE_STRNLEN && !defined _AIX)
213 : : # define local_strnlen strnlen
214 : : # else
215 : : # ifndef local_strnlen_defined
216 : : # define local_strnlen_defined 1
217 : : static size_t
218 : : local_strnlen (const char *string, size_t maxlen)
219 : : {
220 : : const char *end = memchr (string, '\0', maxlen);
221 : : return end ? (size_t) (end - string) : maxlen;
222 : : }
223 : : # endif
224 : : # endif
225 : : #endif
226 : :
227 : : #if (((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && WIDE_CHAR_VERSION) || ((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && !WIDE_CHAR_VERSION && DCHAR_IS_TCHAR)) && HAVE_WCHAR_T
228 : : # if HAVE_WCSLEN
229 : : # define local_wcslen wcslen
230 : : # else
231 : : /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid
232 : : a dependency towards this library, here is a local substitute.
233 : : Define this substitute only once, even if this file is included
234 : : twice in the same compilation unit. */
235 : : # ifndef local_wcslen_defined
236 : : # define local_wcslen_defined 1
237 : : static size_t
238 : : local_wcslen (const wchar_t *s)
239 : : {
240 : : const wchar_t *ptr;
241 : :
242 : : for (ptr = s; *ptr != (wchar_t) 0; ptr++)
243 : : ;
244 : : return ptr - s;
245 : : }
246 : : # endif
247 : : # endif
248 : : #endif
249 : :
250 : : #if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && HAVE_WCHAR_T && WIDE_CHAR_VERSION
251 : : # if HAVE_WCSNLEN
252 : : # define local_wcsnlen wcsnlen
253 : : # else
254 : : # ifndef local_wcsnlen_defined
255 : : # define local_wcsnlen_defined 1
256 : : static size_t
257 : : local_wcsnlen (const wchar_t *s, size_t maxlen)
258 : : {
259 : : const wchar_t *ptr;
260 : :
261 : : for (ptr = s; maxlen > 0 && *ptr != (wchar_t) 0; ptr++, maxlen--)
262 : : ;
263 : : return ptr - s;
264 : : }
265 : : # endif
266 : : # endif
267 : : #endif
268 : :
269 : : #if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL
270 : : /* Determine the decimal-point character according to the current locale. */
271 : : # ifndef decimal_point_char_defined
272 : : # define decimal_point_char_defined 1
273 : : static char
274 : : decimal_point_char (void)
275 : : {
276 : : const char *point;
277 : : /* Determine it in a multithread-safe way. We know nl_langinfo is
278 : : multithread-safe on glibc systems and MacOS X systems, but is not required
279 : : to be multithread-safe by POSIX. sprintf(), however, is multithread-safe.
280 : : localeconv() is rarely multithread-safe. */
281 : : # if HAVE_NL_LANGINFO && (__GLIBC__ || defined __UCLIBC__ || (defined __APPLE__ && defined __MACH__))
282 : : point = nl_langinfo (RADIXCHAR);
283 : : # elif 1
284 : : char pointbuf[5];
285 : : sprintf (pointbuf, "%#.0f", 1.0);
286 : : point = &pointbuf[1];
287 : : # else
288 : : point = localeconv () -> decimal_point;
289 : : # endif
290 : : /* The decimal point is always a single byte: either '.' or ','. */
291 : : return (point[0] != '\0' ? point[0] : '.');
292 : : }
293 : : # endif
294 : : #endif
295 : :
296 : : #if NEED_PRINTF_INFINITE_DOUBLE && !NEED_PRINTF_DOUBLE && !defined IN_LIBINTL
297 : :
298 : : /* Equivalent to !isfinite(x) || x == 0, but does not require libm. */
299 : : static int
300 : : is_infinite_or_zero (double x)
301 : : {
302 : : return isnand (x) || x + x == x;
303 : : }
304 : :
305 : : #endif
306 : :
307 : : #if NEED_PRINTF_INFINITE_LONG_DOUBLE && !NEED_PRINTF_LONG_DOUBLE && !defined IN_LIBINTL
308 : :
309 : : /* Equivalent to !isfinite(x) || x == 0, but does not require libm. */
310 : : static int
311 : : is_infinite_or_zerol (long double x)
312 : : {
313 : : return isnanl (x) || x + x == x;
314 : : }
315 : :
316 : : #endif
317 : :
318 : : #if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL
319 : :
320 : : /* Converting 'long double' to decimal without rare rounding bugs requires
321 : : real bignums. We use the naming conventions of GNU gmp, but vastly simpler
322 : : (and slower) algorithms. */
323 : :
324 : : typedef unsigned int mp_limb_t;
325 : : # define GMP_LIMB_BITS 32
326 : : verify (sizeof (mp_limb_t) * CHAR_BIT == GMP_LIMB_BITS);
327 : :
328 : : typedef unsigned long long mp_twolimb_t;
329 : : # define GMP_TWOLIMB_BITS 64
330 : : verify (sizeof (mp_twolimb_t) * CHAR_BIT == GMP_TWOLIMB_BITS);
331 : :
332 : : /* Representation of a bignum >= 0. */
333 : : typedef struct
334 : : {
335 : : size_t nlimbs;
336 : : mp_limb_t *limbs; /* Bits in little-endian order, allocated with malloc(). */
337 : : } mpn_t;
338 : :
339 : : /* Compute the product of two bignums >= 0.
340 : : Return the allocated memory in case of success, NULL in case of memory
341 : : allocation failure. */
342 : : static void *
343 : : multiply (mpn_t src1, mpn_t src2, mpn_t *dest)
344 : : {
345 : : const mp_limb_t *p1;
346 : : const mp_limb_t *p2;
347 : : size_t len1;
348 : : size_t len2;
349 : :
350 : : if (src1.nlimbs <= src2.nlimbs)
351 : : {
352 : : len1 = src1.nlimbs;
353 : : p1 = src1.limbs;
354 : : len2 = src2.nlimbs;
355 : : p2 = src2.limbs;
356 : : }
357 : : else
358 : : {
359 : : len1 = src2.nlimbs;
360 : : p1 = src2.limbs;
361 : : len2 = src1.nlimbs;
362 : : p2 = src1.limbs;
363 : : }
364 : : /* Now 0 <= len1 <= len2. */
365 : : if (len1 == 0)
366 : : {
367 : : /* src1 or src2 is zero. */
368 : : dest->nlimbs = 0;
369 : : dest->limbs = (mp_limb_t *) malloc (1);
370 : : }
371 : : else
372 : : {
373 : : /* Here 1 <= len1 <= len2. */
374 : : size_t dlen;
375 : : mp_limb_t *dp;
376 : : size_t k, i, j;
377 : :
378 : : dlen = len1 + len2;
379 : : dp = (mp_limb_t *) malloc (dlen * sizeof (mp_limb_t));
380 : : if (dp == NULL)
381 : : return NULL;
382 : : for (k = len2; k > 0; )
383 : : dp[--k] = 0;
384 : : for (i = 0; i < len1; i++)
385 : : {
386 : : mp_limb_t digit1 = p1[i];
387 : : mp_twolimb_t carry = 0;
388 : : for (j = 0; j < len2; j++)
389 : : {
390 : : mp_limb_t digit2 = p2[j];
391 : : carry += (mp_twolimb_t) digit1 * (mp_twolimb_t) digit2;
392 : : carry += dp[i + j];
393 : : dp[i + j] = (mp_limb_t) carry;
394 : : carry = carry >> GMP_LIMB_BITS;
395 : : }
396 : : dp[i + len2] = (mp_limb_t) carry;
397 : : }
398 : : /* Normalise. */
399 : : while (dlen > 0 && dp[dlen - 1] == 0)
400 : : dlen--;
401 : : dest->nlimbs = dlen;
402 : : dest->limbs = dp;
403 : : }
404 : : return dest->limbs;
405 : : }
406 : :
407 : : /* Compute the quotient of a bignum a >= 0 and a bignum b > 0.
408 : : a is written as a = q * b + r with 0 <= r < b. q is the quotient, r
409 : : the remainder.
410 : : Finally, round-to-even is performed: If r > b/2 or if r = b/2 and q is odd,
411 : : q is incremented.
412 : : Return the allocated memory in case of success, NULL in case of memory
413 : : allocation failure. */
414 : : static void *
415 : : divide (mpn_t a, mpn_t b, mpn_t *q)
416 : : {
417 : : /* Algorithm:
418 : : First normalise a and b: a=[a[m-1],...,a[0]], b=[b[n-1],...,b[0]]
419 : : with m>=0 and n>0 (in base beta = 2^GMP_LIMB_BITS).
420 : : If m<n, then q:=0 and r:=a.
421 : : If m>=n=1, perform a single-precision division:
422 : : r:=0, j:=m,
423 : : while j>0 do
424 : : {Here (q[m-1]*beta^(m-1)+...+q[j]*beta^j) * b[0] + r*beta^j =
425 : : = a[m-1]*beta^(m-1)+...+a[j]*beta^j und 0<=r<b[0]<beta}
426 : : j:=j-1, r:=r*beta+a[j], q[j]:=floor(r/b[0]), r:=r-b[0]*q[j].
427 : : Normalise [q[m-1],...,q[0]], yields q.
428 : : If m>=n>1, perform a multiple-precision division:
429 : : We have a/b < beta^(m-n+1).
430 : : s:=intDsize-1-(highest bit in b[n-1]), 0<=s<intDsize.
431 : : Shift a and b left by s bits, copying them. r:=a.
432 : : r=[r[m],...,r[0]], b=[b[n-1],...,b[0]] with b[n-1]>=beta/2.
433 : : For j=m-n,...,0: {Here 0 <= r < b*beta^(j+1).}
434 : : Compute q* :
435 : : q* := floor((r[j+n]*beta+r[j+n-1])/b[n-1]).
436 : : In case of overflow (q* >= beta) set q* := beta-1.
437 : : Compute c2 := ((r[j+n]*beta+r[j+n-1]) - q* * b[n-1])*beta + r[j+n-2]
438 : : and c3 := b[n-2] * q*.
439 : : {We have 0 <= c2 < 2*beta^2, even 0 <= c2 < beta^2 if no overflow
440 : : occurred. Furthermore 0 <= c3 < beta^2.
441 : : If there was overflow and
442 : : r[j+n]*beta+r[j+n-1] - q* * b[n-1] >= beta, i.e. c2 >= beta^2,
443 : : the next test can be skipped.}
444 : : While c3 > c2, {Here 0 <= c2 < c3 < beta^2}
445 : : Put q* := q* - 1, c2 := c2 + b[n-1]*beta, c3 := c3 - b[n-2].
446 : : If q* > 0:
447 : : Put r := r - b * q* * beta^j. In detail:
448 : : [r[n+j],...,r[j]] := [r[n+j],...,r[j]] - q* * [b[n-1],...,b[0]].
449 : : hence: u:=0, for i:=0 to n-1 do
450 : : u := u + q* * b[i],
451 : : r[j+i]:=r[j+i]-(u mod beta) (+ beta, if carry),
452 : : u:=u div beta (+ 1, if carry in subtraction)
453 : : r[n+j]:=r[n+j]-u.
454 : : {Since always u = (q* * [b[i-1],...,b[0]] div beta^i) + 1
455 : : < q* + 1 <= beta,
456 : : the carry u does not overflow.}
457 : : If a negative carry occurs, put q* := q* - 1
458 : : and [r[n+j],...,r[j]] := [r[n+j],...,r[j]] + [0,b[n-1],...,b[0]].
459 : : Set q[j] := q*.
460 : : Normalise [q[m-n],..,q[0]]; this yields the quotient q.
461 : : Shift [r[n-1],...,r[0]] right by s bits and normalise; this yields the
462 : : rest r.
463 : : The room for q[j] can be allocated at the memory location of r[n+j].
464 : : Finally, round-to-even:
465 : : Shift r left by 1 bit.
466 : : If r > b or if r = b and q[0] is odd, q := q+1.
467 : : */
468 : : const mp_limb_t *a_ptr = a.limbs;
469 : : size_t a_len = a.nlimbs;
470 : : const mp_limb_t *b_ptr = b.limbs;
471 : : size_t b_len = b.nlimbs;
472 : : mp_limb_t *roomptr;
473 : : mp_limb_t *tmp_roomptr = NULL;
474 : : mp_limb_t *q_ptr;
475 : : size_t q_len;
476 : : mp_limb_t *r_ptr;
477 : : size_t r_len;
478 : :
479 : : /* Allocate room for a_len+2 digits.
480 : : (Need a_len+1 digits for the real division and 1 more digit for the
481 : : final rounding of q.) */
482 : : roomptr = (mp_limb_t *) malloc ((a_len + 2) * sizeof (mp_limb_t));
483 : : if (roomptr == NULL)
484 : : return NULL;
485 : :
486 : : /* Normalise a. */
487 : : while (a_len > 0 && a_ptr[a_len - 1] == 0)
488 : : a_len--;
489 : :
490 : : /* Normalise b. */
491 : : for (;;)
492 : : {
493 : : if (b_len == 0)
494 : : /* Division by zero. */
495 : : abort ();
496 : : if (b_ptr[b_len - 1] == 0)
497 : : b_len--;
498 : : else
499 : : break;
500 : : }
501 : :
502 : : /* Here m = a_len >= 0 and n = b_len > 0. */
503 : :
504 : : if (a_len < b_len)
505 : : {
506 : : /* m<n: trivial case. q=0, r := copy of a. */
507 : : r_ptr = roomptr;
508 : : r_len = a_len;
509 : : memcpy (r_ptr, a_ptr, a_len * sizeof (mp_limb_t));
510 : : q_ptr = roomptr + a_len;
511 : : q_len = 0;
512 : : }
513 : : else if (b_len == 1)
514 : : {
515 : : /* n=1: single precision division.
516 : : beta^(m-1) <= a < beta^m ==> beta^(m-2) <= a/b < beta^m */
517 : : r_ptr = roomptr;
518 : : q_ptr = roomptr + 1;
519 : : {
520 : : mp_limb_t den = b_ptr[0];
521 : : mp_limb_t remainder = 0;
522 : : const mp_limb_t *sourceptr = a_ptr + a_len;
523 : : mp_limb_t *destptr = q_ptr + a_len;
524 : : size_t count;
525 : : for (count = a_len; count > 0; count--)
526 : : {
527 : : mp_twolimb_t num =
528 : : ((mp_twolimb_t) remainder << GMP_LIMB_BITS) | *--sourceptr;
529 : : *--destptr = num / den;
530 : : remainder = num % den;
531 : : }
532 : : /* Normalise and store r. */
533 : : if (remainder > 0)
534 : : {
535 : : r_ptr[0] = remainder;
536 : : r_len = 1;
537 : : }
538 : : else
539 : : r_len = 0;
540 : : /* Normalise q. */
541 : : q_len = a_len;
542 : : if (q_ptr[q_len - 1] == 0)
543 : : q_len--;
544 : : }
545 : : }
546 : : else
547 : : {
548 : : /* n>1: multiple precision division.
549 : : beta^(m-1) <= a < beta^m, beta^(n-1) <= b < beta^n ==>
550 : : beta^(m-n-1) <= a/b < beta^(m-n+1). */
551 : : /* Determine s. */
552 : : size_t s;
553 : : {
554 : : mp_limb_t msd = b_ptr[b_len - 1]; /* = b[n-1], > 0 */
555 : : /* Determine s = GMP_LIMB_BITS - integer_length (msd).
556 : : Code copied from gnulib's integer_length.c. */
557 : : # if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
558 : : s = __builtin_clz (msd);
559 : : # else
560 : : # if defined DBL_EXPBIT0_WORD && defined DBL_EXPBIT0_BIT
561 : : if (GMP_LIMB_BITS <= DBL_MANT_BIT)
562 : : {
563 : : /* Use 'double' operations.
564 : : Assumes an IEEE 754 'double' implementation. */
565 : : # define DBL_EXP_MASK ((DBL_MAX_EXP - DBL_MIN_EXP) | 7)
566 : : # define DBL_EXP_BIAS (DBL_EXP_MASK / 2 - 1)
567 : : # define NWORDS \
568 : : ((sizeof (double) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
569 : : union { double value; unsigned int word[NWORDS]; } m;
570 : :
571 : : /* Use a single integer to floating-point conversion. */
572 : : m.value = msd;
573 : :
574 : : s = GMP_LIMB_BITS
575 : : - (((m.word[DBL_EXPBIT0_WORD] >> DBL_EXPBIT0_BIT) & DBL_EXP_MASK)
576 : : - DBL_EXP_BIAS);
577 : : }
578 : : else
579 : : # undef NWORDS
580 : : # endif
581 : : {
582 : : s = 31;
583 : : if (msd >= 0x10000)
584 : : {
585 : : msd = msd >> 16;
586 : : s -= 16;
587 : : }
588 : : if (msd >= 0x100)
589 : : {
590 : : msd = msd >> 8;
591 : : s -= 8;
592 : : }
593 : : if (msd >= 0x10)
594 : : {
595 : : msd = msd >> 4;
596 : : s -= 4;
597 : : }
598 : : if (msd >= 0x4)
599 : : {
600 : : msd = msd >> 2;
601 : : s -= 2;
602 : : }
603 : : if (msd >= 0x2)
604 : : {
605 : : msd = msd >> 1;
606 : : s -= 1;
607 : : }
608 : : }
609 : : # endif
610 : : }
611 : : /* 0 <= s < GMP_LIMB_BITS.
612 : : Copy b, shifting it left by s bits. */
613 : : if (s > 0)
614 : : {
615 : : tmp_roomptr = (mp_limb_t *) malloc (b_len * sizeof (mp_limb_t));
616 : : if (tmp_roomptr == NULL)
617 : : {
618 : : free (roomptr);
619 : : return NULL;
620 : : }
621 : : {
622 : : const mp_limb_t *sourceptr = b_ptr;
623 : : mp_limb_t *destptr = tmp_roomptr;
624 : : mp_twolimb_t accu = 0;
625 : : size_t count;
626 : : for (count = b_len; count > 0; count--)
627 : : {
628 : : accu += (mp_twolimb_t) *sourceptr++ << s;
629 : : *destptr++ = (mp_limb_t) accu;
630 : : accu = accu >> GMP_LIMB_BITS;
631 : : }
632 : : /* accu must be zero, since that was how s was determined. */
633 : : if (accu != 0)
634 : : abort ();
635 : : }
636 : : b_ptr = tmp_roomptr;
637 : : }
638 : : /* Copy a, shifting it left by s bits, yields r.
639 : : Memory layout:
640 : : At the beginning: r = roomptr[0..a_len],
641 : : at the end: r = roomptr[0..b_len-1], q = roomptr[b_len..a_len] */
642 : : r_ptr = roomptr;
643 : : if (s == 0)
644 : : {
645 : : memcpy (r_ptr, a_ptr, a_len * sizeof (mp_limb_t));
646 : : r_ptr[a_len] = 0;
647 : : }
648 : : else
649 : : {
650 : : const mp_limb_t *sourceptr = a_ptr;
651 : : mp_limb_t *destptr = r_ptr;
652 : : mp_twolimb_t accu = 0;
653 : : size_t count;
654 : : for (count = a_len; count > 0; count--)
655 : : {
656 : : accu += (mp_twolimb_t) *sourceptr++ << s;
657 : : *destptr++ = (mp_limb_t) accu;
658 : : accu = accu >> GMP_LIMB_BITS;
659 : : }
660 : : *destptr++ = (mp_limb_t) accu;
661 : : }
662 : : q_ptr = roomptr + b_len;
663 : : q_len = a_len - b_len + 1; /* q will have m-n+1 limbs */
664 : : {
665 : : size_t j = a_len - b_len; /* m-n */
666 : : mp_limb_t b_msd = b_ptr[b_len - 1]; /* b[n-1] */
667 : : mp_limb_t b_2msd = b_ptr[b_len - 2]; /* b[n-2] */
668 : : mp_twolimb_t b_msdd = /* b[n-1]*beta+b[n-2] */
669 : : ((mp_twolimb_t) b_msd << GMP_LIMB_BITS) | b_2msd;
670 : : /* Division loop, traversed m-n+1 times.
671 : : j counts down, b is unchanged, beta/2 <= b[n-1] < beta. */
672 : : for (;;)
673 : : {
674 : : mp_limb_t q_star;
675 : : mp_limb_t c1;
676 : : if (r_ptr[j + b_len] < b_msd) /* r[j+n] < b[n-1] ? */
677 : : {
678 : : /* Divide r[j+n]*beta+r[j+n-1] by b[n-1], no overflow. */
679 : : mp_twolimb_t num =
680 : : ((mp_twolimb_t) r_ptr[j + b_len] << GMP_LIMB_BITS)
681 : : | r_ptr[j + b_len - 1];
682 : : q_star = num / b_msd;
683 : : c1 = num % b_msd;
684 : : }
685 : : else
686 : : {
687 : : /* Overflow, hence r[j+n]*beta+r[j+n-1] >= beta*b[n-1]. */
688 : : q_star = (mp_limb_t)~(mp_limb_t)0; /* q* = beta-1 */
689 : : /* Test whether r[j+n]*beta+r[j+n-1] - (beta-1)*b[n-1] >= beta
690 : : <==> r[j+n]*beta+r[j+n-1] + b[n-1] >= beta*b[n-1]+beta
691 : : <==> b[n-1] < floor((r[j+n]*beta+r[j+n-1]+b[n-1])/beta)
692 : : {<= beta !}.
693 : : If yes, jump directly to the subtraction loop.
694 : : (Otherwise, r[j+n]*beta+r[j+n-1] - (beta-1)*b[n-1] < beta
695 : : <==> floor((r[j+n]*beta+r[j+n-1]+b[n-1])/beta) = b[n-1] ) */
696 : : if (r_ptr[j + b_len] > b_msd
697 : : || (c1 = r_ptr[j + b_len - 1] + b_msd) < b_msd)
698 : : /* r[j+n] >= b[n-1]+1 or
699 : : r[j+n] = b[n-1] and the addition r[j+n-1]+b[n-1] gives a
700 : : carry. */
701 : : goto subtract;
702 : : }
703 : : /* q_star = q*,
704 : : c1 = (r[j+n]*beta+r[j+n-1]) - q* * b[n-1] (>=0, <beta). */
705 : : {
706 : : mp_twolimb_t c2 = /* c1*beta+r[j+n-2] */
707 : : ((mp_twolimb_t) c1 << GMP_LIMB_BITS) | r_ptr[j + b_len - 2];
708 : : mp_twolimb_t c3 = /* b[n-2] * q* */
709 : : (mp_twolimb_t) b_2msd * (mp_twolimb_t) q_star;
710 : : /* While c2 < c3, increase c2 and decrease c3.
711 : : Consider c3-c2. While it is > 0, decrease it by
712 : : b[n-1]*beta+b[n-2]. Because of b[n-1]*beta+b[n-2] >= beta^2/2
713 : : this can happen only twice. */
714 : : if (c3 > c2)
715 : : {
716 : : q_star = q_star - 1; /* q* := q* - 1 */
717 : : if (c3 - c2 > b_msdd)
718 : : q_star = q_star - 1; /* q* := q* - 1 */
719 : : }
720 : : }
721 : : if (q_star > 0)
722 : : subtract:
723 : : {
724 : : /* Subtract r := r - b * q* * beta^j. */
725 : : mp_limb_t cr;
726 : : {
727 : : const mp_limb_t *sourceptr = b_ptr;
728 : : mp_limb_t *destptr = r_ptr + j;
729 : : mp_twolimb_t carry = 0;
730 : : size_t count;
731 : : for (count = b_len; count > 0; count--)
732 : : {
733 : : /* Here 0 <= carry <= q*. */
734 : : carry =
735 : : carry
736 : : + (mp_twolimb_t) q_star * (mp_twolimb_t) *sourceptr++
737 : : + (mp_limb_t) ~(*destptr);
738 : : /* Here 0 <= carry <= beta*q* + beta-1. */
739 : : *destptr++ = ~(mp_limb_t) carry;
740 : : carry = carry >> GMP_LIMB_BITS; /* <= q* */
741 : : }
742 : : cr = (mp_limb_t) carry;
743 : : }
744 : : /* Subtract cr from r_ptr[j + b_len], then forget about
745 : : r_ptr[j + b_len]. */
746 : : if (cr > r_ptr[j + b_len])
747 : : {
748 : : /* Subtraction gave a carry. */
749 : : q_star = q_star - 1; /* q* := q* - 1 */
750 : : /* Add b back. */
751 : : {
752 : : const mp_limb_t *sourceptr = b_ptr;
753 : : mp_limb_t *destptr = r_ptr + j;
754 : : mp_limb_t carry = 0;
755 : : size_t count;
756 : : for (count = b_len; count > 0; count--)
757 : : {
758 : : mp_limb_t source1 = *sourceptr++;
759 : : mp_limb_t source2 = *destptr;
760 : : *destptr++ = source1 + source2 + carry;
761 : : carry =
762 : : (carry
763 : : ? source1 >= (mp_limb_t) ~source2
764 : : : source1 > (mp_limb_t) ~source2);
765 : : }
766 : : }
767 : : /* Forget about the carry and about r[j+n]. */
768 : : }
769 : : }
770 : : /* q* is determined. Store it as q[j]. */
771 : : q_ptr[j] = q_star;
772 : : if (j == 0)
773 : : break;
774 : : j--;
775 : : }
776 : : }
777 : : r_len = b_len;
778 : : /* Normalise q. */
779 : : if (q_ptr[q_len - 1] == 0)
780 : : q_len--;
781 : : # if 0 /* Not needed here, since we need r only to compare it with b/2, and
782 : : b is shifted left by s bits. */
783 : : /* Shift r right by s bits. */
784 : : if (s > 0)
785 : : {
786 : : mp_limb_t ptr = r_ptr + r_len;
787 : : mp_twolimb_t accu = 0;
788 : : size_t count;
789 : : for (count = r_len; count > 0; count--)
790 : : {
791 : : accu = (mp_twolimb_t) (mp_limb_t) accu << GMP_LIMB_BITS;
792 : : accu += (mp_twolimb_t) *--ptr << (GMP_LIMB_BITS - s);
793 : : *ptr = (mp_limb_t) (accu >> GMP_LIMB_BITS);
794 : : }
795 : : }
796 : : # endif
797 : : /* Normalise r. */
798 : : while (r_len > 0 && r_ptr[r_len - 1] == 0)
799 : : r_len--;
800 : : }
801 : : /* Compare r << 1 with b. */
802 : : if (r_len > b_len)
803 : : goto increment_q;
804 : : {
805 : : size_t i;
806 : : for (i = b_len;;)
807 : : {
808 : : mp_limb_t r_i =
809 : : (i <= r_len && i > 0 ? r_ptr[i - 1] >> (GMP_LIMB_BITS - 1) : 0)
810 : : | (i < r_len ? r_ptr[i] << 1 : 0);
811 : : mp_limb_t b_i = (i < b_len ? b_ptr[i] : 0);
812 : : if (r_i > b_i)
813 : : goto increment_q;
814 : : if (r_i < b_i)
815 : : goto keep_q;
816 : : if (i == 0)
817 : : break;
818 : : i--;
819 : : }
820 : : }
821 : : if (q_len > 0 && ((q_ptr[0] & 1) != 0))
822 : : /* q is odd. */
823 : : increment_q:
824 : : {
825 : : size_t i;
826 : : for (i = 0; i < q_len; i++)
827 : : if (++(q_ptr[i]) != 0)
828 : : goto keep_q;
829 : : q_ptr[q_len++] = 1;
830 : : }
831 : : keep_q:
832 : : if (tmp_roomptr != NULL)
833 : : free (tmp_roomptr);
834 : : q->limbs = q_ptr;
835 : : q->nlimbs = q_len;
836 : : return roomptr;
837 : : }
838 : :
839 : : /* Convert a bignum a >= 0, multiplied with 10^extra_zeroes, to decimal
840 : : representation.
841 : : Destroys the contents of a.
842 : : Return the allocated memory - containing the decimal digits in low-to-high
843 : : order, terminated with a NUL character - in case of success, NULL in case
844 : : of memory allocation failure. */
845 : : static char *
846 : : convert_to_decimal (mpn_t a, size_t extra_zeroes)
847 : : {
848 : : mp_limb_t *a_ptr = a.limbs;
849 : : size_t a_len = a.nlimbs;
850 : : /* 0.03345 is slightly larger than log(2)/(9*log(10)). */
851 : : size_t c_len = 9 * ((size_t)(a_len * (GMP_LIMB_BITS * 0.03345f)) + 1);
852 : : char *c_ptr = (char *) malloc (xsum (c_len, extra_zeroes));
853 : : if (c_ptr != NULL)
854 : : {
855 : : char *d_ptr = c_ptr;
856 : : for (; extra_zeroes > 0; extra_zeroes--)
857 : : *d_ptr++ = '0';
858 : : while (a_len > 0)
859 : : {
860 : : /* Divide a by 10^9, in-place. */
861 : : mp_limb_t remainder = 0;
862 : : mp_limb_t *ptr = a_ptr + a_len;
863 : : size_t count;
864 : : for (count = a_len; count > 0; count--)
865 : : {
866 : : mp_twolimb_t num =
867 : : ((mp_twolimb_t) remainder << GMP_LIMB_BITS) | *--ptr;
868 : : *ptr = num / 1000000000;
869 : : remainder = num % 1000000000;
870 : : }
871 : : /* Store the remainder as 9 decimal digits. */
872 : : for (count = 9; count > 0; count--)
873 : : {
874 : : *d_ptr++ = '0' + (remainder % 10);
875 : : remainder = remainder / 10;
876 : : }
877 : : /* Normalize a. */
878 : : if (a_ptr[a_len - 1] == 0)
879 : : a_len--;
880 : : }
881 : : /* Remove leading zeroes. */
882 : : while (d_ptr > c_ptr && d_ptr[-1] == '0')
883 : : d_ptr--;
884 : : /* But keep at least one zero. */
885 : : if (d_ptr == c_ptr)
886 : : *d_ptr++ = '0';
887 : : /* Terminate the string. */
888 : : *d_ptr = '\0';
889 : : }
890 : : return c_ptr;
891 : : }
892 : :
893 : : # if NEED_PRINTF_LONG_DOUBLE
894 : :
895 : : /* Assuming x is finite and >= 0:
896 : : write x as x = 2^e * m, where m is a bignum.
897 : : Return the allocated memory in case of success, NULL in case of memory
898 : : allocation failure. */
899 : : static void *
900 : : decode_long_double (long double x, int *ep, mpn_t *mp)
901 : : {
902 : : mpn_t m;
903 : : int exp;
904 : : long double y;
905 : : size_t i;
906 : :
907 : : /* Allocate memory for result. */
908 : : m.nlimbs = (LDBL_MANT_BIT + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS;
909 : : m.limbs = (mp_limb_t *) malloc (m.nlimbs * sizeof (mp_limb_t));
910 : : if (m.limbs == NULL)
911 : : return NULL;
912 : : /* Split into exponential part and mantissa. */
913 : : y = frexpl (x, &exp);
914 : : if (!(y >= 0.0L && y < 1.0L))
915 : : abort ();
916 : : /* x = 2^exp * y = 2^(exp - LDBL_MANT_BIT) * (y * 2^LDBL_MANT_BIT), and the
917 : : latter is an integer. */
918 : : /* Convert the mantissa (y * 2^LDBL_MANT_BIT) to a sequence of limbs.
919 : : I'm not sure whether it's safe to cast a 'long double' value between
920 : : 2^31 and 2^32 to 'unsigned int', therefore play safe and cast only
921 : : 'long double' values between 0 and 2^16 (to 'unsigned int' or 'int',
922 : : doesn't matter). */
923 : : # if (LDBL_MANT_BIT % GMP_LIMB_BITS) != 0
924 : : # if (LDBL_MANT_BIT % GMP_LIMB_BITS) > GMP_LIMB_BITS / 2
925 : : {
926 : : mp_limb_t hi, lo;
927 : : y *= (mp_limb_t) 1 << (LDBL_MANT_BIT % (GMP_LIMB_BITS / 2));
928 : : hi = (int) y;
929 : : y -= hi;
930 : : if (!(y >= 0.0L && y < 1.0L))
931 : : abort ();
932 : : y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
933 : : lo = (int) y;
934 : : y -= lo;
935 : : if (!(y >= 0.0L && y < 1.0L))
936 : : abort ();
937 : : m.limbs[LDBL_MANT_BIT / GMP_LIMB_BITS] = (hi << (GMP_LIMB_BITS / 2)) | lo;
938 : : }
939 : : # else
940 : : {
941 : : mp_limb_t d;
942 : : y *= (mp_limb_t) 1 << (LDBL_MANT_BIT % GMP_LIMB_BITS);
943 : : d = (int) y;
944 : : y -= d;
945 : : if (!(y >= 0.0L && y < 1.0L))
946 : : abort ();
947 : : m.limbs[LDBL_MANT_BIT / GMP_LIMB_BITS] = d;
948 : : }
949 : : # endif
950 : : # endif
951 : : for (i = LDBL_MANT_BIT / GMP_LIMB_BITS; i > 0; )
952 : : {
953 : : mp_limb_t hi, lo;
954 : : y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
955 : : hi = (int) y;
956 : : y -= hi;
957 : : if (!(y >= 0.0L && y < 1.0L))
958 : : abort ();
959 : : y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
960 : : lo = (int) y;
961 : : y -= lo;
962 : : if (!(y >= 0.0L && y < 1.0L))
963 : : abort ();
964 : : m.limbs[--i] = (hi << (GMP_LIMB_BITS / 2)) | lo;
965 : : }
966 : : # if 0 /* On FreeBSD 6.1/x86, 'long double' numbers sometimes have excess
967 : : precision. */
968 : : if (!(y == 0.0L))
969 : : abort ();
970 : : # endif
971 : : /* Normalise. */
972 : : while (m.nlimbs > 0 && m.limbs[m.nlimbs - 1] == 0)
973 : : m.nlimbs--;
974 : : *mp = m;
975 : : *ep = exp - LDBL_MANT_BIT;
976 : : return m.limbs;
977 : : }
978 : :
979 : : # endif
980 : :
981 : : # if NEED_PRINTF_DOUBLE
982 : :
983 : : /* Assuming x is finite and >= 0:
984 : : write x as x = 2^e * m, where m is a bignum.
985 : : Return the allocated memory in case of success, NULL in case of memory
986 : : allocation failure. */
987 : : static void *
988 : : decode_double (double x, int *ep, mpn_t *mp)
989 : : {
990 : : mpn_t m;
991 : : int exp;
992 : : double y;
993 : : size_t i;
994 : :
995 : : /* Allocate memory for result. */
996 : : m.nlimbs = (DBL_MANT_BIT + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS;
997 : : m.limbs = (mp_limb_t *) malloc (m.nlimbs * sizeof (mp_limb_t));
998 : : if (m.limbs == NULL)
999 : : return NULL;
1000 : : /* Split into exponential part and mantissa. */
1001 : : y = frexp (x, &exp);
1002 : : if (!(y >= 0.0 && y < 1.0))
1003 : : abort ();
1004 : : /* x = 2^exp * y = 2^(exp - DBL_MANT_BIT) * (y * 2^DBL_MANT_BIT), and the
1005 : : latter is an integer. */
1006 : : /* Convert the mantissa (y * 2^DBL_MANT_BIT) to a sequence of limbs.
1007 : : I'm not sure whether it's safe to cast a 'double' value between
1008 : : 2^31 and 2^32 to 'unsigned int', therefore play safe and cast only
1009 : : 'double' values between 0 and 2^16 (to 'unsigned int' or 'int',
1010 : : doesn't matter). */
1011 : : # if (DBL_MANT_BIT % GMP_LIMB_BITS) != 0
1012 : : # if (DBL_MANT_BIT % GMP_LIMB_BITS) > GMP_LIMB_BITS / 2
1013 : : {
1014 : : mp_limb_t hi, lo;
1015 : : y *= (mp_limb_t) 1 << (DBL_MANT_BIT % (GMP_LIMB_BITS / 2));
1016 : : hi = (int) y;
1017 : : y -= hi;
1018 : : if (!(y >= 0.0 && y < 1.0))
1019 : : abort ();
1020 : : y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
1021 : : lo = (int) y;
1022 : : y -= lo;
1023 : : if (!(y >= 0.0 && y < 1.0))
1024 : : abort ();
1025 : : m.limbs[DBL_MANT_BIT / GMP_LIMB_BITS] = (hi << (GMP_LIMB_BITS / 2)) | lo;
1026 : : }
1027 : : # else
1028 : : {
1029 : : mp_limb_t d;
1030 : : y *= (mp_limb_t) 1 << (DBL_MANT_BIT % GMP_LIMB_BITS);
1031 : : d = (int) y;
1032 : : y -= d;
1033 : : if (!(y >= 0.0 && y < 1.0))
1034 : : abort ();
1035 : : m.limbs[DBL_MANT_BIT / GMP_LIMB_BITS] = d;
1036 : : }
1037 : : # endif
1038 : : # endif
1039 : : for (i = DBL_MANT_BIT / GMP_LIMB_BITS; i > 0; )
1040 : : {
1041 : : mp_limb_t hi, lo;
1042 : : y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
1043 : : hi = (int) y;
1044 : : y -= hi;
1045 : : if (!(y >= 0.0 && y < 1.0))
1046 : : abort ();
1047 : : y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
1048 : : lo = (int) y;
1049 : : y -= lo;
1050 : : if (!(y >= 0.0 && y < 1.0))
1051 : : abort ();
1052 : : m.limbs[--i] = (hi << (GMP_LIMB_BITS / 2)) | lo;
1053 : : }
1054 : : if (!(y == 0.0))
1055 : : abort ();
1056 : : /* Normalise. */
1057 : : while (m.nlimbs > 0 && m.limbs[m.nlimbs - 1] == 0)
1058 : : m.nlimbs--;
1059 : : *mp = m;
1060 : : *ep = exp - DBL_MANT_BIT;
1061 : : return m.limbs;
1062 : : }
1063 : :
1064 : : # endif
1065 : :
1066 : : /* Assuming x = 2^e * m is finite and >= 0, and n is an integer:
1067 : : Returns the decimal representation of round (x * 10^n).
1068 : : Return the allocated memory - containing the decimal digits in low-to-high
1069 : : order, terminated with a NUL character - in case of success, NULL in case
1070 : : of memory allocation failure. */
1071 : : static char *
1072 : : scale10_round_decimal_decoded (int e, mpn_t m, void *memory, int n)
1073 : : {
1074 : : int s;
1075 : : size_t extra_zeroes;
1076 : : unsigned int abs_n;
1077 : : unsigned int abs_s;
1078 : : mp_limb_t *pow5_ptr;
1079 : : size_t pow5_len;
1080 : : unsigned int s_limbs;
1081 : : unsigned int s_bits;
1082 : : mpn_t pow5;
1083 : : mpn_t z;
1084 : : void *z_memory;
1085 : : char *digits;
1086 : :
1087 : : if (memory == NULL)
1088 : : return NULL;
1089 : : /* x = 2^e * m, hence
1090 : : y = round (2^e * 10^n * m) = round (2^(e+n) * 5^n * m)
1091 : : = round (2^s * 5^n * m). */
1092 : : s = e + n;
1093 : : extra_zeroes = 0;
1094 : : /* Factor out a common power of 10 if possible. */
1095 : : if (s > 0 && n > 0)
1096 : : {
1097 : : extra_zeroes = (s < n ? s : n);
1098 : : s -= extra_zeroes;
1099 : : n -= extra_zeroes;
1100 : : }
1101 : : /* Here y = round (2^s * 5^n * m) * 10^extra_zeroes.
1102 : : Before converting to decimal, we need to compute
1103 : : z = round (2^s * 5^n * m). */
1104 : : /* Compute 5^|n|, possibly shifted by |s| bits if n and s have the same
1105 : : sign. 2.322 is slightly larger than log(5)/log(2). */
1106 : : abs_n = (n >= 0 ? n : -n);
1107 : : abs_s = (s >= 0 ? s : -s);
1108 : : pow5_ptr = (mp_limb_t *) malloc (((int)(abs_n * (2.322f / GMP_LIMB_BITS)) + 1
1109 : : + abs_s / GMP_LIMB_BITS + 1)
1110 : : * sizeof (mp_limb_t));
1111 : : if (pow5_ptr == NULL)
1112 : : {
1113 : : free (memory);
1114 : : return NULL;
1115 : : }
1116 : : /* Initialize with 1. */
1117 : : pow5_ptr[0] = 1;
1118 : : pow5_len = 1;
1119 : : /* Multiply with 5^|n|. */
1120 : : if (abs_n > 0)
1121 : : {
1122 : : static mp_limb_t const small_pow5[13 + 1] =
1123 : : {
1124 : : 1, 5, 25, 125, 625, 3125, 15625, 78125, 390625, 1953125, 9765625,
1125 : : 48828125, 244140625, 1220703125
1126 : : };
1127 : : unsigned int n13;
1128 : : for (n13 = 0; n13 <= abs_n; n13 += 13)
1129 : : {
1130 : : mp_limb_t digit1 = small_pow5[n13 + 13 <= abs_n ? 13 : abs_n - n13];
1131 : : size_t j;
1132 : : mp_twolimb_t carry = 0;
1133 : : for (j = 0; j < pow5_len; j++)
1134 : : {
1135 : : mp_limb_t digit2 = pow5_ptr[j];
1136 : : carry += (mp_twolimb_t) digit1 * (mp_twolimb_t) digit2;
1137 : : pow5_ptr[j] = (mp_limb_t) carry;
1138 : : carry = carry >> GMP_LIMB_BITS;
1139 : : }
1140 : : if (carry > 0)
1141 : : pow5_ptr[pow5_len++] = (mp_limb_t) carry;
1142 : : }
1143 : : }
1144 : : s_limbs = abs_s / GMP_LIMB_BITS;
1145 : : s_bits = abs_s % GMP_LIMB_BITS;
1146 : : if (n >= 0 ? s >= 0 : s <= 0)
1147 : : {
1148 : : /* Multiply with 2^|s|. */
1149 : : if (s_bits > 0)
1150 : : {
1151 : : mp_limb_t *ptr = pow5_ptr;
1152 : : mp_twolimb_t accu = 0;
1153 : : size_t count;
1154 : : for (count = pow5_len; count > 0; count--)
1155 : : {
1156 : : accu += (mp_twolimb_t) *ptr << s_bits;
1157 : : *ptr++ = (mp_limb_t) accu;
1158 : : accu = accu >> GMP_LIMB_BITS;
1159 : : }
1160 : : if (accu > 0)
1161 : : {
1162 : : *ptr = (mp_limb_t) accu;
1163 : : pow5_len++;
1164 : : }
1165 : : }
1166 : : if (s_limbs > 0)
1167 : : {
1168 : : size_t count;
1169 : : for (count = pow5_len; count > 0;)
1170 : : {
1171 : : count--;
1172 : : pow5_ptr[s_limbs + count] = pow5_ptr[count];
1173 : : }
1174 : : for (count = s_limbs; count > 0;)
1175 : : {
1176 : : count--;
1177 : : pow5_ptr[count] = 0;
1178 : : }
1179 : : pow5_len += s_limbs;
1180 : : }
1181 : : pow5.limbs = pow5_ptr;
1182 : : pow5.nlimbs = pow5_len;
1183 : : if (n >= 0)
1184 : : {
1185 : : /* Multiply m with pow5. No division needed. */
1186 : : z_memory = multiply (m, pow5, &z);
1187 : : }
1188 : : else
1189 : : {
1190 : : /* Divide m by pow5 and round. */
1191 : : z_memory = divide (m, pow5, &z);
1192 : : }
1193 : : }
1194 : : else
1195 : : {
1196 : : pow5.limbs = pow5_ptr;
1197 : : pow5.nlimbs = pow5_len;
1198 : : if (n >= 0)
1199 : : {
1200 : : /* n >= 0, s < 0.
1201 : : Multiply m with pow5, then divide by 2^|s|. */
1202 : : mpn_t numerator;
1203 : : mpn_t denominator;
1204 : : void *tmp_memory;
1205 : : tmp_memory = multiply (m, pow5, &numerator);
1206 : : if (tmp_memory == NULL)
1207 : : {
1208 : : free (pow5_ptr);
1209 : : free (memory);
1210 : : return NULL;
1211 : : }
1212 : : /* Construct 2^|s|. */
1213 : : {
1214 : : mp_limb_t *ptr = pow5_ptr + pow5_len;
1215 : : size_t i;
1216 : : for (i = 0; i < s_limbs; i++)
1217 : : ptr[i] = 0;
1218 : : ptr[s_limbs] = (mp_limb_t) 1 << s_bits;
1219 : : denominator.limbs = ptr;
1220 : : denominator.nlimbs = s_limbs + 1;
1221 : : }
1222 : : z_memory = divide (numerator, denominator, &z);
1223 : : free (tmp_memory);
1224 : : }
1225 : : else
1226 : : {
1227 : : /* n < 0, s > 0.
1228 : : Multiply m with 2^s, then divide by pow5. */
1229 : : mpn_t numerator;
1230 : : mp_limb_t *num_ptr;
1231 : : num_ptr = (mp_limb_t *) malloc ((m.nlimbs + s_limbs + 1)
1232 : : * sizeof (mp_limb_t));
1233 : : if (num_ptr == NULL)
1234 : : {
1235 : : free (pow5_ptr);
1236 : : free (memory);
1237 : : return NULL;
1238 : : }
1239 : : {
1240 : : mp_limb_t *destptr = num_ptr;
1241 : : {
1242 : : size_t i;
1243 : : for (i = 0; i < s_limbs; i++)
1244 : : *destptr++ = 0;
1245 : : }
1246 : : if (s_bits > 0)
1247 : : {
1248 : : const mp_limb_t *sourceptr = m.limbs;
1249 : : mp_twolimb_t accu = 0;
1250 : : size_t count;
1251 : : for (count = m.nlimbs; count > 0; count--)
1252 : : {
1253 : : accu += (mp_twolimb_t) *sourceptr++ << s_bits;
1254 : : *destptr++ = (mp_limb_t) accu;
1255 : : accu = accu >> GMP_LIMB_BITS;
1256 : : }
1257 : : if (accu > 0)
1258 : : *destptr++ = (mp_limb_t) accu;
1259 : : }
1260 : : else
1261 : : {
1262 : : const mp_limb_t *sourceptr = m.limbs;
1263 : : size_t count;
1264 : : for (count = m.nlimbs; count > 0; count--)
1265 : : *destptr++ = *sourceptr++;
1266 : : }
1267 : : numerator.limbs = num_ptr;
1268 : : numerator.nlimbs = destptr - num_ptr;
1269 : : }
1270 : : z_memory = divide (numerator, pow5, &z);
1271 : : free (num_ptr);
1272 : : }
1273 : : }
1274 : : free (pow5_ptr);
1275 : : free (memory);
1276 : :
1277 : : /* Here y = round (x * 10^n) = z * 10^extra_zeroes. */
1278 : :
1279 : : if (z_memory == NULL)
1280 : : return NULL;
1281 : : digits = convert_to_decimal (z, extra_zeroes);
1282 : : free (z_memory);
1283 : : return digits;
1284 : : }
1285 : :
1286 : : # if NEED_PRINTF_LONG_DOUBLE
1287 : :
1288 : : /* Assuming x is finite and >= 0, and n is an integer:
1289 : : Returns the decimal representation of round (x * 10^n).
1290 : : Return the allocated memory - containing the decimal digits in low-to-high
1291 : : order, terminated with a NUL character - in case of success, NULL in case
1292 : : of memory allocation failure. */
1293 : : static char *
1294 : : scale10_round_decimal_long_double (long double x, int n)
1295 : : {
1296 : : int e IF_LINT(= 0);
1297 : : mpn_t m;
1298 : : void *memory = decode_long_double (x, &e, &m);
1299 : : return scale10_round_decimal_decoded (e, m, memory, n);
1300 : : }
1301 : :
1302 : : # endif
1303 : :
1304 : : # if NEED_PRINTF_DOUBLE
1305 : :
1306 : : /* Assuming x is finite and >= 0, and n is an integer:
1307 : : Returns the decimal representation of round (x * 10^n).
1308 : : Return the allocated memory - containing the decimal digits in low-to-high
1309 : : order, terminated with a NUL character - in case of success, NULL in case
1310 : : of memory allocation failure. */
1311 : : static char *
1312 : : scale10_round_decimal_double (double x, int n)
1313 : : {
1314 : : int e IF_LINT(= 0);
1315 : : mpn_t m;
1316 : : void *memory = decode_double (x, &e, &m);
1317 : : return scale10_round_decimal_decoded (e, m, memory, n);
1318 : : }
1319 : :
1320 : : # endif
1321 : :
1322 : : # if NEED_PRINTF_LONG_DOUBLE
1323 : :
1324 : : /* Assuming x is finite and > 0:
1325 : : Return an approximation for n with 10^n <= x < 10^(n+1).
1326 : : The approximation is usually the right n, but may be off by 1 sometimes. */
1327 : : static int
1328 : : floorlog10l (long double x)
1329 : : {
1330 : : int exp;
1331 : : long double y;
1332 : : double z;
1333 : : double l;
1334 : :
1335 : : /* Split into exponential part and mantissa. */
1336 : : y = frexpl (x, &exp);
1337 : : if (!(y >= 0.0L && y < 1.0L))
1338 : : abort ();
1339 : : if (y == 0.0L)
1340 : : return INT_MIN;
1341 : : if (y < 0.5L)
1342 : : {
1343 : : while (y < (1.0L / (1 << (GMP_LIMB_BITS / 2)) / (1 << (GMP_LIMB_BITS / 2))))
1344 : : {
1345 : : y *= 1.0L * (1 << (GMP_LIMB_BITS / 2)) * (1 << (GMP_LIMB_BITS / 2));
1346 : : exp -= GMP_LIMB_BITS;
1347 : : }
1348 : : if (y < (1.0L / (1 << 16)))
1349 : : {
1350 : : y *= 1.0L * (1 << 16);
1351 : : exp -= 16;
1352 : : }
1353 : : if (y < (1.0L / (1 << 8)))
1354 : : {
1355 : : y *= 1.0L * (1 << 8);
1356 : : exp -= 8;
1357 : : }
1358 : : if (y < (1.0L / (1 << 4)))
1359 : : {
1360 : : y *= 1.0L * (1 << 4);
1361 : : exp -= 4;
1362 : : }
1363 : : if (y < (1.0L / (1 << 2)))
1364 : : {
1365 : : y *= 1.0L * (1 << 2);
1366 : : exp -= 2;
1367 : : }
1368 : : if (y < (1.0L / (1 << 1)))
1369 : : {
1370 : : y *= 1.0L * (1 << 1);
1371 : : exp -= 1;
1372 : : }
1373 : : }
1374 : : if (!(y >= 0.5L && y < 1.0L))
1375 : : abort ();
1376 : : /* Compute an approximation for l = log2(x) = exp + log2(y). */
1377 : : l = exp;
1378 : : z = y;
1379 : : if (z < 0.70710678118654752444)
1380 : : {
1381 : : z *= 1.4142135623730950488;
1382 : : l -= 0.5;
1383 : : }
1384 : : if (z < 0.8408964152537145431)
1385 : : {
1386 : : z *= 1.1892071150027210667;
1387 : : l -= 0.25;
1388 : : }
1389 : : if (z < 0.91700404320467123175)
1390 : : {
1391 : : z *= 1.0905077326652576592;
1392 : : l -= 0.125;
1393 : : }
1394 : : if (z < 0.9576032806985736469)
1395 : : {
1396 : : z *= 1.0442737824274138403;
1397 : : l -= 0.0625;
1398 : : }
1399 : : /* Now 0.95 <= z <= 1.01. */
1400 : : z = 1 - z;
1401 : : /* log2(1-z) = 1/log(2) * (- z - z^2/2 - z^3/3 - z^4/4 - ...)
1402 : : Four terms are enough to get an approximation with error < 10^-7. */
1403 : : l -= 1.4426950408889634074 * z * (1.0 + z * (0.5 + z * ((1.0 / 3) + z * 0.25)));
1404 : : /* Finally multiply with log(2)/log(10), yields an approximation for
1405 : : log10(x). */
1406 : : l *= 0.30102999566398119523;
1407 : : /* Round down to the next integer. */
1408 : : return (int) l + (l < 0 ? -1 : 0);
1409 : : }
1410 : :
1411 : : # endif
1412 : :
1413 : : # if NEED_PRINTF_DOUBLE
1414 : :
1415 : : /* Assuming x is finite and > 0:
1416 : : Return an approximation for n with 10^n <= x < 10^(n+1).
1417 : : The approximation is usually the right n, but may be off by 1 sometimes. */
1418 : : static int
1419 : : floorlog10 (double x)
1420 : : {
1421 : : int exp;
1422 : : double y;
1423 : : double z;
1424 : : double l;
1425 : :
1426 : : /* Split into exponential part and mantissa. */
1427 : : y = frexp (x, &exp);
1428 : : if (!(y >= 0.0 && y < 1.0))
1429 : : abort ();
1430 : : if (y == 0.0)
1431 : : return INT_MIN;
1432 : : if (y < 0.5)
1433 : : {
1434 : : while (y < (1.0 / (1 << (GMP_LIMB_BITS / 2)) / (1 << (GMP_LIMB_BITS / 2))))
1435 : : {
1436 : : y *= 1.0 * (1 << (GMP_LIMB_BITS / 2)) * (1 << (GMP_LIMB_BITS / 2));
1437 : : exp -= GMP_LIMB_BITS;
1438 : : }
1439 : : if (y < (1.0 / (1 << 16)))
1440 : : {
1441 : : y *= 1.0 * (1 << 16);
1442 : : exp -= 16;
1443 : : }
1444 : : if (y < (1.0 / (1 << 8)))
1445 : : {
1446 : : y *= 1.0 * (1 << 8);
1447 : : exp -= 8;
1448 : : }
1449 : : if (y < (1.0 / (1 << 4)))
1450 : : {
1451 : : y *= 1.0 * (1 << 4);
1452 : : exp -= 4;
1453 : : }
1454 : : if (y < (1.0 / (1 << 2)))
1455 : : {
1456 : : y *= 1.0 * (1 << 2);
1457 : : exp -= 2;
1458 : : }
1459 : : if (y < (1.0 / (1 << 1)))
1460 : : {
1461 : : y *= 1.0 * (1 << 1);
1462 : : exp -= 1;
1463 : : }
1464 : : }
1465 : : if (!(y >= 0.5 && y < 1.0))
1466 : : abort ();
1467 : : /* Compute an approximation for l = log2(x) = exp + log2(y). */
1468 : : l = exp;
1469 : : z = y;
1470 : : if (z < 0.70710678118654752444)
1471 : : {
1472 : : z *= 1.4142135623730950488;
1473 : : l -= 0.5;
1474 : : }
1475 : : if (z < 0.8408964152537145431)
1476 : : {
1477 : : z *= 1.1892071150027210667;
1478 : : l -= 0.25;
1479 : : }
1480 : : if (z < 0.91700404320467123175)
1481 : : {
1482 : : z *= 1.0905077326652576592;
1483 : : l -= 0.125;
1484 : : }
1485 : : if (z < 0.9576032806985736469)
1486 : : {
1487 : : z *= 1.0442737824274138403;
1488 : : l -= 0.0625;
1489 : : }
1490 : : /* Now 0.95 <= z <= 1.01. */
1491 : : z = 1 - z;
1492 : : /* log2(1-z) = 1/log(2) * (- z - z^2/2 - z^3/3 - z^4/4 - ...)
1493 : : Four terms are enough to get an approximation with error < 10^-7. */
1494 : : l -= 1.4426950408889634074 * z * (1.0 + z * (0.5 + z * ((1.0 / 3) + z * 0.25)));
1495 : : /* Finally multiply with log(2)/log(10), yields an approximation for
1496 : : log10(x). */
1497 : : l *= 0.30102999566398119523;
1498 : : /* Round down to the next integer. */
1499 : : return (int) l + (l < 0 ? -1 : 0);
1500 : : }
1501 : :
1502 : : # endif
1503 : :
1504 : : /* Tests whether a string of digits consists of exactly PRECISION zeroes and
1505 : : a single '1' digit. */
1506 : : static int
1507 : : is_borderline (const char *digits, size_t precision)
1508 : : {
1509 : : for (; precision > 0; precision--, digits++)
1510 : : if (*digits != '0')
1511 : : return 0;
1512 : : if (*digits != '1')
1513 : : return 0;
1514 : : digits++;
1515 : : return *digits == '\0';
1516 : : }
1517 : :
1518 : : #endif
1519 : :
1520 : : #if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99
1521 : :
1522 : : /* Use a different function name, to make it possible that the 'wchar_t'
1523 : : parametrization and the 'char' parametrization get compiled in the same
1524 : : translation unit. */
1525 : : # if WIDE_CHAR_VERSION
1526 : : # define MAX_ROOM_NEEDED wmax_room_needed
1527 : : # else
1528 : : # define MAX_ROOM_NEEDED max_room_needed
1529 : : # endif
1530 : :
1531 : : /* Returns the number of TCHAR_T units needed as temporary space for the result
1532 : : of sprintf or SNPRINTF of a single conversion directive. */
1533 : : static inline size_t
1534 : : MAX_ROOM_NEEDED (const arguments *ap, size_t arg_index, FCHAR_T conversion,
1535 : : arg_type type, int flags, size_t width, int has_precision,
1536 : : size_t precision, int pad_ourselves)
1537 : : {
1538 : : size_t tmp_length;
1539 : :
1540 : : switch (conversion)
1541 : : {
1542 : : case 'd': case 'i': case 'u':
1543 : : # if HAVE_LONG_LONG_INT
1544 : : if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
1545 : : tmp_length =
1546 : : (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
1547 : : * 0.30103 /* binary -> decimal */
1548 : : )
1549 : : + 1; /* turn floor into ceil */
1550 : : else
1551 : : # endif
1552 : : if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
1553 : : tmp_length =
1554 : : (unsigned int) (sizeof (unsigned long) * CHAR_BIT
1555 : : * 0.30103 /* binary -> decimal */
1556 : : )
1557 : : + 1; /* turn floor into ceil */
1558 : : else
1559 : : tmp_length =
1560 : : (unsigned int) (sizeof (unsigned int) * CHAR_BIT
1561 : : * 0.30103 /* binary -> decimal */
1562 : : )
1563 : : + 1; /* turn floor into ceil */
1564 : : if (tmp_length < precision)
1565 : : tmp_length = precision;
1566 : : /* Multiply by 2, as an estimate for FLAG_GROUP. */
1567 : : tmp_length = xsum (tmp_length, tmp_length);
1568 : : /* Add 1, to account for a leading sign. */
1569 : : tmp_length = xsum (tmp_length, 1);
1570 : : break;
1571 : :
1572 : : case 'o':
1573 : : # if HAVE_LONG_LONG_INT
1574 : : if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
1575 : : tmp_length =
1576 : : (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
1577 : : * 0.333334 /* binary -> octal */
1578 : : )
1579 : : + 1; /* turn floor into ceil */
1580 : : else
1581 : : # endif
1582 : : if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
1583 : : tmp_length =
1584 : : (unsigned int) (sizeof (unsigned long) * CHAR_BIT
1585 : : * 0.333334 /* binary -> octal */
1586 : : )
1587 : : + 1; /* turn floor into ceil */
1588 : : else
1589 : : tmp_length =
1590 : : (unsigned int) (sizeof (unsigned int) * CHAR_BIT
1591 : : * 0.333334 /* binary -> octal */
1592 : : )
1593 : : + 1; /* turn floor into ceil */
1594 : : if (tmp_length < precision)
1595 : : tmp_length = precision;
1596 : : /* Add 1, to account for a leading sign. */
1597 : : tmp_length = xsum (tmp_length, 1);
1598 : : break;
1599 : :
1600 : : case 'x': case 'X':
1601 : : # if HAVE_LONG_LONG_INT
1602 : : if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
1603 : : tmp_length =
1604 : : (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
1605 : : * 0.25 /* binary -> hexadecimal */
1606 : : )
1607 : : + 1; /* turn floor into ceil */
1608 : : else
1609 : : # endif
1610 : : if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
1611 : : tmp_length =
1612 : : (unsigned int) (sizeof (unsigned long) * CHAR_BIT
1613 : : * 0.25 /* binary -> hexadecimal */
1614 : : )
1615 : : + 1; /* turn floor into ceil */
1616 : : else
1617 : : tmp_length =
1618 : : (unsigned int) (sizeof (unsigned int) * CHAR_BIT
1619 : : * 0.25 /* binary -> hexadecimal */
1620 : : )
1621 : : + 1; /* turn floor into ceil */
1622 : : if (tmp_length < precision)
1623 : : tmp_length = precision;
1624 : : /* Add 2, to account for a leading sign or alternate form. */
1625 : : tmp_length = xsum (tmp_length, 2);
1626 : : break;
1627 : :
1628 : : case 'f': case 'F':
1629 : : if (type == TYPE_LONGDOUBLE)
1630 : : tmp_length =
1631 : : (unsigned int) (LDBL_MAX_EXP
1632 : : * 0.30103 /* binary -> decimal */
1633 : : * 2 /* estimate for FLAG_GROUP */
1634 : : )
1635 : : + 1 /* turn floor into ceil */
1636 : : + 10; /* sign, decimal point etc. */
1637 : : else
1638 : : tmp_length =
1639 : : (unsigned int) (DBL_MAX_EXP
1640 : : * 0.30103 /* binary -> decimal */
1641 : : * 2 /* estimate for FLAG_GROUP */
1642 : : )
1643 : : + 1 /* turn floor into ceil */
1644 : : + 10; /* sign, decimal point etc. */
1645 : : tmp_length = xsum (tmp_length, precision);
1646 : : break;
1647 : :
1648 : : case 'e': case 'E': case 'g': case 'G':
1649 : : tmp_length =
1650 : : 12; /* sign, decimal point, exponent etc. */
1651 : : tmp_length = xsum (tmp_length, precision);
1652 : : break;
1653 : :
1654 : : case 'a': case 'A':
1655 : : if (type == TYPE_LONGDOUBLE)
1656 : : tmp_length =
1657 : : (unsigned int) (LDBL_DIG
1658 : : * 0.831 /* decimal -> hexadecimal */
1659 : : )
1660 : : + 1; /* turn floor into ceil */
1661 : : else
1662 : : tmp_length =
1663 : : (unsigned int) (DBL_DIG
1664 : : * 0.831 /* decimal -> hexadecimal */
1665 : : )
1666 : : + 1; /* turn floor into ceil */
1667 : : if (tmp_length < precision)
1668 : : tmp_length = precision;
1669 : : /* Account for sign, decimal point etc. */
1670 : : tmp_length = xsum (tmp_length, 12);
1671 : : break;
1672 : :
1673 : : case 'c':
1674 : : # if HAVE_WINT_T && !WIDE_CHAR_VERSION
1675 : : if (type == TYPE_WIDE_CHAR)
1676 : : tmp_length = MB_CUR_MAX;
1677 : : else
1678 : : # endif
1679 : : tmp_length = 1;
1680 : : break;
1681 : :
1682 : : case 's':
1683 : : # if HAVE_WCHAR_T
1684 : : if (type == TYPE_WIDE_STRING)
1685 : : {
1686 : : # if WIDE_CHAR_VERSION
1687 : : /* ISO C says about %ls in fwprintf:
1688 : : "If the precision is not specified or is greater than the size
1689 : : of the array, the array shall contain a null wide character."
1690 : : So if there is a precision, we must not use wcslen. */
1691 : : const wchar_t *arg = ap->arg[arg_index].a.a_wide_string;
1692 : :
1693 : : if (has_precision)
1694 : : tmp_length = local_wcsnlen (arg, precision);
1695 : : else
1696 : : tmp_length = local_wcslen (arg);
1697 : : # else
1698 : : /* ISO C says about %ls in fprintf:
1699 : : "If a precision is specified, no more than that many bytes are
1700 : : written (including shift sequences, if any), and the array
1701 : : shall contain a null wide character if, to equal the multibyte
1702 : : character sequence length given by the precision, the function
1703 : : would need to access a wide character one past the end of the
1704 : : array."
1705 : : So if there is a precision, we must not use wcslen. */
1706 : : /* This case has already been handled separately in VASNPRINTF. */
1707 : : abort ();
1708 : : # endif
1709 : : }
1710 : : else
1711 : : # endif
1712 : : {
1713 : : # if WIDE_CHAR_VERSION
1714 : : /* ISO C says about %s in fwprintf:
1715 : : "If the precision is not specified or is greater than the size
1716 : : of the converted array, the converted array shall contain a
1717 : : null wide character."
1718 : : So if there is a precision, we must not use strlen. */
1719 : : /* This case has already been handled separately in VASNPRINTF. */
1720 : : abort ();
1721 : : # else
1722 : : /* ISO C says about %s in fprintf:
1723 : : "If the precision is not specified or greater than the size of
1724 : : the array, the array shall contain a null character."
1725 : : So if there is a precision, we must not use strlen. */
1726 : : const char *arg = ap->arg[arg_index].a.a_string;
1727 : :
1728 : : if (has_precision)
1729 : : tmp_length = local_strnlen (arg, precision);
1730 : : else
1731 : : tmp_length = strlen (arg);
1732 : : # endif
1733 : : }
1734 : : break;
1735 : :
1736 : : case 'p':
1737 : : tmp_length =
1738 : : (unsigned int) (sizeof (void *) * CHAR_BIT
1739 : : * 0.25 /* binary -> hexadecimal */
1740 : : )
1741 : : + 1 /* turn floor into ceil */
1742 : : + 2; /* account for leading 0x */
1743 : : break;
1744 : :
1745 : : default:
1746 : : abort ();
1747 : : }
1748 : :
1749 : : if (!pad_ourselves)
1750 : : {
1751 : : # if ENABLE_UNISTDIO
1752 : : /* Padding considers the number of characters, therefore the number of
1753 : : elements after padding may be
1754 : : > max (tmp_length, width)
1755 : : but is certainly
1756 : : <= tmp_length + width. */
1757 : : tmp_length = xsum (tmp_length, width);
1758 : : # else
1759 : : /* Padding considers the number of elements, says POSIX. */
1760 : : if (tmp_length < width)
1761 : : tmp_length = width;
1762 : : # endif
1763 : : }
1764 : :
1765 : : tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
1766 : :
1767 : : return tmp_length;
1768 : : }
1769 : :
1770 : : #endif
1771 : :
1772 : : DCHAR_T *
1773 : 36 : VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
1774 : : const FCHAR_T *format, va_list args)
1775 : : {
1776 : : DIRECTIVES d;
1777 : : arguments a;
1778 : :
1779 [ - + ]: 36 : if (PRINTF_PARSE (format, &d, &a) < 0)
1780 : : /* errno is already set. */
1781 : 0 : return NULL;
1782 : :
1783 : : #define CLEANUP() \
1784 : : if (d.dir != d.direct_alloc_dir) \
1785 : : free (d.dir); \
1786 : : if (a.arg != a.direct_alloc_arg) \
1787 : : free (a.arg);
1788 : :
1789 [ - + ]: 36 : if (PRINTF_FETCHARGS (args, &a) < 0)
1790 : : {
1791 [ # # ][ # # ]: 0 : CLEANUP ();
1792 : 0 : errno = EINVAL;
1793 : 0 : return NULL;
1794 : : }
1795 : :
1796 : : {
1797 : : size_t buf_neededlength;
1798 : : TCHAR_T *buf;
1799 : : TCHAR_T *buf_malloced;
1800 : : const FCHAR_T *cp;
1801 : : size_t i;
1802 : : DIRECTIVE *dp;
1803 : : /* Output string accumulator. */
1804 : : DCHAR_T *result;
1805 : : size_t allocated;
1806 : : size_t length;
1807 : :
1808 : : /* Allocate a small buffer that will hold a directive passed to
1809 : : sprintf or snprintf. */
1810 : 36 : buf_neededlength =
1811 : 36 : xsum4 (7, d.max_width_length, d.max_precision_length, 6);
1812 : : #if HAVE_ALLOCA
1813 [ + - ]: 36 : if (buf_neededlength < 4000 / sizeof (TCHAR_T))
1814 : : {
1815 : 36 : buf = (TCHAR_T *) alloca (buf_neededlength * sizeof (TCHAR_T));
1816 : 36 : buf_malloced = NULL;
1817 : : }
1818 : : else
1819 : : #endif
1820 : : {
1821 : 0 : size_t buf_memsize = xtimes (buf_neededlength, sizeof (TCHAR_T));
1822 [ # # ]: 0 : if (size_overflow_p (buf_memsize))
1823 : 0 : goto out_of_memory_1;
1824 : 0 : buf = (TCHAR_T *) malloc (buf_memsize);
1825 [ # # ]: 0 : if (buf == NULL)
1826 : 0 : goto out_of_memory_1;
1827 : 0 : buf_malloced = buf;
1828 : : }
1829 : :
1830 [ + + ]: 36 : if (resultbuf != NULL)
1831 : : {
1832 : 18 : result = resultbuf;
1833 : 18 : allocated = *lengthp;
1834 : : }
1835 : : else
1836 : : {
1837 : 18 : result = NULL;
1838 : 18 : allocated = 0;
1839 : : }
1840 : 36 : length = 0;
1841 : : /* Invariants:
1842 : : result is either == resultbuf or == NULL or malloc-allocated.
1843 : : If length > 0, then result != NULL. */
1844 : :
1845 : : /* Ensures that allocated >= needed. Aborts through a jump to
1846 : : out_of_memory if needed is SIZE_MAX or otherwise too big. */
1847 : : #define ENSURE_ALLOCATION(needed) \
1848 : : if ((needed) > allocated) \
1849 : : { \
1850 : : size_t memory_size; \
1851 : : DCHAR_T *memory; \
1852 : : \
1853 : : allocated = (allocated > 0 ? xtimes (allocated, 2) : 12); \
1854 : : if ((needed) > allocated) \
1855 : : allocated = (needed); \
1856 : : memory_size = xtimes (allocated, sizeof (DCHAR_T)); \
1857 : : if (size_overflow_p (memory_size)) \
1858 : : goto out_of_memory; \
1859 : : if (result == resultbuf || result == NULL) \
1860 : : memory = (DCHAR_T *) malloc (memory_size); \
1861 : : else \
1862 : : memory = (DCHAR_T *) realloc (result, memory_size); \
1863 : : if (memory == NULL) \
1864 : : goto out_of_memory; \
1865 : : if (result == resultbuf && length > 0) \
1866 : : DCHAR_CPY (memory, result, length); \
1867 : : result = memory; \
1868 : : }
1869 : :
1870 : 36 : for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++)
1871 : : {
1872 [ - + ]: 72 : if (cp != dp->dir_start)
1873 : : {
1874 : 0 : size_t n = dp->dir_start - cp;
1875 : 0 : size_t augmented_length = xsum (length, n);
1876 : :
1877 [ # # ][ # # ]: 0 : ENSURE_ALLOCATION (augmented_length);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1878 : : /* This copies a piece of FCHAR_T[] into a DCHAR_T[]. Here we
1879 : : need that the format string contains only ASCII characters
1880 : : if FCHAR_T and DCHAR_T are not the same type. */
1881 : : if (sizeof (FCHAR_T) == sizeof (DCHAR_T))
1882 : : {
1883 : 0 : DCHAR_CPY (result + length, (const DCHAR_T *) cp, n);
1884 : 0 : length = augmented_length;
1885 : : }
1886 : : else
1887 : : {
1888 : : do
1889 : : result[length++] = (unsigned char) *cp++;
1890 : : while (--n > 0);
1891 : : }
1892 : : }
1893 [ + + ]: 72 : if (i == d.count)
1894 : 36 : break;
1895 : :
1896 : : /* Execute a single directive. */
1897 [ - + ]: 36 : if (dp->conversion == '%')
1898 : : {
1899 : : size_t augmented_length;
1900 : :
1901 [ # # ]: 0 : if (!(dp->arg_index == ARG_NONE))
1902 : 0 : abort ();
1903 : 0 : augmented_length = xsum (length, 1);
1904 [ # # ][ # # ]: 0 : ENSURE_ALLOCATION (augmented_length);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1905 : 0 : result[length] = '%';
1906 : 0 : length = augmented_length;
1907 : : }
1908 : : else
1909 : : {
1910 [ - + ]: 36 : if (!(dp->arg_index != ARG_NONE))
1911 : 0 : abort ();
1912 : :
1913 [ - + ]: 36 : if (dp->conversion == 'n')
1914 : : {
1915 [ # # # # : 0 : switch (a.arg[dp->arg_index].type)
# # ]
1916 : : {
1917 : : case TYPE_COUNT_SCHAR_POINTER:
1918 : 0 : *a.arg[dp->arg_index].a.a_count_schar_pointer = length;
1919 : 0 : break;
1920 : : case TYPE_COUNT_SHORT_POINTER:
1921 : 0 : *a.arg[dp->arg_index].a.a_count_short_pointer = length;
1922 : 0 : break;
1923 : : case TYPE_COUNT_INT_POINTER:
1924 : 0 : *a.arg[dp->arg_index].a.a_count_int_pointer = length;
1925 : 0 : break;
1926 : : case TYPE_COUNT_LONGINT_POINTER:
1927 : 0 : *a.arg[dp->arg_index].a.a_count_longint_pointer = length;
1928 : 0 : break;
1929 : : #if HAVE_LONG_LONG_INT
1930 : : case TYPE_COUNT_LONGLONGINT_POINTER:
1931 : 0 : *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length;
1932 : 0 : break;
1933 : : #endif
1934 : : default:
1935 : 0 : abort ();
1936 : : }
1937 : : }
1938 : : #if ENABLE_UNISTDIO
1939 : : /* The unistdio extensions. */
1940 : : else if (dp->conversion == 'U')
1941 : : {
1942 : : arg_type type = a.arg[dp->arg_index].type;
1943 : : int flags = dp->flags;
1944 : : int has_width;
1945 : : size_t width;
1946 : : int has_precision;
1947 : : size_t precision;
1948 : :
1949 : : has_width = 0;
1950 : : width = 0;
1951 : : if (dp->width_start != dp->width_end)
1952 : : {
1953 : : if (dp->width_arg_index != ARG_NONE)
1954 : : {
1955 : : int arg;
1956 : :
1957 : : if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
1958 : : abort ();
1959 : : arg = a.arg[dp->width_arg_index].a.a_int;
1960 : : if (arg < 0)
1961 : : {
1962 : : /* "A negative field width is taken as a '-' flag
1963 : : followed by a positive field width." */
1964 : : flags |= FLAG_LEFT;
1965 : : width = (unsigned int) (-arg);
1966 : : }
1967 : : else
1968 : : width = arg;
1969 : : }
1970 : : else
1971 : : {
1972 : : const FCHAR_T *digitp = dp->width_start;
1973 : :
1974 : : do
1975 : : width = xsum (xtimes (width, 10), *digitp++ - '0');
1976 : : while (digitp != dp->width_end);
1977 : : }
1978 : : has_width = 1;
1979 : : }
1980 : :
1981 : : has_precision = 0;
1982 : : precision = 0;
1983 : : if (dp->precision_start != dp->precision_end)
1984 : : {
1985 : : if (dp->precision_arg_index != ARG_NONE)
1986 : : {
1987 : : int arg;
1988 : :
1989 : : if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
1990 : : abort ();
1991 : : arg = a.arg[dp->precision_arg_index].a.a_int;
1992 : : /* "A negative precision is taken as if the precision
1993 : : were omitted." */
1994 : : if (arg >= 0)
1995 : : {
1996 : : precision = arg;
1997 : : has_precision = 1;
1998 : : }
1999 : : }
2000 : : else
2001 : : {
2002 : : const FCHAR_T *digitp = dp->precision_start + 1;
2003 : :
2004 : : precision = 0;
2005 : : while (digitp != dp->precision_end)
2006 : : precision = xsum (xtimes (precision, 10), *digitp++ - '0');
2007 : : has_precision = 1;
2008 : : }
2009 : : }
2010 : :
2011 : : switch (type)
2012 : : {
2013 : : case TYPE_U8_STRING:
2014 : : {
2015 : : const uint8_t *arg = a.arg[dp->arg_index].a.a_u8_string;
2016 : : const uint8_t *arg_end;
2017 : : size_t characters;
2018 : :
2019 : : if (has_precision)
2020 : : {
2021 : : /* Use only PRECISION characters, from the left. */
2022 : : arg_end = arg;
2023 : : characters = 0;
2024 : : for (; precision > 0; precision--)
2025 : : {
2026 : : int count = u8_strmblen (arg_end);
2027 : : if (count == 0)
2028 : : break;
2029 : : if (count < 0)
2030 : : {
2031 : : if (!(result == resultbuf || result == NULL))
2032 : : free (result);
2033 : : if (buf_malloced != NULL)
2034 : : free (buf_malloced);
2035 : : CLEANUP ();
2036 : : errno = EILSEQ;
2037 : : return NULL;
2038 : : }
2039 : : arg_end += count;
2040 : : characters++;
2041 : : }
2042 : : }
2043 : : else if (has_width)
2044 : : {
2045 : : /* Use the entire string, and count the number of
2046 : : characters. */
2047 : : arg_end = arg;
2048 : : characters = 0;
2049 : : for (;;)
2050 : : {
2051 : : int count = u8_strmblen (arg_end);
2052 : : if (count == 0)
2053 : : break;
2054 : : if (count < 0)
2055 : : {
2056 : : if (!(result == resultbuf || result == NULL))
2057 : : free (result);
2058 : : if (buf_malloced != NULL)
2059 : : free (buf_malloced);
2060 : : CLEANUP ();
2061 : : errno = EILSEQ;
2062 : : return NULL;
2063 : : }
2064 : : arg_end += count;
2065 : : characters++;
2066 : : }
2067 : : }
2068 : : else
2069 : : {
2070 : : /* Use the entire string. */
2071 : : arg_end = arg + u8_strlen (arg);
2072 : : /* The number of characters doesn't matter. */
2073 : : characters = 0;
2074 : : }
2075 : :
2076 : : if (has_width && width > characters
2077 : : && !(dp->flags & FLAG_LEFT))
2078 : : {
2079 : : size_t n = width - characters;
2080 : : ENSURE_ALLOCATION (xsum (length, n));
2081 : : DCHAR_SET (result + length, ' ', n);
2082 : : length += n;
2083 : : }
2084 : :
2085 : : # if DCHAR_IS_UINT8_T
2086 : : {
2087 : : size_t n = arg_end - arg;
2088 : : ENSURE_ALLOCATION (xsum (length, n));
2089 : : DCHAR_CPY (result + length, arg, n);
2090 : : length += n;
2091 : : }
2092 : : # else
2093 : : { /* Convert. */
2094 : : DCHAR_T *converted = result + length;
2095 : : size_t converted_len = allocated - length;
2096 : : # if DCHAR_IS_TCHAR
2097 : : /* Convert from UTF-8 to locale encoding. */
2098 : : converted =
2099 : : u8_conv_to_encoding (locale_charset (),
2100 : : iconveh_question_mark,
2101 : : arg, arg_end - arg, NULL,
2102 : : converted, &converted_len);
2103 : : # else
2104 : : /* Convert from UTF-8 to UTF-16/UTF-32. */
2105 : : converted =
2106 : : U8_TO_DCHAR (arg, arg_end - arg,
2107 : : converted, &converted_len);
2108 : : # endif
2109 : : if (converted == NULL)
2110 : : {
2111 : : int saved_errno = errno;
2112 : : if (!(result == resultbuf || result == NULL))
2113 : : free (result);
2114 : : if (buf_malloced != NULL)
2115 : : free (buf_malloced);
2116 : : CLEANUP ();
2117 : : errno = saved_errno;
2118 : : return NULL;
2119 : : }
2120 : : if (converted != result + length)
2121 : : {
2122 : : ENSURE_ALLOCATION (xsum (length, converted_len));
2123 : : DCHAR_CPY (result + length, converted, converted_len);
2124 : : free (converted);
2125 : : }
2126 : : length += converted_len;
2127 : : }
2128 : : # endif
2129 : :
2130 : : if (has_width && width > characters
2131 : : && (dp->flags & FLAG_LEFT))
2132 : : {
2133 : : size_t n = width - characters;
2134 : : ENSURE_ALLOCATION (xsum (length, n));
2135 : : DCHAR_SET (result + length, ' ', n);
2136 : : length += n;
2137 : : }
2138 : : }
2139 : : break;
2140 : :
2141 : : case TYPE_U16_STRING:
2142 : : {
2143 : : const uint16_t *arg = a.arg[dp->arg_index].a.a_u16_string;
2144 : : const uint16_t *arg_end;
2145 : : size_t characters;
2146 : :
2147 : : if (has_precision)
2148 : : {
2149 : : /* Use only PRECISION characters, from the left. */
2150 : : arg_end = arg;
2151 : : characters = 0;
2152 : : for (; precision > 0; precision--)
2153 : : {
2154 : : int count = u16_strmblen (arg_end);
2155 : : if (count == 0)
2156 : : break;
2157 : : if (count < 0)
2158 : : {
2159 : : if (!(result == resultbuf || result == NULL))
2160 : : free (result);
2161 : : if (buf_malloced != NULL)
2162 : : free (buf_malloced);
2163 : : CLEANUP ();
2164 : : errno = EILSEQ;
2165 : : return NULL;
2166 : : }
2167 : : arg_end += count;
2168 : : characters++;
2169 : : }
2170 : : }
2171 : : else if (has_width)
2172 : : {
2173 : : /* Use the entire string, and count the number of
2174 : : characters. */
2175 : : arg_end = arg;
2176 : : characters = 0;
2177 : : for (;;)
2178 : : {
2179 : : int count = u16_strmblen (arg_end);
2180 : : if (count == 0)
2181 : : break;
2182 : : if (count < 0)
2183 : : {
2184 : : if (!(result == resultbuf || result == NULL))
2185 : : free (result);
2186 : : if (buf_malloced != NULL)
2187 : : free (buf_malloced);
2188 : : CLEANUP ();
2189 : : errno = EILSEQ;
2190 : : return NULL;
2191 : : }
2192 : : arg_end += count;
2193 : : characters++;
2194 : : }
2195 : : }
2196 : : else
2197 : : {
2198 : : /* Use the entire string. */
2199 : : arg_end = arg + u16_strlen (arg);
2200 : : /* The number of characters doesn't matter. */
2201 : : characters = 0;
2202 : : }
2203 : :
2204 : : if (has_width && width > characters
2205 : : && !(dp->flags & FLAG_LEFT))
2206 : : {
2207 : : size_t n = width - characters;
2208 : : ENSURE_ALLOCATION (xsum (length, n));
2209 : : DCHAR_SET (result + length, ' ', n);
2210 : : length += n;
2211 : : }
2212 : :
2213 : : # if DCHAR_IS_UINT16_T
2214 : : {
2215 : : size_t n = arg_end - arg;
2216 : : ENSURE_ALLOCATION (xsum (length, n));
2217 : : DCHAR_CPY (result + length, arg, n);
2218 : : length += n;
2219 : : }
2220 : : # else
2221 : : { /* Convert. */
2222 : : DCHAR_T *converted = result + length;
2223 : : size_t converted_len = allocated - length;
2224 : : # if DCHAR_IS_TCHAR
2225 : : /* Convert from UTF-16 to locale encoding. */
2226 : : converted =
2227 : : u16_conv_to_encoding (locale_charset (),
2228 : : iconveh_question_mark,
2229 : : arg, arg_end - arg, NULL,
2230 : : converted, &converted_len);
2231 : : # else
2232 : : /* Convert from UTF-16 to UTF-8/UTF-32. */
2233 : : converted =
2234 : : U16_TO_DCHAR (arg, arg_end - arg,
2235 : : converted, &converted_len);
2236 : : # endif
2237 : : if (converted == NULL)
2238 : : {
2239 : : int saved_errno = errno;
2240 : : if (!(result == resultbuf || result == NULL))
2241 : : free (result);
2242 : : if (buf_malloced != NULL)
2243 : : free (buf_malloced);
2244 : : CLEANUP ();
2245 : : errno = saved_errno;
2246 : : return NULL;
2247 : : }
2248 : : if (converted != result + length)
2249 : : {
2250 : : ENSURE_ALLOCATION (xsum (length, converted_len));
2251 : : DCHAR_CPY (result + length, converted, converted_len);
2252 : : free (converted);
2253 : : }
2254 : : length += converted_len;
2255 : : }
2256 : : # endif
2257 : :
2258 : : if (has_width && width > characters
2259 : : && (dp->flags & FLAG_LEFT))
2260 : : {
2261 : : size_t n = width - characters;
2262 : : ENSURE_ALLOCATION (xsum (length, n));
2263 : : DCHAR_SET (result + length, ' ', n);
2264 : : length += n;
2265 : : }
2266 : : }
2267 : : break;
2268 : :
2269 : : case TYPE_U32_STRING:
2270 : : {
2271 : : const uint32_t *arg = a.arg[dp->arg_index].a.a_u32_string;
2272 : : const uint32_t *arg_end;
2273 : : size_t characters;
2274 : :
2275 : : if (has_precision)
2276 : : {
2277 : : /* Use only PRECISION characters, from the left. */
2278 : : arg_end = arg;
2279 : : characters = 0;
2280 : : for (; precision > 0; precision--)
2281 : : {
2282 : : int count = u32_strmblen (arg_end);
2283 : : if (count == 0)
2284 : : break;
2285 : : if (count < 0)
2286 : : {
2287 : : if (!(result == resultbuf || result == NULL))
2288 : : free (result);
2289 : : if (buf_malloced != NULL)
2290 : : free (buf_malloced);
2291 : : CLEANUP ();
2292 : : errno = EILSEQ;
2293 : : return NULL;
2294 : : }
2295 : : arg_end += count;
2296 : : characters++;
2297 : : }
2298 : : }
2299 : : else if (has_width)
2300 : : {
2301 : : /* Use the entire string, and count the number of
2302 : : characters. */
2303 : : arg_end = arg;
2304 : : characters = 0;
2305 : : for (;;)
2306 : : {
2307 : : int count = u32_strmblen (arg_end);
2308 : : if (count == 0)
2309 : : break;
2310 : : if (count < 0)
2311 : : {
2312 : : if (!(result == resultbuf || result == NULL))
2313 : : free (result);
2314 : : if (buf_malloced != NULL)
2315 : : free (buf_malloced);
2316 : : CLEANUP ();
2317 : : errno = EILSEQ;
2318 : : return NULL;
2319 : : }
2320 : : arg_end += count;
2321 : : characters++;
2322 : : }
2323 : : }
2324 : : else
2325 : : {
2326 : : /* Use the entire string. */
2327 : : arg_end = arg + u32_strlen (arg);
2328 : : /* The number of characters doesn't matter. */
2329 : : characters = 0;
2330 : : }
2331 : :
2332 : : if (has_width && width > characters
2333 : : && !(dp->flags & FLAG_LEFT))
2334 : : {
2335 : : size_t n = width - characters;
2336 : : ENSURE_ALLOCATION (xsum (length, n));
2337 : : DCHAR_SET (result + length, ' ', n);
2338 : : length += n;
2339 : : }
2340 : :
2341 : : # if DCHAR_IS_UINT32_T
2342 : : {
2343 : : size_t n = arg_end - arg;
2344 : : ENSURE_ALLOCATION (xsum (length, n));
2345 : : DCHAR_CPY (result + length, arg, n);
2346 : : length += n;
2347 : : }
2348 : : # else
2349 : : { /* Convert. */
2350 : : DCHAR_T *converted = result + length;
2351 : : size_t converted_len = allocated - length;
2352 : : # if DCHAR_IS_TCHAR
2353 : : /* Convert from UTF-32 to locale encoding. */
2354 : : converted =
2355 : : u32_conv_to_encoding (locale_charset (),
2356 : : iconveh_question_mark,
2357 : : arg, arg_end - arg, NULL,
2358 : : converted, &converted_len);
2359 : : # else
2360 : : /* Convert from UTF-32 to UTF-8/UTF-16. */
2361 : : converted =
2362 : : U32_TO_DCHAR (arg, arg_end - arg,
2363 : : converted, &converted_len);
2364 : : # endif
2365 : : if (converted == NULL)
2366 : : {
2367 : : int saved_errno = errno;
2368 : : if (!(result == resultbuf || result == NULL))
2369 : : free (result);
2370 : : if (buf_malloced != NULL)
2371 : : free (buf_malloced);
2372 : : CLEANUP ();
2373 : : errno = saved_errno;
2374 : : return NULL;
2375 : : }
2376 : : if (converted != result + length)
2377 : : {
2378 : : ENSURE_ALLOCATION (xsum (length, converted_len));
2379 : : DCHAR_CPY (result + length, converted, converted_len);
2380 : : free (converted);
2381 : : }
2382 : : length += converted_len;
2383 : : }
2384 : : # endif
2385 : :
2386 : : if (has_width && width > characters
2387 : : && (dp->flags & FLAG_LEFT))
2388 : : {
2389 : : size_t n = width - characters;
2390 : : ENSURE_ALLOCATION (xsum (length, n));
2391 : : DCHAR_SET (result + length, ' ', n);
2392 : : length += n;
2393 : : }
2394 : : }
2395 : : break;
2396 : :
2397 : : default:
2398 : : abort ();
2399 : : }
2400 : : }
2401 : : #endif
2402 : : #if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && HAVE_WCHAR_T
2403 : : else if (dp->conversion == 's'
2404 : : # if WIDE_CHAR_VERSION
2405 : : && a.arg[dp->arg_index].type != TYPE_WIDE_STRING
2406 : : # else
2407 : : && a.arg[dp->arg_index].type == TYPE_WIDE_STRING
2408 : : # endif
2409 : : )
2410 : : {
2411 : : /* The normal handling of the 's' directive below requires
2412 : : allocating a temporary buffer. The determination of its
2413 : : length (tmp_length), in the case when a precision is
2414 : : specified, below requires a conversion between a char[]
2415 : : string and a wchar_t[] wide string. It could be done, but
2416 : : we have no guarantee that the implementation of sprintf will
2417 : : use the exactly same algorithm. Without this guarantee, it
2418 : : is possible to have buffer overrun bugs. In order to avoid
2419 : : such bugs, we implement the entire processing of the 's'
2420 : : directive ourselves. */
2421 : : int flags = dp->flags;
2422 : : int has_width;
2423 : : size_t width;
2424 : : int has_precision;
2425 : : size_t precision;
2426 : :
2427 : : has_width = 0;
2428 : : width = 0;
2429 : : if (dp->width_start != dp->width_end)
2430 : : {
2431 : : if (dp->width_arg_index != ARG_NONE)
2432 : : {
2433 : : int arg;
2434 : :
2435 : : if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
2436 : : abort ();
2437 : : arg = a.arg[dp->width_arg_index].a.a_int;
2438 : : if (arg < 0)
2439 : : {
2440 : : /* "A negative field width is taken as a '-' flag
2441 : : followed by a positive field width." */
2442 : : flags |= FLAG_LEFT;
2443 : : width = (unsigned int) (-arg);
2444 : : }
2445 : : else
2446 : : width = arg;
2447 : : }
2448 : : else
2449 : : {
2450 : : const FCHAR_T *digitp = dp->width_start;
2451 : :
2452 : : do
2453 : : width = xsum (xtimes (width, 10), *digitp++ - '0');
2454 : : while (digitp != dp->width_end);
2455 : : }
2456 : : has_width = 1;
2457 : : }
2458 : :
2459 : : has_precision = 0;
2460 : : precision = 6;
2461 : : if (dp->precision_start != dp->precision_end)
2462 : : {
2463 : : if (dp->precision_arg_index != ARG_NONE)
2464 : : {
2465 : : int arg;
2466 : :
2467 : : if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
2468 : : abort ();
2469 : : arg = a.arg[dp->precision_arg_index].a.a_int;
2470 : : /* "A negative precision is taken as if the precision
2471 : : were omitted." */
2472 : : if (arg >= 0)
2473 : : {
2474 : : precision = arg;
2475 : : has_precision = 1;
2476 : : }
2477 : : }
2478 : : else
2479 : : {
2480 : : const FCHAR_T *digitp = dp->precision_start + 1;
2481 : :
2482 : : precision = 0;
2483 : : while (digitp != dp->precision_end)
2484 : : precision = xsum (xtimes (precision, 10), *digitp++ - '0');
2485 : : has_precision = 1;
2486 : : }
2487 : : }
2488 : :
2489 : : # if WIDE_CHAR_VERSION
2490 : : /* %s in vasnwprintf. See the specification of fwprintf. */
2491 : : {
2492 : : const char *arg = a.arg[dp->arg_index].a.a_string;
2493 : : const char *arg_end;
2494 : : size_t characters;
2495 : :
2496 : : if (has_precision)
2497 : : {
2498 : : /* Use only as many bytes as needed to produce PRECISION
2499 : : wide characters, from the left. */
2500 : : # if HAVE_MBRTOWC
2501 : : mbstate_t state;
2502 : : memset (&state, '\0', sizeof (mbstate_t));
2503 : : # endif
2504 : : arg_end = arg;
2505 : : characters = 0;
2506 : : for (; precision > 0; precision--)
2507 : : {
2508 : : int count;
2509 : : # if HAVE_MBRTOWC
2510 : : count = mbrlen (arg_end, MB_CUR_MAX, &state);
2511 : : # else
2512 : : count = mblen (arg_end, MB_CUR_MAX);
2513 : : # endif
2514 : : if (count == 0)
2515 : : /* Found the terminating NUL. */
2516 : : break;
2517 : : if (count < 0)
2518 : : {
2519 : : /* Invalid or incomplete multibyte character. */
2520 : : if (!(result == resultbuf || result == NULL))
2521 : : free (result);
2522 : : if (buf_malloced != NULL)
2523 : : free (buf_malloced);
2524 : : CLEANUP ();
2525 : : errno = EILSEQ;
2526 : : return NULL;
2527 : : }
2528 : : arg_end += count;
2529 : : characters++;
2530 : : }
2531 : : }
2532 : : else if (has_width)
2533 : : {
2534 : : /* Use the entire string, and count the number of wide
2535 : : characters. */
2536 : : # if HAVE_MBRTOWC
2537 : : mbstate_t state;
2538 : : memset (&state, '\0', sizeof (mbstate_t));
2539 : : # endif
2540 : : arg_end = arg;
2541 : : characters = 0;
2542 : : for (;;)
2543 : : {
2544 : : int count;
2545 : : # if HAVE_MBRTOWC
2546 : : count = mbrlen (arg_end, MB_CUR_MAX, &state);
2547 : : # else
2548 : : count = mblen (arg_end, MB_CUR_MAX);
2549 : : # endif
2550 : : if (count == 0)
2551 : : /* Found the terminating NUL. */
2552 : : break;
2553 : : if (count < 0)
2554 : : {
2555 : : /* Invalid or incomplete multibyte character. */
2556 : : if (!(result == resultbuf || result == NULL))
2557 : : free (result);
2558 : : if (buf_malloced != NULL)
2559 : : free (buf_malloced);
2560 : : CLEANUP ();
2561 : : errno = EILSEQ;
2562 : : return NULL;
2563 : : }
2564 : : arg_end += count;
2565 : : characters++;
2566 : : }
2567 : : }
2568 : : else
2569 : : {
2570 : : /* Use the entire string. */
2571 : : arg_end = arg + strlen (arg);
2572 : : /* The number of characters doesn't matter. */
2573 : : characters = 0;
2574 : : }
2575 : :
2576 : : if (has_width && width > characters
2577 : : && !(dp->flags & FLAG_LEFT))
2578 : : {
2579 : : size_t n = width - characters;
2580 : : ENSURE_ALLOCATION (xsum (length, n));
2581 : : DCHAR_SET (result + length, ' ', n);
2582 : : length += n;
2583 : : }
2584 : :
2585 : : if (has_precision || has_width)
2586 : : {
2587 : : /* We know the number of wide characters in advance. */
2588 : : size_t remaining;
2589 : : # if HAVE_MBRTOWC
2590 : : mbstate_t state;
2591 : : memset (&state, '\0', sizeof (mbstate_t));
2592 : : # endif
2593 : : ENSURE_ALLOCATION (xsum (length, characters));
2594 : : for (remaining = characters; remaining > 0; remaining--)
2595 : : {
2596 : : wchar_t wc;
2597 : : int count;
2598 : : # if HAVE_MBRTOWC
2599 : : count = mbrtowc (&wc, arg, arg_end - arg, &state);
2600 : : # else
2601 : : count = mbtowc (&wc, arg, arg_end - arg);
2602 : : # endif
2603 : : if (count <= 0)
2604 : : /* mbrtowc not consistent with mbrlen, or mbtowc
2605 : : not consistent with mblen. */
2606 : : abort ();
2607 : : result[length++] = wc;
2608 : : arg += count;
2609 : : }
2610 : : if (!(arg == arg_end))
2611 : : abort ();
2612 : : }
2613 : : else
2614 : : {
2615 : : # if HAVE_MBRTOWC
2616 : : mbstate_t state;
2617 : : memset (&state, '\0', sizeof (mbstate_t));
2618 : : # endif
2619 : : while (arg < arg_end)
2620 : : {
2621 : : wchar_t wc;
2622 : : int count;
2623 : : # if HAVE_MBRTOWC
2624 : : count = mbrtowc (&wc, arg, arg_end - arg, &state);
2625 : : # else
2626 : : count = mbtowc (&wc, arg, arg_end - arg);
2627 : : # endif
2628 : : if (count <= 0)
2629 : : /* mbrtowc not consistent with mbrlen, or mbtowc
2630 : : not consistent with mblen. */
2631 : : abort ();
2632 : : ENSURE_ALLOCATION (xsum (length, 1));
2633 : : result[length++] = wc;
2634 : : arg += count;
2635 : : }
2636 : : }
2637 : :
2638 : : if (has_width && width > characters
2639 : : && (dp->flags & FLAG_LEFT))
2640 : : {
2641 : : size_t n = width - characters;
2642 : : ENSURE_ALLOCATION (xsum (length, n));
2643 : : DCHAR_SET (result + length, ' ', n);
2644 : : length += n;
2645 : : }
2646 : : }
2647 : : # else
2648 : : /* %ls in vasnprintf. See the specification of fprintf. */
2649 : : {
2650 : : const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
2651 : : const wchar_t *arg_end;
2652 : : size_t characters;
2653 : : # if !DCHAR_IS_TCHAR
2654 : : /* This code assumes that TCHAR_T is 'char'. */
2655 : : verify (sizeof (TCHAR_T) == 1);
2656 : : TCHAR_T *tmpsrc;
2657 : : DCHAR_T *tmpdst;
2658 : : size_t tmpdst_len;
2659 : : # endif
2660 : : size_t w;
2661 : :
2662 : : if (has_precision)
2663 : : {
2664 : : /* Use only as many wide characters as needed to produce
2665 : : at most PRECISION bytes, from the left. */
2666 : : # if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2667 : : mbstate_t state;
2668 : : memset (&state, '\0', sizeof (mbstate_t));
2669 : : # endif
2670 : : arg_end = arg;
2671 : : characters = 0;
2672 : : while (precision > 0)
2673 : : {
2674 : : char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
2675 : : int count;
2676 : :
2677 : : if (*arg_end == 0)
2678 : : /* Found the terminating null wide character. */
2679 : : break;
2680 : : # if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2681 : : count = wcrtomb (cbuf, *arg_end, &state);
2682 : : # else
2683 : : count = wctomb (cbuf, *arg_end);
2684 : : # endif
2685 : : if (count < 0)
2686 : : {
2687 : : /* Cannot convert. */
2688 : : if (!(result == resultbuf || result == NULL))
2689 : : free (result);
2690 : : if (buf_malloced != NULL)
2691 : : free (buf_malloced);
2692 : : CLEANUP ();
2693 : : errno = EILSEQ;
2694 : : return NULL;
2695 : : }
2696 : : if (precision < count)
2697 : : break;
2698 : : arg_end++;
2699 : : characters += count;
2700 : : precision -= count;
2701 : : }
2702 : : }
2703 : : # if DCHAR_IS_TCHAR
2704 : : else if (has_width)
2705 : : # else
2706 : : else
2707 : : # endif
2708 : : {
2709 : : /* Use the entire string, and count the number of
2710 : : bytes. */
2711 : : # if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2712 : : mbstate_t state;
2713 : : memset (&state, '\0', sizeof (mbstate_t));
2714 : : # endif
2715 : : arg_end = arg;
2716 : : characters = 0;
2717 : : for (;;)
2718 : : {
2719 : : char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
2720 : : int count;
2721 : :
2722 : : if (*arg_end == 0)
2723 : : /* Found the terminating null wide character. */
2724 : : break;
2725 : : # if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2726 : : count = wcrtomb (cbuf, *arg_end, &state);
2727 : : # else
2728 : : count = wctomb (cbuf, *arg_end);
2729 : : # endif
2730 : : if (count < 0)
2731 : : {
2732 : : /* Cannot convert. */
2733 : : if (!(result == resultbuf || result == NULL))
2734 : : free (result);
2735 : : if (buf_malloced != NULL)
2736 : : free (buf_malloced);
2737 : : CLEANUP ();
2738 : : errno = EILSEQ;
2739 : : return NULL;
2740 : : }
2741 : : arg_end++;
2742 : : characters += count;
2743 : : }
2744 : : }
2745 : : # if DCHAR_IS_TCHAR
2746 : : else
2747 : : {
2748 : : /* Use the entire string. */
2749 : : arg_end = arg + local_wcslen (arg);
2750 : : /* The number of bytes doesn't matter. */
2751 : : characters = 0;
2752 : : }
2753 : : # endif
2754 : :
2755 : : # if !DCHAR_IS_TCHAR
2756 : : /* Convert the string into a piece of temporary memory. */
2757 : : tmpsrc = (TCHAR_T *) malloc (characters * sizeof (TCHAR_T));
2758 : : if (tmpsrc == NULL)
2759 : : goto out_of_memory;
2760 : : {
2761 : : TCHAR_T *tmpptr = tmpsrc;
2762 : : size_t remaining;
2763 : : # if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2764 : : mbstate_t state;
2765 : : memset (&state, '\0', sizeof (mbstate_t));
2766 : : # endif
2767 : : for (remaining = characters; remaining > 0; )
2768 : : {
2769 : : char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
2770 : : int count;
2771 : :
2772 : : if (*arg == 0)
2773 : : abort ();
2774 : : # if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2775 : : count = wcrtomb (cbuf, *arg, &state);
2776 : : # else
2777 : : count = wctomb (cbuf, *arg);
2778 : : # endif
2779 : : if (count <= 0)
2780 : : /* Inconsistency. */
2781 : : abort ();
2782 : : memcpy (tmpptr, cbuf, count);
2783 : : tmpptr += count;
2784 : : arg++;
2785 : : remaining -= count;
2786 : : }
2787 : : if (!(arg == arg_end))
2788 : : abort ();
2789 : : }
2790 : :
2791 : : /* Convert from TCHAR_T[] to DCHAR_T[]. */
2792 : : tmpdst =
2793 : : DCHAR_CONV_FROM_ENCODING (locale_charset (),
2794 : : iconveh_question_mark,
2795 : : tmpsrc, characters,
2796 : : NULL,
2797 : : NULL, &tmpdst_len);
2798 : : if (tmpdst == NULL)
2799 : : {
2800 : : int saved_errno = errno;
2801 : : free (tmpsrc);
2802 : : if (!(result == resultbuf || result == NULL))
2803 : : free (result);
2804 : : if (buf_malloced != NULL)
2805 : : free (buf_malloced);
2806 : : CLEANUP ();
2807 : : errno = saved_errno;
2808 : : return NULL;
2809 : : }
2810 : : free (tmpsrc);
2811 : : # endif
2812 : :
2813 : : if (has_width)
2814 : : {
2815 : : # if ENABLE_UNISTDIO
2816 : : /* Outside POSIX, it's preferable to compare the width
2817 : : against the number of _characters_ of the converted
2818 : : value. */
2819 : : w = DCHAR_MBSNLEN (result + length, characters);
2820 : : # else
2821 : : /* The width is compared against the number of _bytes_
2822 : : of the converted value, says POSIX. */
2823 : : w = characters;
2824 : : # endif
2825 : : }
2826 : : else
2827 : : /* w doesn't matter. */
2828 : : w = 0;
2829 : :
2830 : : if (has_width && width > w
2831 : : && !(dp->flags & FLAG_LEFT))
2832 : : {
2833 : : size_t n = width - w;
2834 : : ENSURE_ALLOCATION (xsum (length, n));
2835 : : DCHAR_SET (result + length, ' ', n);
2836 : : length += n;
2837 : : }
2838 : :
2839 : : # if DCHAR_IS_TCHAR
2840 : : if (has_precision || has_width)
2841 : : {
2842 : : /* We know the number of bytes in advance. */
2843 : : size_t remaining;
2844 : : # if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2845 : : mbstate_t state;
2846 : : memset (&state, '\0', sizeof (mbstate_t));
2847 : : # endif
2848 : : ENSURE_ALLOCATION (xsum (length, characters));
2849 : : for (remaining = characters; remaining > 0; )
2850 : : {
2851 : : char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
2852 : : int count;
2853 : :
2854 : : if (*arg == 0)
2855 : : abort ();
2856 : : # if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2857 : : count = wcrtomb (cbuf, *arg, &state);
2858 : : # else
2859 : : count = wctomb (cbuf, *arg);
2860 : : # endif
2861 : : if (count <= 0)
2862 : : /* Inconsistency. */
2863 : : abort ();
2864 : : memcpy (result + length, cbuf, count);
2865 : : length += count;
2866 : : arg++;
2867 : : remaining -= count;
2868 : : }
2869 : : if (!(arg == arg_end))
2870 : : abort ();
2871 : : }
2872 : : else
2873 : : {
2874 : : # if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2875 : : mbstate_t state;
2876 : : memset (&state, '\0', sizeof (mbstate_t));
2877 : : # endif
2878 : : while (arg < arg_end)
2879 : : {
2880 : : char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
2881 : : int count;
2882 : :
2883 : : if (*arg == 0)
2884 : : abort ();
2885 : : # if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2886 : : count = wcrtomb (cbuf, *arg, &state);
2887 : : # else
2888 : : count = wctomb (cbuf, *arg);
2889 : : # endif
2890 : : if (count <= 0)
2891 : : {
2892 : : /* Cannot convert. */
2893 : : if (!(result == resultbuf || result == NULL))
2894 : : free (result);
2895 : : if (buf_malloced != NULL)
2896 : : free (buf_malloced);
2897 : : CLEANUP ();
2898 : : errno = EILSEQ;
2899 : : return NULL;
2900 : : }
2901 : : ENSURE_ALLOCATION (xsum (length, count));
2902 : : memcpy (result + length, cbuf, count);
2903 : : length += count;
2904 : : arg++;
2905 : : }
2906 : : }
2907 : : # else
2908 : : ENSURE_ALLOCATION (xsum (length, tmpdst_len));
2909 : : DCHAR_CPY (result + length, tmpdst, tmpdst_len);
2910 : : free (tmpdst);
2911 : : length += tmpdst_len;
2912 : : # endif
2913 : :
2914 : : if (has_width && width > w
2915 : : && (dp->flags & FLAG_LEFT))
2916 : : {
2917 : : size_t n = width - w;
2918 : : ENSURE_ALLOCATION (xsum (length, n));
2919 : : DCHAR_SET (result + length, ' ', n);
2920 : : length += n;
2921 : : }
2922 : : }
2923 : : # endif
2924 : : }
2925 : : #endif
2926 : : #if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL
2927 : : else if ((dp->conversion == 'a' || dp->conversion == 'A')
2928 : : # if !(NEED_PRINTF_DIRECTIVE_A || (NEED_PRINTF_LONG_DOUBLE && NEED_PRINTF_DOUBLE))
2929 : : && (0
2930 : : # if NEED_PRINTF_DOUBLE
2931 : : || a.arg[dp->arg_index].type == TYPE_DOUBLE
2932 : : # endif
2933 : : # if NEED_PRINTF_LONG_DOUBLE
2934 : : || a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
2935 : : # endif
2936 : : )
2937 : : # endif
2938 : : )
2939 : : {
2940 : : arg_type type = a.arg[dp->arg_index].type;
2941 : : int flags = dp->flags;
2942 : : int has_width;
2943 : : size_t width;
2944 : : int has_precision;
2945 : : size_t precision;
2946 : : size_t tmp_length;
2947 : : DCHAR_T tmpbuf[700];
2948 : : DCHAR_T *tmp;
2949 : : DCHAR_T *pad_ptr;
2950 : : DCHAR_T *p;
2951 : :
2952 : : has_width = 0;
2953 : : width = 0;
2954 : : if (dp->width_start != dp->width_end)
2955 : : {
2956 : : if (dp->width_arg_index != ARG_NONE)
2957 : : {
2958 : : int arg;
2959 : :
2960 : : if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
2961 : : abort ();
2962 : : arg = a.arg[dp->width_arg_index].a.a_int;
2963 : : if (arg < 0)
2964 : : {
2965 : : /* "A negative field width is taken as a '-' flag
2966 : : followed by a positive field width." */
2967 : : flags |= FLAG_LEFT;
2968 : : width = (unsigned int) (-arg);
2969 : : }
2970 : : else
2971 : : width = arg;
2972 : : }
2973 : : else
2974 : : {
2975 : : const FCHAR_T *digitp = dp->width_start;
2976 : :
2977 : : do
2978 : : width = xsum (xtimes (width, 10), *digitp++ - '0');
2979 : : while (digitp != dp->width_end);
2980 : : }
2981 : : has_width = 1;
2982 : : }
2983 : :
2984 : : has_precision = 0;
2985 : : precision = 0;
2986 : : if (dp->precision_start != dp->precision_end)
2987 : : {
2988 : : if (dp->precision_arg_index != ARG_NONE)
2989 : : {
2990 : : int arg;
2991 : :
2992 : : if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
2993 : : abort ();
2994 : : arg = a.arg[dp->precision_arg_index].a.a_int;
2995 : : /* "A negative precision is taken as if the precision
2996 : : were omitted." */
2997 : : if (arg >= 0)
2998 : : {
2999 : : precision = arg;
3000 : : has_precision = 1;
3001 : : }
3002 : : }
3003 : : else
3004 : : {
3005 : : const FCHAR_T *digitp = dp->precision_start + 1;
3006 : :
3007 : : precision = 0;
3008 : : while (digitp != dp->precision_end)
3009 : : precision = xsum (xtimes (precision, 10), *digitp++ - '0');
3010 : : has_precision = 1;
3011 : : }
3012 : : }
3013 : :
3014 : : /* Allocate a temporary buffer of sufficient size. */
3015 : : if (type == TYPE_LONGDOUBLE)
3016 : : tmp_length =
3017 : : (unsigned int) ((LDBL_DIG + 1)
3018 : : * 0.831 /* decimal -> hexadecimal */
3019 : : )
3020 : : + 1; /* turn floor into ceil */
3021 : : else
3022 : : tmp_length =
3023 : : (unsigned int) ((DBL_DIG + 1)
3024 : : * 0.831 /* decimal -> hexadecimal */
3025 : : )
3026 : : + 1; /* turn floor into ceil */
3027 : : if (tmp_length < precision)
3028 : : tmp_length = precision;
3029 : : /* Account for sign, decimal point etc. */
3030 : : tmp_length = xsum (tmp_length, 12);
3031 : :
3032 : : if (tmp_length < width)
3033 : : tmp_length = width;
3034 : :
3035 : : tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
3036 : :
3037 : : if (tmp_length <= sizeof (tmpbuf) / sizeof (DCHAR_T))
3038 : : tmp = tmpbuf;
3039 : : else
3040 : : {
3041 : : size_t tmp_memsize = xtimes (tmp_length, sizeof (DCHAR_T));
3042 : :
3043 : : if (size_overflow_p (tmp_memsize))
3044 : : /* Overflow, would lead to out of memory. */
3045 : : goto out_of_memory;
3046 : : tmp = (DCHAR_T *) malloc (tmp_memsize);
3047 : : if (tmp == NULL)
3048 : : /* Out of memory. */
3049 : : goto out_of_memory;
3050 : : }
3051 : :
3052 : : pad_ptr = NULL;
3053 : : p = tmp;
3054 : : if (type == TYPE_LONGDOUBLE)
3055 : : {
3056 : : # if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE
3057 : : long double arg = a.arg[dp->arg_index].a.a_longdouble;
3058 : :
3059 : : if (isnanl (arg))
3060 : : {
3061 : : if (dp->conversion == 'A')
3062 : : {
3063 : : *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
3064 : : }
3065 : : else
3066 : : {
3067 : : *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
3068 : : }
3069 : : }
3070 : : else
3071 : : {
3072 : : int sign = 0;
3073 : : DECL_LONG_DOUBLE_ROUNDING
3074 : :
3075 : : BEGIN_LONG_DOUBLE_ROUNDING ();
3076 : :
3077 : : if (signbit (arg)) /* arg < 0.0L or negative zero */
3078 : : {
3079 : : sign = -1;
3080 : : arg = -arg;
3081 : : }
3082 : :
3083 : : if (sign < 0)
3084 : : *p++ = '-';
3085 : : else if (flags & FLAG_SHOWSIGN)
3086 : : *p++ = '+';
3087 : : else if (flags & FLAG_SPACE)
3088 : : *p++ = ' ';
3089 : :
3090 : : if (arg > 0.0L && arg + arg == arg)
3091 : : {
3092 : : if (dp->conversion == 'A')
3093 : : {
3094 : : *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
3095 : : }
3096 : : else
3097 : : {
3098 : : *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
3099 : : }
3100 : : }
3101 : : else
3102 : : {
3103 : : int exponent;
3104 : : long double mantissa;
3105 : :
3106 : : if (arg > 0.0L)
3107 : : mantissa = printf_frexpl (arg, &exponent);
3108 : : else
3109 : : {
3110 : : exponent = 0;
3111 : : mantissa = 0.0L;
3112 : : }
3113 : :
3114 : : if (has_precision
3115 : : && precision < (unsigned int) ((LDBL_DIG + 1) * 0.831) + 1)
3116 : : {
3117 : : /* Round the mantissa. */
3118 : : long double tail = mantissa;
3119 : : size_t q;
3120 : :
3121 : : for (q = precision; ; q--)
3122 : : {
3123 : : int digit = (int) tail;
3124 : : tail -= digit;
3125 : : if (q == 0)
3126 : : {
3127 : : if (digit & 1 ? tail >= 0.5L : tail > 0.5L)
3128 : : tail = 1 - tail;
3129 : : else
3130 : : tail = - tail;
3131 : : break;
3132 : : }
3133 : : tail *= 16.0L;
3134 : : }
3135 : : if (tail != 0.0L)
3136 : : for (q = precision; q > 0; q--)
3137 : : tail *= 0.0625L;
3138 : : mantissa += tail;
3139 : : }
3140 : :
3141 : : *p++ = '0';
3142 : : *p++ = dp->conversion - 'A' + 'X';
3143 : : pad_ptr = p;
3144 : : {
3145 : : int digit;
3146 : :
3147 : : digit = (int) mantissa;
3148 : : mantissa -= digit;
3149 : : *p++ = '0' + digit;
3150 : : if ((flags & FLAG_ALT)
3151 : : || mantissa > 0.0L || precision > 0)
3152 : : {
3153 : : *p++ = decimal_point_char ();
3154 : : /* This loop terminates because we assume
3155 : : that FLT_RADIX is a power of 2. */
3156 : : while (mantissa > 0.0L)
3157 : : {
3158 : : mantissa *= 16.0L;
3159 : : digit = (int) mantissa;
3160 : : mantissa -= digit;
3161 : : *p++ = digit
3162 : : + (digit < 10
3163 : : ? '0'
3164 : : : dp->conversion - 10);
3165 : : if (precision > 0)
3166 : : precision--;
3167 : : }
3168 : : while (precision > 0)
3169 : : {
3170 : : *p++ = '0';
3171 : : precision--;
3172 : : }
3173 : : }
3174 : : }
3175 : : *p++ = dp->conversion - 'A' + 'P';
3176 : : # if WIDE_CHAR_VERSION
3177 : : {
3178 : : static const wchar_t decimal_format[] =
3179 : : { '%', '+', 'd', '\0' };
3180 : : SNPRINTF (p, 6 + 1, decimal_format, exponent);
3181 : : }
3182 : : while (*p != '\0')
3183 : : p++;
3184 : : # else
3185 : : if (sizeof (DCHAR_T) == 1)
3186 : : {
3187 : : sprintf ((char *) p, "%+d", exponent);
3188 : : while (*p != '\0')
3189 : : p++;
3190 : : }
3191 : : else
3192 : : {
3193 : : char expbuf[6 + 1];
3194 : : const char *ep;
3195 : : sprintf (expbuf, "%+d", exponent);
3196 : : for (ep = expbuf; (*p = *ep) != '\0'; ep++)
3197 : : p++;
3198 : : }
3199 : : # endif
3200 : : }
3201 : :
3202 : : END_LONG_DOUBLE_ROUNDING ();
3203 : : }
3204 : : # else
3205 : : abort ();
3206 : : # endif
3207 : : }
3208 : : else
3209 : : {
3210 : : # if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE
3211 : : double arg = a.arg[dp->arg_index].a.a_double;
3212 : :
3213 : : if (isnand (arg))
3214 : : {
3215 : : if (dp->conversion == 'A')
3216 : : {
3217 : : *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
3218 : : }
3219 : : else
3220 : : {
3221 : : *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
3222 : : }
3223 : : }
3224 : : else
3225 : : {
3226 : : int sign = 0;
3227 : :
3228 : : if (signbit (arg)) /* arg < 0.0 or negative zero */
3229 : : {
3230 : : sign = -1;
3231 : : arg = -arg;
3232 : : }
3233 : :
3234 : : if (sign < 0)
3235 : : *p++ = '-';
3236 : : else if (flags & FLAG_SHOWSIGN)
3237 : : *p++ = '+';
3238 : : else if (flags & FLAG_SPACE)
3239 : : *p++ = ' ';
3240 : :
3241 : : if (arg > 0.0 && arg + arg == arg)
3242 : : {
3243 : : if (dp->conversion == 'A')
3244 : : {
3245 : : *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
3246 : : }
3247 : : else
3248 : : {
3249 : : *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
3250 : : }
3251 : : }
3252 : : else
3253 : : {
3254 : : int exponent;
3255 : : double mantissa;
3256 : :
3257 : : if (arg > 0.0)
3258 : : mantissa = printf_frexp (arg, &exponent);
3259 : : else
3260 : : {
3261 : : exponent = 0;
3262 : : mantissa = 0.0;
3263 : : }
3264 : :
3265 : : if (has_precision
3266 : : && precision < (unsigned int) ((DBL_DIG + 1) * 0.831) + 1)
3267 : : {
3268 : : /* Round the mantissa. */
3269 : : double tail = mantissa;
3270 : : size_t q;
3271 : :
3272 : : for (q = precision; ; q--)
3273 : : {
3274 : : int digit = (int) tail;
3275 : : tail -= digit;
3276 : : if (q == 0)
3277 : : {
3278 : : if (digit & 1 ? tail >= 0.5 : tail > 0.5)
3279 : : tail = 1 - tail;
3280 : : else
3281 : : tail = - tail;
3282 : : break;
3283 : : }
3284 : : tail *= 16.0;
3285 : : }
3286 : : if (tail != 0.0)
3287 : : for (q = precision; q > 0; q--)
3288 : : tail *= 0.0625;
3289 : : mantissa += tail;
3290 : : }
3291 : :
3292 : : *p++ = '0';
3293 : : *p++ = dp->conversion - 'A' + 'X';
3294 : : pad_ptr = p;
3295 : : {
3296 : : int digit;
3297 : :
3298 : : digit = (int) mantissa;
3299 : : mantissa -= digit;
3300 : : *p++ = '0' + digit;
3301 : : if ((flags & FLAG_ALT)
3302 : : || mantissa > 0.0 || precision > 0)
3303 : : {
3304 : : *p++ = decimal_point_char ();
3305 : : /* This loop terminates because we assume
3306 : : that FLT_RADIX is a power of 2. */
3307 : : while (mantissa > 0.0)
3308 : : {
3309 : : mantissa *= 16.0;
3310 : : digit = (int) mantissa;
3311 : : mantissa -= digit;
3312 : : *p++ = digit
3313 : : + (digit < 10
3314 : : ? '0'
3315 : : : dp->conversion - 10);
3316 : : if (precision > 0)
3317 : : precision--;
3318 : : }
3319 : : while (precision > 0)
3320 : : {
3321 : : *p++ = '0';
3322 : : precision--;
3323 : : }
3324 : : }
3325 : : }
3326 : : *p++ = dp->conversion - 'A' + 'P';
3327 : : # if WIDE_CHAR_VERSION
3328 : : {
3329 : : static const wchar_t decimal_format[] =
3330 : : { '%', '+', 'd', '\0' };
3331 : : SNPRINTF (p, 6 + 1, decimal_format, exponent);
3332 : : }
3333 : : while (*p != '\0')
3334 : : p++;
3335 : : # else
3336 : : if (sizeof (DCHAR_T) == 1)
3337 : : {
3338 : : sprintf ((char *) p, "%+d", exponent);
3339 : : while (*p != '\0')
3340 : : p++;
3341 : : }
3342 : : else
3343 : : {
3344 : : char expbuf[6 + 1];
3345 : : const char *ep;
3346 : : sprintf (expbuf, "%+d", exponent);
3347 : : for (ep = expbuf; (*p = *ep) != '\0'; ep++)
3348 : : p++;
3349 : : }
3350 : : # endif
3351 : : }
3352 : : }
3353 : : # else
3354 : : abort ();
3355 : : # endif
3356 : : }
3357 : : /* The generated string now extends from tmp to p, with the
3358 : : zero padding insertion point being at pad_ptr. */
3359 : : if (has_width && p - tmp < width)
3360 : : {
3361 : : size_t pad = width - (p - tmp);
3362 : : DCHAR_T *end = p + pad;
3363 : :
3364 : : if (flags & FLAG_LEFT)
3365 : : {
3366 : : /* Pad with spaces on the right. */
3367 : : for (; pad > 0; pad--)
3368 : : *p++ = ' ';
3369 : : }
3370 : : else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
3371 : : {
3372 : : /* Pad with zeroes. */
3373 : : DCHAR_T *q = end;
3374 : :
3375 : : while (p > pad_ptr)
3376 : : *--q = *--p;
3377 : : for (; pad > 0; pad--)
3378 : : *p++ = '0';
3379 : : }
3380 : : else
3381 : : {
3382 : : /* Pad with spaces on the left. */
3383 : : DCHAR_T *q = end;
3384 : :
3385 : : while (p > tmp)
3386 : : *--q = *--p;
3387 : : for (; pad > 0; pad--)
3388 : : *p++ = ' ';
3389 : : }
3390 : :
3391 : : p = end;
3392 : : }
3393 : :
3394 : : {
3395 : : size_t count = p - tmp;
3396 : :
3397 : : if (count >= tmp_length)
3398 : : /* tmp_length was incorrectly calculated - fix the
3399 : : code above! */
3400 : : abort ();
3401 : :
3402 : : /* Make room for the result. */
3403 : : if (count >= allocated - length)
3404 : : {
3405 : : size_t n = xsum (length, count);
3406 : :
3407 : : ENSURE_ALLOCATION (n);
3408 : : }
3409 : :
3410 : : /* Append the result. */
3411 : : memcpy (result + length, tmp, count * sizeof (DCHAR_T));
3412 : : if (tmp != tmpbuf)
3413 : : free (tmp);
3414 : : length += count;
3415 : : }
3416 : : }
3417 : : #endif
3418 : : #if (NEED_PRINTF_INFINITE_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL
3419 : : else if ((dp->conversion == 'f' || dp->conversion == 'F'
3420 : : || dp->conversion == 'e' || dp->conversion == 'E'
3421 : : || dp->conversion == 'g' || dp->conversion == 'G'
3422 : : || dp->conversion == 'a' || dp->conversion == 'A')
3423 : : && (0
3424 : : # if NEED_PRINTF_DOUBLE
3425 : : || a.arg[dp->arg_index].type == TYPE_DOUBLE
3426 : : # elif NEED_PRINTF_INFINITE_DOUBLE
3427 : : || (a.arg[dp->arg_index].type == TYPE_DOUBLE
3428 : : /* The systems (mingw) which produce wrong output
3429 : : for Inf, -Inf, and NaN also do so for -0.0.
3430 : : Therefore we treat this case here as well. */
3431 : : && is_infinite_or_zero (a.arg[dp->arg_index].a.a_double))
3432 : : # endif
3433 : : # if NEED_PRINTF_LONG_DOUBLE
3434 : : || a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
3435 : : # elif NEED_PRINTF_INFINITE_LONG_DOUBLE
3436 : : || (a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
3437 : : /* Some systems produce wrong output for Inf,
3438 : : -Inf, and NaN. Some systems in this category
3439 : : (IRIX 5.3) also do so for -0.0. Therefore we
3440 : : treat this case here as well. */
3441 : : && is_infinite_or_zerol (a.arg[dp->arg_index].a.a_longdouble))
3442 : : # endif
3443 : : ))
3444 : : {
3445 : : # if (NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE)
3446 : : arg_type type = a.arg[dp->arg_index].type;
3447 : : # endif
3448 : : int flags = dp->flags;
3449 : : int has_width;
3450 : : size_t width;
3451 : : int has_precision;
3452 : : size_t precision;
3453 : : size_t tmp_length;
3454 : : DCHAR_T tmpbuf[700];
3455 : : DCHAR_T *tmp;
3456 : : DCHAR_T *pad_ptr;
3457 : : DCHAR_T *p;
3458 : :
3459 : : has_width = 0;
3460 : : width = 0;
3461 : : if (dp->width_start != dp->width_end)
3462 : : {
3463 : : if (dp->width_arg_index != ARG_NONE)
3464 : : {
3465 : : int arg;
3466 : :
3467 : : if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
3468 : : abort ();
3469 : : arg = a.arg[dp->width_arg_index].a.a_int;
3470 : : if (arg < 0)
3471 : : {
3472 : : /* "A negative field width is taken as a '-' flag
3473 : : followed by a positive field width." */
3474 : : flags |= FLAG_LEFT;
3475 : : width = (unsigned int) (-arg);
3476 : : }
3477 : : else
3478 : : width = arg;
3479 : : }
3480 : : else
3481 : : {
3482 : : const FCHAR_T *digitp = dp->width_start;
3483 : :
3484 : : do
3485 : : width = xsum (xtimes (width, 10), *digitp++ - '0');
3486 : : while (digitp != dp->width_end);
3487 : : }
3488 : : has_width = 1;
3489 : : }
3490 : :
3491 : : has_precision = 0;
3492 : : precision = 0;
3493 : : if (dp->precision_start != dp->precision_end)
3494 : : {
3495 : : if (dp->precision_arg_index != ARG_NONE)
3496 : : {
3497 : : int arg;
3498 : :
3499 : : if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
3500 : : abort ();
3501 : : arg = a.arg[dp->precision_arg_index].a.a_int;
3502 : : /* "A negative precision is taken as if the precision
3503 : : were omitted." */
3504 : : if (arg >= 0)
3505 : : {
3506 : : precision = arg;
3507 : : has_precision = 1;
3508 : : }
3509 : : }
3510 : : else
3511 : : {
3512 : : const FCHAR_T *digitp = dp->precision_start + 1;
3513 : :
3514 : : precision = 0;
3515 : : while (digitp != dp->precision_end)
3516 : : precision = xsum (xtimes (precision, 10), *digitp++ - '0');
3517 : : has_precision = 1;
3518 : : }
3519 : : }
3520 : :
3521 : : /* POSIX specifies the default precision to be 6 for %f, %F,
3522 : : %e, %E, but not for %g, %G. Implementations appear to use
3523 : : the same default precision also for %g, %G. But for %a, %A,
3524 : : the default precision is 0. */
3525 : : if (!has_precision)
3526 : : if (!(dp->conversion == 'a' || dp->conversion == 'A'))
3527 : : precision = 6;
3528 : :
3529 : : /* Allocate a temporary buffer of sufficient size. */
3530 : : # if NEED_PRINTF_DOUBLE && NEED_PRINTF_LONG_DOUBLE
3531 : : tmp_length = (type == TYPE_LONGDOUBLE ? LDBL_DIG + 1 : DBL_DIG + 1);
3532 : : # elif NEED_PRINTF_INFINITE_DOUBLE && NEED_PRINTF_LONG_DOUBLE
3533 : : tmp_length = (type == TYPE_LONGDOUBLE ? LDBL_DIG + 1 : 0);
3534 : : # elif NEED_PRINTF_LONG_DOUBLE
3535 : : tmp_length = LDBL_DIG + 1;
3536 : : # elif NEED_PRINTF_DOUBLE
3537 : : tmp_length = DBL_DIG + 1;
3538 : : # else
3539 : : tmp_length = 0;
3540 : : # endif
3541 : : if (tmp_length < precision)
3542 : : tmp_length = precision;
3543 : : # if NEED_PRINTF_LONG_DOUBLE
3544 : : # if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
3545 : : if (type == TYPE_LONGDOUBLE)
3546 : : # endif
3547 : : if (dp->conversion == 'f' || dp->conversion == 'F')
3548 : : {
3549 : : long double arg = a.arg[dp->arg_index].a.a_longdouble;
3550 : : if (!(isnanl (arg) || arg + arg == arg))
3551 : : {
3552 : : /* arg is finite and nonzero. */
3553 : : int exponent = floorlog10l (arg < 0 ? -arg : arg);
3554 : : if (exponent >= 0 && tmp_length < exponent + precision)
3555 : : tmp_length = exponent + precision;
3556 : : }
3557 : : }
3558 : : # endif
3559 : : # if NEED_PRINTF_DOUBLE
3560 : : # if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE
3561 : : if (type == TYPE_DOUBLE)
3562 : : # endif
3563 : : if (dp->conversion == 'f' || dp->conversion == 'F')
3564 : : {
3565 : : double arg = a.arg[dp->arg_index].a.a_double;
3566 : : if (!(isnand (arg) || arg + arg == arg))
3567 : : {
3568 : : /* arg is finite and nonzero. */
3569 : : int exponent = floorlog10 (arg < 0 ? -arg : arg);
3570 : : if (exponent >= 0 && tmp_length < exponent + precision)
3571 : : tmp_length = exponent + precision;
3572 : : }
3573 : : }
3574 : : # endif
3575 : : /* Account for sign, decimal point etc. */
3576 : : tmp_length = xsum (tmp_length, 12);
3577 : :
3578 : : if (tmp_length < width)
3579 : : tmp_length = width;
3580 : :
3581 : : tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
3582 : :
3583 : : if (tmp_length <= sizeof (tmpbuf) / sizeof (DCHAR_T))
3584 : : tmp = tmpbuf;
3585 : : else
3586 : : {
3587 : : size_t tmp_memsize = xtimes (tmp_length, sizeof (DCHAR_T));
3588 : :
3589 : : if (size_overflow_p (tmp_memsize))
3590 : : /* Overflow, would lead to out of memory. */
3591 : : goto out_of_memory;
3592 : : tmp = (DCHAR_T *) malloc (tmp_memsize);
3593 : : if (tmp == NULL)
3594 : : /* Out of memory. */
3595 : : goto out_of_memory;
3596 : : }
3597 : :
3598 : : pad_ptr = NULL;
3599 : : p = tmp;
3600 : :
3601 : : # if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE
3602 : : # if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
3603 : : if (type == TYPE_LONGDOUBLE)
3604 : : # endif
3605 : : {
3606 : : long double arg = a.arg[dp->arg_index].a.a_longdouble;
3607 : :
3608 : : if (isnanl (arg))
3609 : : {
3610 : : if (dp->conversion >= 'A' && dp->conversion <= 'Z')
3611 : : {
3612 : : *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
3613 : : }
3614 : : else
3615 : : {
3616 : : *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
3617 : : }
3618 : : }
3619 : : else
3620 : : {
3621 : : int sign = 0;
3622 : : DECL_LONG_DOUBLE_ROUNDING
3623 : :
3624 : : BEGIN_LONG_DOUBLE_ROUNDING ();
3625 : :
3626 : : if (signbit (arg)) /* arg < 0.0L or negative zero */
3627 : : {
3628 : : sign = -1;
3629 : : arg = -arg;
3630 : : }
3631 : :
3632 : : if (sign < 0)
3633 : : *p++ = '-';
3634 : : else if (flags & FLAG_SHOWSIGN)
3635 : : *p++ = '+';
3636 : : else if (flags & FLAG_SPACE)
3637 : : *p++ = ' ';
3638 : :
3639 : : if (arg > 0.0L && arg + arg == arg)
3640 : : {
3641 : : if (dp->conversion >= 'A' && dp->conversion <= 'Z')
3642 : : {
3643 : : *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
3644 : : }
3645 : : else
3646 : : {
3647 : : *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
3648 : : }
3649 : : }
3650 : : else
3651 : : {
3652 : : # if NEED_PRINTF_LONG_DOUBLE
3653 : : pad_ptr = p;
3654 : :
3655 : : if (dp->conversion == 'f' || dp->conversion == 'F')
3656 : : {
3657 : : char *digits;
3658 : : size_t ndigits;
3659 : :
3660 : : digits =
3661 : : scale10_round_decimal_long_double (arg, precision);
3662 : : if (digits == NULL)
3663 : : {
3664 : : END_LONG_DOUBLE_ROUNDING ();
3665 : : goto out_of_memory;
3666 : : }
3667 : : ndigits = strlen (digits);
3668 : :
3669 : : if (ndigits > precision)
3670 : : do
3671 : : {
3672 : : --ndigits;
3673 : : *p++ = digits[ndigits];
3674 : : }
3675 : : while (ndigits > precision);
3676 : : else
3677 : : *p++ = '0';
3678 : : /* Here ndigits <= precision. */
3679 : : if ((flags & FLAG_ALT) || precision > 0)
3680 : : {
3681 : : *p++ = decimal_point_char ();
3682 : : for (; precision > ndigits; precision--)
3683 : : *p++ = '0';
3684 : : while (ndigits > 0)
3685 : : {
3686 : : --ndigits;
3687 : : *p++ = digits[ndigits];
3688 : : }
3689 : : }
3690 : :
3691 : : free (digits);
3692 : : }
3693 : : else if (dp->conversion == 'e' || dp->conversion == 'E')
3694 : : {
3695 : : int exponent;
3696 : :
3697 : : if (arg == 0.0L)
3698 : : {
3699 : : exponent = 0;
3700 : : *p++ = '0';
3701 : : if ((flags & FLAG_ALT) || precision > 0)
3702 : : {
3703 : : *p++ = decimal_point_char ();
3704 : : for (; precision > 0; precision--)
3705 : : *p++ = '0';
3706 : : }
3707 : : }
3708 : : else
3709 : : {
3710 : : /* arg > 0.0L. */
3711 : : int adjusted;
3712 : : char *digits;
3713 : : size_t ndigits;
3714 : :
3715 : : exponent = floorlog10l (arg);
3716 : : adjusted = 0;
3717 : : for (;;)
3718 : : {
3719 : : digits =
3720 : : scale10_round_decimal_long_double (arg,
3721 : : (int)precision - exponent);
3722 : : if (digits == NULL)
3723 : : {
3724 : : END_LONG_DOUBLE_ROUNDING ();
3725 : : goto out_of_memory;
3726 : : }
3727 : : ndigits = strlen (digits);
3728 : :
3729 : : if (ndigits == precision + 1)
3730 : : break;
3731 : : if (ndigits < precision
3732 : : || ndigits > precision + 2)
3733 : : /* The exponent was not guessed
3734 : : precisely enough. */
3735 : : abort ();
3736 : : if (adjusted)
3737 : : /* None of two values of exponent is
3738 : : the right one. Prevent an endless
3739 : : loop. */
3740 : : abort ();
3741 : : free (digits);
3742 : : if (ndigits == precision)
3743 : : exponent -= 1;
3744 : : else
3745 : : exponent += 1;
3746 : : adjusted = 1;
3747 : : }
3748 : : /* Here ndigits = precision+1. */
3749 : : if (is_borderline (digits, precision))
3750 : : {
3751 : : /* Maybe the exponent guess was too high
3752 : : and a smaller exponent can be reached
3753 : : by turning a 10...0 into 9...9x. */
3754 : : char *digits2 =
3755 : : scale10_round_decimal_long_double (arg,
3756 : : (int)precision - exponent + 1);
3757 : : if (digits2 == NULL)
3758 : : {
3759 : : free (digits);
3760 : : END_LONG_DOUBLE_ROUNDING ();
3761 : : goto out_of_memory;
3762 : : }
3763 : : if (strlen (digits2) == precision + 1)
3764 : : {
3765 : : free (digits);
3766 : : digits = digits2;
3767 : : exponent -= 1;
3768 : : }
3769 : : else
3770 : : free (digits2);
3771 : : }
3772 : : /* Here ndigits = precision+1. */
3773 : :
3774 : : *p++ = digits[--ndigits];
3775 : : if ((flags & FLAG_ALT) || precision > 0)
3776 : : {
3777 : : *p++ = decimal_point_char ();
3778 : : while (ndigits > 0)
3779 : : {
3780 : : --ndigits;
3781 : : *p++ = digits[ndigits];
3782 : : }
3783 : : }
3784 : :
3785 : : free (digits);
3786 : : }
3787 : :
3788 : : *p++ = dp->conversion; /* 'e' or 'E' */
3789 : : # if WIDE_CHAR_VERSION
3790 : : {
3791 : : static const wchar_t decimal_format[] =
3792 : : { '%', '+', '.', '2', 'd', '\0' };
3793 : : SNPRINTF (p, 6 + 1, decimal_format, exponent);
3794 : : }
3795 : : while (*p != '\0')
3796 : : p++;
3797 : : # else
3798 : : if (sizeof (DCHAR_T) == 1)
3799 : : {
3800 : : sprintf ((char *) p, "%+.2d", exponent);
3801 : : while (*p != '\0')
3802 : : p++;
3803 : : }
3804 : : else
3805 : : {
3806 : : char expbuf[6 + 1];
3807 : : const char *ep;
3808 : : sprintf (expbuf, "%+.2d", exponent);
3809 : : for (ep = expbuf; (*p = *ep) != '\0'; ep++)
3810 : : p++;
3811 : : }
3812 : : # endif
3813 : : }
3814 : : else if (dp->conversion == 'g' || dp->conversion == 'G')
3815 : : {
3816 : : if (precision == 0)
3817 : : precision = 1;
3818 : : /* precision >= 1. */
3819 : :
3820 : : if (arg == 0.0L)
3821 : : /* The exponent is 0, >= -4, < precision.
3822 : : Use fixed-point notation. */
3823 : : {
3824 : : size_t ndigits = precision;
3825 : : /* Number of trailing zeroes that have to be
3826 : : dropped. */
3827 : : size_t nzeroes =
3828 : : (flags & FLAG_ALT ? 0 : precision - 1);
3829 : :
3830 : : --ndigits;
3831 : : *p++ = '0';
3832 : : if ((flags & FLAG_ALT) || ndigits > nzeroes)
3833 : : {
3834 : : *p++ = decimal_point_char ();
3835 : : while (ndigits > nzeroes)
3836 : : {
3837 : : --ndigits;
3838 : : *p++ = '0';
3839 : : }
3840 : : }
3841 : : }
3842 : : else
3843 : : {
3844 : : /* arg > 0.0L. */
3845 : : int exponent;
3846 : : int adjusted;
3847 : : char *digits;
3848 : : size_t ndigits;
3849 : : size_t nzeroes;
3850 : :
3851 : : exponent = floorlog10l (arg);
3852 : : adjusted = 0;
3853 : : for (;;)
3854 : : {
3855 : : digits =
3856 : : scale10_round_decimal_long_double (arg,
3857 : : (int)(precision - 1) - exponent);
3858 : : if (digits == NULL)
3859 : : {
3860 : : END_LONG_DOUBLE_ROUNDING ();
3861 : : goto out_of_memory;
3862 : : }
3863 : : ndigits = strlen (digits);
3864 : :
3865 : : if (ndigits == precision)
3866 : : break;
3867 : : if (ndigits < precision - 1
3868 : : || ndigits > precision + 1)
3869 : : /* The exponent was not guessed
3870 : : precisely enough. */
3871 : : abort ();
3872 : : if (adjusted)
3873 : : /* None of two values of exponent is
3874 : : the right one. Prevent an endless
3875 : : loop. */
3876 : : abort ();
3877 : : free (digits);
3878 : : if (ndigits < precision)
3879 : : exponent -= 1;
3880 : : else
3881 : : exponent += 1;
3882 : : adjusted = 1;
3883 : : }
3884 : : /* Here ndigits = precision. */
3885 : : if (is_borderline (digits, precision - 1))
3886 : : {
3887 : : /* Maybe the exponent guess was too high
3888 : : and a smaller exponent can be reached
3889 : : by turning a 10...0 into 9...9x. */
3890 : : char *digits2 =
3891 : : scale10_round_decimal_long_double (arg,
3892 : : (int)(precision - 1) - exponent + 1);
3893 : : if (digits2 == NULL)
3894 : : {
3895 : : free (digits);
3896 : : END_LONG_DOUBLE_ROUNDING ();
3897 : : goto out_of_memory;
3898 : : }
3899 : : if (strlen (digits2) == precision)
3900 : : {
3901 : : free (digits);
3902 : : digits = digits2;
3903 : : exponent -= 1;
3904 : : }
3905 : : else
3906 : : free (digits2);
3907 : : }
3908 : : /* Here ndigits = precision. */
3909 : :
3910 : : /* Determine the number of trailing zeroes
3911 : : that have to be dropped. */
3912 : : nzeroes = 0;
3913 : : if ((flags & FLAG_ALT) == 0)
3914 : : while (nzeroes < ndigits
3915 : : && digits[nzeroes] == '0')
3916 : : nzeroes++;
3917 : :
3918 : : /* The exponent is now determined. */
3919 : : if (exponent >= -4
3920 : : && exponent < (long)precision)
3921 : : {
3922 : : /* Fixed-point notation:
3923 : : max(exponent,0)+1 digits, then the
3924 : : decimal point, then the remaining
3925 : : digits without trailing zeroes. */
3926 : : if (exponent >= 0)
3927 : : {
3928 : : size_t count = exponent + 1;
3929 : : /* Note: count <= precision = ndigits. */
3930 : : for (; count > 0; count--)
3931 : : *p++ = digits[--ndigits];
3932 : : if ((flags & FLAG_ALT) || ndigits > nzeroes)
3933 : : {
3934 : : *p++ = decimal_point_char ();
3935 : : while (ndigits > nzeroes)
3936 : : {
3937 : : --ndigits;
3938 : : *p++ = digits[ndigits];
3939 : : }
3940 : : }
3941 : : }
3942 : : else
3943 : : {
3944 : : size_t count = -exponent - 1;
3945 : : *p++ = '0';
3946 : : *p++ = decimal_point_char ();
3947 : : for (; count > 0; count--)
3948 : : *p++ = '0';
3949 : : while (ndigits > nzeroes)
3950 : : {
3951 : : --ndigits;
3952 : : *p++ = digits[ndigits];
3953 : : }
3954 : : }
3955 : : }
3956 : : else
3957 : : {
3958 : : /* Exponential notation. */
3959 : : *p++ = digits[--ndigits];
3960 : : if ((flags & FLAG_ALT) || ndigits > nzeroes)
3961 : : {
3962 : : *p++ = decimal_point_char ();
3963 : : while (ndigits > nzeroes)
3964 : : {
3965 : : --ndigits;
3966 : : *p++ = digits[ndigits];
3967 : : }
3968 : : }
3969 : : *p++ = dp->conversion - 'G' + 'E'; /* 'e' or 'E' */
3970 : : # if WIDE_CHAR_VERSION
3971 : : {
3972 : : static const wchar_t decimal_format[] =
3973 : : { '%', '+', '.', '2', 'd', '\0' };
3974 : : SNPRINTF (p, 6 + 1, decimal_format, exponent);
3975 : : }
3976 : : while (*p != '\0')
3977 : : p++;
3978 : : # else
3979 : : if (sizeof (DCHAR_T) == 1)
3980 : : {
3981 : : sprintf ((char *) p, "%+.2d", exponent);
3982 : : while (*p != '\0')
3983 : : p++;
3984 : : }
3985 : : else
3986 : : {
3987 : : char expbuf[6 + 1];
3988 : : const char *ep;
3989 : : sprintf (expbuf, "%+.2d", exponent);
3990 : : for (ep = expbuf; (*p = *ep) != '\0'; ep++)
3991 : : p++;
3992 : : }
3993 : : # endif
3994 : : }
3995 : :
3996 : : free (digits);
3997 : : }
3998 : : }
3999 : : else
4000 : : abort ();
4001 : : # else
4002 : : /* arg is finite. */
4003 : : if (!(arg == 0.0L))
4004 : : abort ();
4005 : :
4006 : : pad_ptr = p;
4007 : :
4008 : : if (dp->conversion == 'f' || dp->conversion == 'F')
4009 : : {
4010 : : *p++ = '0';
4011 : : if ((flags & FLAG_ALT) || precision > 0)
4012 : : {
4013 : : *p++ = decimal_point_char ();
4014 : : for (; precision > 0; precision--)
4015 : : *p++ = '0';
4016 : : }
4017 : : }
4018 : : else if (dp->conversion == 'e' || dp->conversion == 'E')
4019 : : {
4020 : : *p++ = '0';
4021 : : if ((flags & FLAG_ALT) || precision > 0)
4022 : : {
4023 : : *p++ = decimal_point_char ();
4024 : : for (; precision > 0; precision--)
4025 : : *p++ = '0';
4026 : : }
4027 : : *p++ = dp->conversion; /* 'e' or 'E' */
4028 : : *p++ = '+';
4029 : : *p++ = '0';
4030 : : *p++ = '0';
4031 : : }
4032 : : else if (dp->conversion == 'g' || dp->conversion == 'G')
4033 : : {
4034 : : *p++ = '0';
4035 : : if (flags & FLAG_ALT)
4036 : : {
4037 : : size_t ndigits =
4038 : : (precision > 0 ? precision - 1 : 0);
4039 : : *p++ = decimal_point_char ();
4040 : : for (; ndigits > 0; --ndigits)
4041 : : *p++ = '0';
4042 : : }
4043 : : }
4044 : : else if (dp->conversion == 'a' || dp->conversion == 'A')
4045 : : {
4046 : : *p++ = '0';
4047 : : *p++ = dp->conversion - 'A' + 'X';
4048 : : pad_ptr = p;
4049 : : *p++ = '0';
4050 : : if ((flags & FLAG_ALT) || precision > 0)
4051 : : {
4052 : : *p++ = decimal_point_char ();
4053 : : for (; precision > 0; precision--)
4054 : : *p++ = '0';
4055 : : }
4056 : : *p++ = dp->conversion - 'A' + 'P';
4057 : : *p++ = '+';
4058 : : *p++ = '0';
4059 : : }
4060 : : else
4061 : : abort ();
4062 : : # endif
4063 : : }
4064 : :
4065 : : END_LONG_DOUBLE_ROUNDING ();
4066 : : }
4067 : : }
4068 : : # if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
4069 : : else
4070 : : # endif
4071 : : # endif
4072 : : # if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
4073 : : {
4074 : : double arg = a.arg[dp->arg_index].a.a_double;
4075 : :
4076 : : if (isnand (arg))
4077 : : {
4078 : : if (dp->conversion >= 'A' && dp->conversion <= 'Z')
4079 : : {
4080 : : *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
4081 : : }
4082 : : else
4083 : : {
4084 : : *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
4085 : : }
4086 : : }
4087 : : else
4088 : : {
4089 : : int sign = 0;
4090 : :
4091 : : if (signbit (arg)) /* arg < 0.0 or negative zero */
4092 : : {
4093 : : sign = -1;
4094 : : arg = -arg;
4095 : : }
4096 : :
4097 : : if (sign < 0)
4098 : : *p++ = '-';
4099 : : else if (flags & FLAG_SHOWSIGN)
4100 : : *p++ = '+';
4101 : : else if (flags & FLAG_SPACE)
4102 : : *p++ = ' ';
4103 : :
4104 : : if (arg > 0.0 && arg + arg == arg)
4105 : : {
4106 : : if (dp->conversion >= 'A' && dp->conversion <= 'Z')
4107 : : {
4108 : : *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
4109 : : }
4110 : : else
4111 : : {
4112 : : *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
4113 : : }
4114 : : }
4115 : : else
4116 : : {
4117 : : # if NEED_PRINTF_DOUBLE
4118 : : pad_ptr = p;
4119 : :
4120 : : if (dp->conversion == 'f' || dp->conversion == 'F')
4121 : : {
4122 : : char *digits;
4123 : : size_t ndigits;
4124 : :
4125 : : digits =
4126 : : scale10_round_decimal_double (arg, precision);
4127 : : if (digits == NULL)
4128 : : goto out_of_memory;
4129 : : ndigits = strlen (digits);
4130 : :
4131 : : if (ndigits > precision)
4132 : : do
4133 : : {
4134 : : --ndigits;
4135 : : *p++ = digits[ndigits];
4136 : : }
4137 : : while (ndigits > precision);
4138 : : else
4139 : : *p++ = '0';
4140 : : /* Here ndigits <= precision. */
4141 : : if ((flags & FLAG_ALT) || precision > 0)
4142 : : {
4143 : : *p++ = decimal_point_char ();
4144 : : for (; precision > ndigits; precision--)
4145 : : *p++ = '0';
4146 : : while (ndigits > 0)
4147 : : {
4148 : : --ndigits;
4149 : : *p++ = digits[ndigits];
4150 : : }
4151 : : }
4152 : :
4153 : : free (digits);
4154 : : }
4155 : : else if (dp->conversion == 'e' || dp->conversion == 'E')
4156 : : {
4157 : : int exponent;
4158 : :
4159 : : if (arg == 0.0)
4160 : : {
4161 : : exponent = 0;
4162 : : *p++ = '0';
4163 : : if ((flags & FLAG_ALT) || precision > 0)
4164 : : {
4165 : : *p++ = decimal_point_char ();
4166 : : for (; precision > 0; precision--)
4167 : : *p++ = '0';
4168 : : }
4169 : : }
4170 : : else
4171 : : {
4172 : : /* arg > 0.0. */
4173 : : int adjusted;
4174 : : char *digits;
4175 : : size_t ndigits;
4176 : :
4177 : : exponent = floorlog10 (arg);
4178 : : adjusted = 0;
4179 : : for (;;)
4180 : : {
4181 : : digits =
4182 : : scale10_round_decimal_double (arg,
4183 : : (int)precision - exponent);
4184 : : if (digits == NULL)
4185 : : goto out_of_memory;
4186 : : ndigits = strlen (digits);
4187 : :
4188 : : if (ndigits == precision + 1)
4189 : : break;
4190 : : if (ndigits < precision
4191 : : || ndigits > precision + 2)
4192 : : /* The exponent was not guessed
4193 : : precisely enough. */
4194 : : abort ();
4195 : : if (adjusted)
4196 : : /* None of two values of exponent is
4197 : : the right one. Prevent an endless
4198 : : loop. */
4199 : : abort ();
4200 : : free (digits);
4201 : : if (ndigits == precision)
4202 : : exponent -= 1;
4203 : : else
4204 : : exponent += 1;
4205 : : adjusted = 1;
4206 : : }
4207 : : /* Here ndigits = precision+1. */
4208 : : if (is_borderline (digits, precision))
4209 : : {
4210 : : /* Maybe the exponent guess was too high
4211 : : and a smaller exponent can be reached
4212 : : by turning a 10...0 into 9...9x. */
4213 : : char *digits2 =
4214 : : scale10_round_decimal_double (arg,
4215 : : (int)precision - exponent + 1);
4216 : : if (digits2 == NULL)
4217 : : {
4218 : : free (digits);
4219 : : goto out_of_memory;
4220 : : }
4221 : : if (strlen (digits2) == precision + 1)
4222 : : {
4223 : : free (digits);
4224 : : digits = digits2;
4225 : : exponent -= 1;
4226 : : }
4227 : : else
4228 : : free (digits2);
4229 : : }
4230 : : /* Here ndigits = precision+1. */
4231 : :
4232 : : *p++ = digits[--ndigits];
4233 : : if ((flags & FLAG_ALT) || precision > 0)
4234 : : {
4235 : : *p++ = decimal_point_char ();
4236 : : while (ndigits > 0)
4237 : : {
4238 : : --ndigits;
4239 : : *p++ = digits[ndigits];
4240 : : }
4241 : : }
4242 : :
4243 : : free (digits);
4244 : : }
4245 : :
4246 : : *p++ = dp->conversion; /* 'e' or 'E' */
4247 : : # if WIDE_CHAR_VERSION
4248 : : {
4249 : : static const wchar_t decimal_format[] =
4250 : : /* Produce the same number of exponent digits
4251 : : as the native printf implementation. */
4252 : : # if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
4253 : : { '%', '+', '.', '3', 'd', '\0' };
4254 : : # else
4255 : : { '%', '+', '.', '2', 'd', '\0' };
4256 : : # endif
4257 : : SNPRINTF (p, 6 + 1, decimal_format, exponent);
4258 : : }
4259 : : while (*p != '\0')
4260 : : p++;
4261 : : # else
4262 : : {
4263 : : static const char decimal_format[] =
4264 : : /* Produce the same number of exponent digits
4265 : : as the native printf implementation. */
4266 : : # if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
4267 : : "%+.3d";
4268 : : # else
4269 : : "%+.2d";
4270 : : # endif
4271 : : if (sizeof (DCHAR_T) == 1)
4272 : : {
4273 : : sprintf ((char *) p, decimal_format, exponent);
4274 : : while (*p != '\0')
4275 : : p++;
4276 : : }
4277 : : else
4278 : : {
4279 : : char expbuf[6 + 1];
4280 : : const char *ep;
4281 : : sprintf (expbuf, decimal_format, exponent);
4282 : : for (ep = expbuf; (*p = *ep) != '\0'; ep++)
4283 : : p++;
4284 : : }
4285 : : }
4286 : : # endif
4287 : : }
4288 : : else if (dp->conversion == 'g' || dp->conversion == 'G')
4289 : : {
4290 : : if (precision == 0)
4291 : : precision = 1;
4292 : : /* precision >= 1. */
4293 : :
4294 : : if (arg == 0.0)
4295 : : /* The exponent is 0, >= -4, < precision.
4296 : : Use fixed-point notation. */
4297 : : {
4298 : : size_t ndigits = precision;
4299 : : /* Number of trailing zeroes that have to be
4300 : : dropped. */
4301 : : size_t nzeroes =
4302 : : (flags & FLAG_ALT ? 0 : precision - 1);
4303 : :
4304 : : --ndigits;
4305 : : *p++ = '0';
4306 : : if ((flags & FLAG_ALT) || ndigits > nzeroes)
4307 : : {
4308 : : *p++ = decimal_point_char ();
4309 : : while (ndigits > nzeroes)
4310 : : {
4311 : : --ndigits;
4312 : : *p++ = '0';
4313 : : }
4314 : : }
4315 : : }
4316 : : else
4317 : : {
4318 : : /* arg > 0.0. */
4319 : : int exponent;
4320 : : int adjusted;
4321 : : char *digits;
4322 : : size_t ndigits;
4323 : : size_t nzeroes;
4324 : :
4325 : : exponent = floorlog10 (arg);
4326 : : adjusted = 0;
4327 : : for (;;)
4328 : : {
4329 : : digits =
4330 : : scale10_round_decimal_double (arg,
4331 : : (int)(precision - 1) - exponent);
4332 : : if (digits == NULL)
4333 : : goto out_of_memory;
4334 : : ndigits = strlen (digits);
4335 : :
4336 : : if (ndigits == precision)
4337 : : break;
4338 : : if (ndigits < precision - 1
4339 : : || ndigits > precision + 1)
4340 : : /* The exponent was not guessed
4341 : : precisely enough. */
4342 : : abort ();
4343 : : if (adjusted)
4344 : : /* None of two values of exponent is
4345 : : the right one. Prevent an endless
4346 : : loop. */
4347 : : abort ();
4348 : : free (digits);
4349 : : if (ndigits < precision)
4350 : : exponent -= 1;
4351 : : else
4352 : : exponent += 1;
4353 : : adjusted = 1;
4354 : : }
4355 : : /* Here ndigits = precision. */
4356 : : if (is_borderline (digits, precision - 1))
4357 : : {
4358 : : /* Maybe the exponent guess was too high
4359 : : and a smaller exponent can be reached
4360 : : by turning a 10...0 into 9...9x. */
4361 : : char *digits2 =
4362 : : scale10_round_decimal_double (arg,
4363 : : (int)(precision - 1) - exponent + 1);
4364 : : if (digits2 == NULL)
4365 : : {
4366 : : free (digits);
4367 : : goto out_of_memory;
4368 : : }
4369 : : if (strlen (digits2) == precision)
4370 : : {
4371 : : free (digits);
4372 : : digits = digits2;
4373 : : exponent -= 1;
4374 : : }
4375 : : else
4376 : : free (digits2);
4377 : : }
4378 : : /* Here ndigits = precision. */
4379 : :
4380 : : /* Determine the number of trailing zeroes
4381 : : that have to be dropped. */
4382 : : nzeroes = 0;
4383 : : if ((flags & FLAG_ALT) == 0)
4384 : : while (nzeroes < ndigits
4385 : : && digits[nzeroes] == '0')
4386 : : nzeroes++;
4387 : :
4388 : : /* The exponent is now determined. */
4389 : : if (exponent >= -4
4390 : : && exponent < (long)precision)
4391 : : {
4392 : : /* Fixed-point notation:
4393 : : max(exponent,0)+1 digits, then the
4394 : : decimal point, then the remaining
4395 : : digits without trailing zeroes. */
4396 : : if (exponent >= 0)
4397 : : {
4398 : : size_t count = exponent + 1;
4399 : : /* Note: count <= precision = ndigits. */
4400 : : for (; count > 0; count--)
4401 : : *p++ = digits[--ndigits];
4402 : : if ((flags & FLAG_ALT) || ndigits > nzeroes)
4403 : : {
4404 : : *p++ = decimal_point_char ();
4405 : : while (ndigits > nzeroes)
4406 : : {
4407 : : --ndigits;
4408 : : *p++ = digits[ndigits];
4409 : : }
4410 : : }
4411 : : }
4412 : : else
4413 : : {
4414 : : size_t count = -exponent - 1;
4415 : : *p++ = '0';
4416 : : *p++ = decimal_point_char ();
4417 : : for (; count > 0; count--)
4418 : : *p++ = '0';
4419 : : while (ndigits > nzeroes)
4420 : : {
4421 : : --ndigits;
4422 : : *p++ = digits[ndigits];
4423 : : }
4424 : : }
4425 : : }
4426 : : else
4427 : : {
4428 : : /* Exponential notation. */
4429 : : *p++ = digits[--ndigits];
4430 : : if ((flags & FLAG_ALT) || ndigits > nzeroes)
4431 : : {
4432 : : *p++ = decimal_point_char ();
4433 : : while (ndigits > nzeroes)
4434 : : {
4435 : : --ndigits;
4436 : : *p++ = digits[ndigits];
4437 : : }
4438 : : }
4439 : : *p++ = dp->conversion - 'G' + 'E'; /* 'e' or 'E' */
4440 : : # if WIDE_CHAR_VERSION
4441 : : {
4442 : : static const wchar_t decimal_format[] =
4443 : : /* Produce the same number of exponent digits
4444 : : as the native printf implementation. */
4445 : : # if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
4446 : : { '%', '+', '.', '3', 'd', '\0' };
4447 : : # else
4448 : : { '%', '+', '.', '2', 'd', '\0' };
4449 : : # endif
4450 : : SNPRINTF (p, 6 + 1, decimal_format, exponent);
4451 : : }
4452 : : while (*p != '\0')
4453 : : p++;
4454 : : # else
4455 : : {
4456 : : static const char decimal_format[] =
4457 : : /* Produce the same number of exponent digits
4458 : : as the native printf implementation. */
4459 : : # if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
4460 : : "%+.3d";
4461 : : # else
4462 : : "%+.2d";
4463 : : # endif
4464 : : if (sizeof (DCHAR_T) == 1)
4465 : : {
4466 : : sprintf ((char *) p, decimal_format, exponent);
4467 : : while (*p != '\0')
4468 : : p++;
4469 : : }
4470 : : else
4471 : : {
4472 : : char expbuf[6 + 1];
4473 : : const char *ep;
4474 : : sprintf (expbuf, decimal_format, exponent);
4475 : : for (ep = expbuf; (*p = *ep) != '\0'; ep++)
4476 : : p++;
4477 : : }
4478 : : }
4479 : : # endif
4480 : : }
4481 : :
4482 : : free (digits);
4483 : : }
4484 : : }
4485 : : else
4486 : : abort ();
4487 : : # else
4488 : : /* arg is finite. */
4489 : : if (!(arg == 0.0))
4490 : : abort ();
4491 : :
4492 : : pad_ptr = p;
4493 : :
4494 : : if (dp->conversion == 'f' || dp->conversion == 'F')
4495 : : {
4496 : : *p++ = '0';
4497 : : if ((flags & FLAG_ALT) || precision > 0)
4498 : : {
4499 : : *p++ = decimal_point_char ();
4500 : : for (; precision > 0; precision--)
4501 : : *p++ = '0';
4502 : : }
4503 : : }
4504 : : else if (dp->conversion == 'e' || dp->conversion == 'E')
4505 : : {
4506 : : *p++ = '0';
4507 : : if ((flags & FLAG_ALT) || precision > 0)
4508 : : {
4509 : : *p++ = decimal_point_char ();
4510 : : for (; precision > 0; precision--)
4511 : : *p++ = '0';
4512 : : }
4513 : : *p++ = dp->conversion; /* 'e' or 'E' */
4514 : : *p++ = '+';
4515 : : /* Produce the same number of exponent digits as
4516 : : the native printf implementation. */
4517 : : # if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
4518 : : *p++ = '0';
4519 : : # endif
4520 : : *p++ = '0';
4521 : : *p++ = '0';
4522 : : }
4523 : : else if (dp->conversion == 'g' || dp->conversion == 'G')
4524 : : {
4525 : : *p++ = '0';
4526 : : if (flags & FLAG_ALT)
4527 : : {
4528 : : size_t ndigits =
4529 : : (precision > 0 ? precision - 1 : 0);
4530 : : *p++ = decimal_point_char ();
4531 : : for (; ndigits > 0; --ndigits)
4532 : : *p++ = '0';
4533 : : }
4534 : : }
4535 : : else
4536 : : abort ();
4537 : : # endif
4538 : : }
4539 : : }
4540 : : }
4541 : : # endif
4542 : :
4543 : : /* The generated string now extends from tmp to p, with the
4544 : : zero padding insertion point being at pad_ptr. */
4545 : : if (has_width && p - tmp < width)
4546 : : {
4547 : : size_t pad = width - (p - tmp);
4548 : : DCHAR_T *end = p + pad;
4549 : :
4550 : : if (flags & FLAG_LEFT)
4551 : : {
4552 : : /* Pad with spaces on the right. */
4553 : : for (; pad > 0; pad--)
4554 : : *p++ = ' ';
4555 : : }
4556 : : else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
4557 : : {
4558 : : /* Pad with zeroes. */
4559 : : DCHAR_T *q = end;
4560 : :
4561 : : while (p > pad_ptr)
4562 : : *--q = *--p;
4563 : : for (; pad > 0; pad--)
4564 : : *p++ = '0';
4565 : : }
4566 : : else
4567 : : {
4568 : : /* Pad with spaces on the left. */
4569 : : DCHAR_T *q = end;
4570 : :
4571 : : while (p > tmp)
4572 : : *--q = *--p;
4573 : : for (; pad > 0; pad--)
4574 : : *p++ = ' ';
4575 : : }
4576 : :
4577 : : p = end;
4578 : : }
4579 : :
4580 : : {
4581 : : size_t count = p - tmp;
4582 : :
4583 : : if (count >= tmp_length)
4584 : : /* tmp_length was incorrectly calculated - fix the
4585 : : code above! */
4586 : : abort ();
4587 : :
4588 : : /* Make room for the result. */
4589 : : if (count >= allocated - length)
4590 : : {
4591 : : size_t n = xsum (length, count);
4592 : :
4593 : : ENSURE_ALLOCATION (n);
4594 : : }
4595 : :
4596 : : /* Append the result. */
4597 : : memcpy (result + length, tmp, count * sizeof (DCHAR_T));
4598 : : if (tmp != tmpbuf)
4599 : : free (tmp);
4600 : : length += count;
4601 : : }
4602 : : }
4603 : : #endif
4604 : : else
4605 : : {
4606 : 36 : arg_type type = a.arg[dp->arg_index].type;
4607 : 36 : int flags = dp->flags;
4608 : : #if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
4609 : : int has_width;
4610 : : size_t width;
4611 : : #endif
4612 : : #if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || NEED_PRINTF_UNBOUNDED_PRECISION
4613 : : int has_precision;
4614 : : size_t precision;
4615 : : #endif
4616 : : #if NEED_PRINTF_UNBOUNDED_PRECISION
4617 : : int prec_ourselves;
4618 : : #else
4619 : : # define prec_ourselves 0
4620 : : #endif
4621 : : #if NEED_PRINTF_FLAG_LEFTADJUST
4622 : : # define pad_ourselves 1
4623 : : #elif !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
4624 : : int pad_ourselves;
4625 : : #else
4626 : : # define pad_ourselves 0
4627 : : #endif
4628 : : TCHAR_T *fbp;
4629 : : unsigned int prefix_count;
4630 : : int prefixes[2] IF_LINT (= { 0 });
4631 : : int orig_errno;
4632 : : #if !USE_SNPRINTF
4633 : : size_t tmp_length;
4634 : : TCHAR_T tmpbuf[700];
4635 : : TCHAR_T *tmp;
4636 : : #endif
4637 : :
4638 : : #if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
4639 : : has_width = 0;
4640 : : width = 0;
4641 : : if (dp->width_start != dp->width_end)
4642 : : {
4643 : : if (dp->width_arg_index != ARG_NONE)
4644 : : {
4645 : : int arg;
4646 : :
4647 : : if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
4648 : : abort ();
4649 : : arg = a.arg[dp->width_arg_index].a.a_int;
4650 : : if (arg < 0)
4651 : : {
4652 : : /* "A negative field width is taken as a '-' flag
4653 : : followed by a positive field width." */
4654 : : flags |= FLAG_LEFT;
4655 : : width = (unsigned int) (-arg);
4656 : : }
4657 : : else
4658 : : width = arg;
4659 : : }
4660 : : else
4661 : : {
4662 : : const FCHAR_T *digitp = dp->width_start;
4663 : :
4664 : : do
4665 : : width = xsum (xtimes (width, 10), *digitp++ - '0');
4666 : : while (digitp != dp->width_end);
4667 : : }
4668 : : has_width = 1;
4669 : : }
4670 : : #endif
4671 : :
4672 : : #if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || NEED_PRINTF_UNBOUNDED_PRECISION
4673 : : has_precision = 0;
4674 : : precision = 6;
4675 : : if (dp->precision_start != dp->precision_end)
4676 : : {
4677 : : if (dp->precision_arg_index != ARG_NONE)
4678 : : {
4679 : : int arg;
4680 : :
4681 : : if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
4682 : : abort ();
4683 : : arg = a.arg[dp->precision_arg_index].a.a_int;
4684 : : /* "A negative precision is taken as if the precision
4685 : : were omitted." */
4686 : : if (arg >= 0)
4687 : : {
4688 : : precision = arg;
4689 : : has_precision = 1;
4690 : : }
4691 : : }
4692 : : else
4693 : : {
4694 : : const FCHAR_T *digitp = dp->precision_start + 1;
4695 : :
4696 : : precision = 0;
4697 : : while (digitp != dp->precision_end)
4698 : : precision = xsum (xtimes (precision, 10), *digitp++ - '0');
4699 : : has_precision = 1;
4700 : : }
4701 : : }
4702 : : #endif
4703 : :
4704 : : /* Decide whether to handle the precision ourselves. */
4705 : : #if NEED_PRINTF_UNBOUNDED_PRECISION
4706 : : switch (dp->conversion)
4707 : : {
4708 : : case 'd': case 'i': case 'u':
4709 : : case 'o':
4710 : : case 'x': case 'X': case 'p':
4711 : : prec_ourselves = has_precision && (precision > 0);
4712 : : break;
4713 : : default:
4714 : : prec_ourselves = 0;
4715 : : break;
4716 : : }
4717 : : #endif
4718 : :
4719 : : /* Decide whether to perform the padding ourselves. */
4720 : : #if !NEED_PRINTF_FLAG_LEFTADJUST && (!DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION)
4721 : : switch (dp->conversion)
4722 : : {
4723 : : # if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO
4724 : : /* If we need conversion from TCHAR_T[] to DCHAR_T[], we need
4725 : : to perform the padding after this conversion. Functions
4726 : : with unistdio extensions perform the padding based on
4727 : : character count rather than element count. */
4728 : : case 'c': case 's':
4729 : : # endif
4730 : : # if NEED_PRINTF_FLAG_ZERO
4731 : : case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
4732 : : case 'a': case 'A':
4733 : : # endif
4734 : : pad_ourselves = 1;
4735 : : break;
4736 : : default:
4737 : : pad_ourselves = prec_ourselves;
4738 : : break;
4739 : : }
4740 : : #endif
4741 : :
4742 : : #if !USE_SNPRINTF
4743 : : /* Allocate a temporary buffer of sufficient size for calling
4744 : : sprintf. */
4745 : : tmp_length =
4746 : : MAX_ROOM_NEEDED (&a, dp->arg_index, dp->conversion, type,
4747 : : flags, width, has_precision, precision,
4748 : : pad_ourselves);
4749 : :
4750 : : if (tmp_length <= sizeof (tmpbuf) / sizeof (TCHAR_T))
4751 : : tmp = tmpbuf;
4752 : : else
4753 : : {
4754 : : size_t tmp_memsize = xtimes (tmp_length, sizeof (TCHAR_T));
4755 : :
4756 : : if (size_overflow_p (tmp_memsize))
4757 : : /* Overflow, would lead to out of memory. */
4758 : : goto out_of_memory;
4759 : : tmp = (TCHAR_T *) malloc (tmp_memsize);
4760 : : if (tmp == NULL)
4761 : : /* Out of memory. */
4762 : : goto out_of_memory;
4763 : : }
4764 : : #endif
4765 : :
4766 : : /* Construct the format string for calling snprintf or
4767 : : sprintf. */
4768 : 36 : fbp = buf;
4769 : 36 : *fbp++ = '%';
4770 : : #if NEED_PRINTF_FLAG_GROUPING
4771 : : /* The underlying implementation doesn't support the ' flag.
4772 : : Produce no grouping characters in this case; this is
4773 : : acceptable because the grouping is locale dependent. */
4774 : : #else
4775 [ - + ]: 36 : if (flags & FLAG_GROUP)
4776 : 0 : *fbp++ = '\'';
4777 : : #endif
4778 [ - + ]: 36 : if (flags & FLAG_LEFT)
4779 : 0 : *fbp++ = '-';
4780 [ - + ]: 36 : if (flags & FLAG_SHOWSIGN)
4781 : 0 : *fbp++ = '+';
4782 [ - + ]: 36 : if (flags & FLAG_SPACE)
4783 : 0 : *fbp++ = ' ';
4784 [ - + ]: 36 : if (flags & FLAG_ALT)
4785 : 0 : *fbp++ = '#';
4786 : : #if __GLIBC__ >= 2 && !defined __UCLIBC__
4787 [ - + ]: 36 : if (flags & FLAG_LOCALIZED)
4788 : 0 : *fbp++ = 'I';
4789 : : #endif
4790 : : if (!pad_ourselves)
4791 : : {
4792 [ - + ]: 36 : if (flags & FLAG_ZERO)
4793 : 0 : *fbp++ = '0';
4794 [ - + ]: 36 : if (dp->width_start != dp->width_end)
4795 : : {
4796 : 0 : size_t n = dp->width_end - dp->width_start;
4797 : : /* The width specification is known to consist only
4798 : : of standard ASCII characters. */
4799 : : if (sizeof (FCHAR_T) == sizeof (TCHAR_T))
4800 : : {
4801 : 0 : memcpy (fbp, dp->width_start, n * sizeof (TCHAR_T));
4802 : 0 : fbp += n;
4803 : : }
4804 : : else
4805 : : {
4806 : : const FCHAR_T *mp = dp->width_start;
4807 : : do
4808 : : *fbp++ = (unsigned char) *mp++;
4809 : : while (--n > 0);
4810 : : }
4811 : : }
4812 : : }
4813 : : if (!prec_ourselves)
4814 : : {
4815 [ - + ]: 36 : if (dp->precision_start != dp->precision_end)
4816 : : {
4817 : 0 : size_t n = dp->precision_end - dp->precision_start;
4818 : : /* The precision specification is known to consist only
4819 : : of standard ASCII characters. */
4820 : : if (sizeof (FCHAR_T) == sizeof (TCHAR_T))
4821 : : {
4822 : 0 : memcpy (fbp, dp->precision_start, n * sizeof (TCHAR_T));
4823 : 0 : fbp += n;
4824 : : }
4825 : : else
4826 : : {
4827 : : const FCHAR_T *mp = dp->precision_start;
4828 : : do
4829 : : *fbp++ = (unsigned char) *mp++;
4830 : : while (--n > 0);
4831 : : }
4832 : : }
4833 : : }
4834 : :
4835 [ - - - + ]: 36 : switch (type)
4836 : : {
4837 : : #if HAVE_LONG_LONG_INT
4838 : : case TYPE_LONGLONGINT:
4839 : : case TYPE_ULONGLONGINT:
4840 : : # if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
4841 : : *fbp++ = 'I';
4842 : : *fbp++ = '6';
4843 : : *fbp++ = '4';
4844 : : break;
4845 : : # else
4846 : 0 : *fbp++ = 'l';
4847 : : /*FALLTHROUGH*/
4848 : : # endif
4849 : : #endif
4850 : : case TYPE_LONGINT:
4851 : : case TYPE_ULONGINT:
4852 : : #if HAVE_WINT_T
4853 : : case TYPE_WIDE_CHAR:
4854 : : #endif
4855 : : #if HAVE_WCHAR_T
4856 : : case TYPE_WIDE_STRING:
4857 : : #endif
4858 : 0 : *fbp++ = 'l';
4859 : 0 : break;
4860 : : case TYPE_LONGDOUBLE:
4861 : 0 : *fbp++ = 'L';
4862 : 0 : break;
4863 : : default:
4864 : 36 : break;
4865 : : }
4866 : : #if NEED_PRINTF_DIRECTIVE_F
4867 : : if (dp->conversion == 'F')
4868 : : *fbp = 'f';
4869 : : else
4870 : : #endif
4871 : 36 : *fbp = dp->conversion;
4872 : : #if USE_SNPRINTF
4873 : : # if !(((__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)) && !defined __UCLIBC__) || ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__))
4874 : : fbp[1] = '%';
4875 : : fbp[2] = 'n';
4876 : : fbp[3] = '\0';
4877 : : # else
4878 : : /* On glibc2 systems from glibc >= 2.3 - probably also older
4879 : : ones - we know that snprintf's return value conforms to
4880 : : ISO C 99: the tests gl_SNPRINTF_RETVAL_C99 and
4881 : : gl_SNPRINTF_TRUNCATION_C99 pass.
4882 : : Therefore we can avoid using %n in this situation.
4883 : : On glibc2 systems from 2004-10-18 or newer, the use of %n
4884 : : in format strings in writable memory may crash the program
4885 : : (if compiled with _FORTIFY_SOURCE=2), so we should avoid it
4886 : : in this situation. */
4887 : : /* On native Windows systems (such as mingw), we can avoid using
4888 : : %n because:
4889 : : - Although the gl_SNPRINTF_TRUNCATION_C99 test fails,
4890 : : snprintf does not write more than the specified number
4891 : : of bytes. (snprintf (buf, 3, "%d %d", 4567, 89) writes
4892 : : '4', '5', '6' into buf, not '4', '5', '\0'.)
4893 : : - Although the gl_SNPRINTF_RETVAL_C99 test fails, snprintf
4894 : : allows us to recognize the case of an insufficient
4895 : : buffer size: it returns -1 in this case.
4896 : : On native Windows systems (such as mingw) where the OS is
4897 : : Windows Vista, the use of %n in format strings by default
4898 : : crashes the program. See
4899 : : <http://gcc.gnu.org/ml/gcc/2007-06/msg00122.html> and
4900 : : <http://msdn2.microsoft.com/en-us/library/ms175782(VS.80).aspx>
4901 : : So we should avoid %n in this situation. */
4902 : 36 : fbp[1] = '\0';
4903 : : # endif
4904 : : #else
4905 : : fbp[1] = '\0';
4906 : : #endif
4907 : :
4908 : : /* Construct the arguments for calling snprintf or sprintf. */
4909 : 36 : prefix_count = 0;
4910 [ - + ]: 36 : if (!pad_ourselves && dp->width_arg_index != ARG_NONE)
4911 : : {
4912 [ # # ]: 0 : if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
4913 : 0 : abort ();
4914 : 0 : prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int;
4915 : : }
4916 [ - + ]: 36 : if (!prec_ourselves && dp->precision_arg_index != ARG_NONE)
4917 : : {
4918 [ # # ]: 0 : if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
4919 : 0 : abort ();
4920 : 0 : prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int;
4921 : : }
4922 : :
4923 : : #if USE_SNPRINTF
4924 : : /* The SNPRINTF result is appended after result[0..length].
4925 : : The latter is an array of DCHAR_T; SNPRINTF appends an
4926 : : array of TCHAR_T to it. This is possible because
4927 : : sizeof (TCHAR_T) divides sizeof (DCHAR_T) and
4928 : : alignof (TCHAR_T) <= alignof (DCHAR_T). */
4929 : : # define TCHARS_PER_DCHAR (sizeof (DCHAR_T) / sizeof (TCHAR_T))
4930 : : /* Ensure that maxlen below will be >= 2. Needed on BeOS,
4931 : : where an snprintf() with maxlen==1 acts like sprintf(). */
4932 [ + + ][ + + ]: 36 : ENSURE_ALLOCATION (xsum (length,
[ + - ][ - + ]
[ + - ][ - + ]
[ # # ][ + - ]
[ + - ][ - + ]
4933 : : (2 + TCHARS_PER_DCHAR - 1)
4934 : : / TCHARS_PER_DCHAR));
4935 : : /* Prepare checking whether snprintf returns the count
4936 : : via %n. */
4937 : 36 : *(TCHAR_T *) (result + length) = '\0';
4938 : : #endif
4939 : :
4940 : 36 : orig_errno = errno;
4941 : :
4942 : : for (;;)
4943 : : {
4944 : 48 : int count = -1;
4945 : :
4946 : : #if USE_SNPRINTF
4947 : 48 : int retcount = 0;
4948 : 48 : size_t maxlen = allocated - length;
4949 : : /* SNPRINTF can fail if its second argument is
4950 : : > INT_MAX. */
4951 [ - + ]: 48 : if (maxlen > INT_MAX / TCHARS_PER_DCHAR)
4952 : 0 : maxlen = INT_MAX / TCHARS_PER_DCHAR;
4953 : 48 : maxlen = maxlen * TCHARS_PER_DCHAR;
4954 : : # define SNPRINTF_BUF(arg) \
4955 : : switch (prefix_count) \
4956 : : { \
4957 : : case 0: \
4958 : : retcount = SNPRINTF ((TCHAR_T *) (result + length), \
4959 : : maxlen, buf, \
4960 : : arg, &count); \
4961 : : break; \
4962 : : case 1: \
4963 : : retcount = SNPRINTF ((TCHAR_T *) (result + length), \
4964 : : maxlen, buf, \
4965 : : prefixes[0], arg, &count); \
4966 : : break; \
4967 : : case 2: \
4968 : : retcount = SNPRINTF ((TCHAR_T *) (result + length), \
4969 : : maxlen, buf, \
4970 : : prefixes[0], prefixes[1], arg, \
4971 : : &count); \
4972 : : break; \
4973 : : default: \
4974 : : abort (); \
4975 : : }
4976 : : #else
4977 : : # define SNPRINTF_BUF(arg) \
4978 : : switch (prefix_count) \
4979 : : { \
4980 : : case 0: \
4981 : : count = sprintf (tmp, buf, arg); \
4982 : : break; \
4983 : : case 1: \
4984 : : count = sprintf (tmp, buf, prefixes[0], arg); \
4985 : : break; \
4986 : : case 2: \
4987 : : count = sprintf (tmp, buf, prefixes[0], prefixes[1],\
4988 : : arg); \
4989 : : break; \
4990 : : default: \
4991 : : abort (); \
4992 : : }
4993 : : #endif
4994 : :
4995 : 48 : errno = 0;
4996 [ - - - - : 48 : switch (type)
+ - - - -
- - - - -
- - - - ]
4997 : : {
4998 : : case TYPE_SCHAR:
4999 : : {
5000 : 0 : int arg = a.arg[dp->arg_index].a.a_schar;
5001 [ # # # # ]: 0 : SNPRINTF_BUF (arg);
5002 : : }
5003 : 0 : break;
5004 : : case TYPE_UCHAR:
5005 : : {
5006 : 0 : unsigned int arg = a.arg[dp->arg_index].a.a_uchar;
5007 [ # # # # ]: 0 : SNPRINTF_BUF (arg);
5008 : : }
5009 : 0 : break;
5010 : : case TYPE_SHORT:
5011 : : {
5012 : 0 : int arg = a.arg[dp->arg_index].a.a_short;
5013 [ # # # # ]: 0 : SNPRINTF_BUF (arg);
5014 : : }
5015 : 0 : break;
5016 : : case TYPE_USHORT:
5017 : : {
5018 : 0 : unsigned int arg = a.arg[dp->arg_index].a.a_ushort;
5019 [ # # # # ]: 0 : SNPRINTF_BUF (arg);
5020 : : }
5021 : 0 : break;
5022 : : case TYPE_INT:
5023 : : {
5024 : 48 : int arg = a.arg[dp->arg_index].a.a_int;
5025 [ + - - - ]: 48 : SNPRINTF_BUF (arg);
5026 : : }
5027 : 48 : break;
5028 : : case TYPE_UINT:
5029 : : {
5030 : 0 : unsigned int arg = a.arg[dp->arg_index].a.a_uint;
5031 [ # # # # ]: 0 : SNPRINTF_BUF (arg);
5032 : : }
5033 : 0 : break;
5034 : : case TYPE_LONGINT:
5035 : : {
5036 : 0 : long int arg = a.arg[dp->arg_index].a.a_longint;
5037 [ # # # # ]: 0 : SNPRINTF_BUF (arg);
5038 : : }
5039 : 0 : break;
5040 : : case TYPE_ULONGINT:
5041 : : {
5042 : 0 : unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint;
5043 [ # # # # ]: 0 : SNPRINTF_BUF (arg);
5044 : : }
5045 : 0 : break;
5046 : : #if HAVE_LONG_LONG_INT
5047 : : case TYPE_LONGLONGINT:
5048 : : {
5049 : 0 : long long int arg = a.arg[dp->arg_index].a.a_longlongint;
5050 [ # # # # ]: 0 : SNPRINTF_BUF (arg);
5051 : : }
5052 : 0 : break;
5053 : : case TYPE_ULONGLONGINT:
5054 : : {
5055 : 0 : unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint;
5056 [ # # # # ]: 0 : SNPRINTF_BUF (arg);
5057 : : }
5058 : 0 : break;
5059 : : #endif
5060 : : case TYPE_DOUBLE:
5061 : : {
5062 : 0 : double arg = a.arg[dp->arg_index].a.a_double;
5063 [ # # # # ]: 0 : SNPRINTF_BUF (arg);
5064 : : }
5065 : 0 : break;
5066 : : case TYPE_LONGDOUBLE:
5067 : : {
5068 : 0 : long double arg = a.arg[dp->arg_index].a.a_longdouble;
5069 [ # # # # ]: 0 : SNPRINTF_BUF (arg);
5070 : : }
5071 : 0 : break;
5072 : : case TYPE_CHAR:
5073 : : {
5074 : 0 : int arg = a.arg[dp->arg_index].a.a_char;
5075 [ # # # # ]: 0 : SNPRINTF_BUF (arg);
5076 : : }
5077 : 0 : break;
5078 : : #if HAVE_WINT_T
5079 : : case TYPE_WIDE_CHAR:
5080 : : {
5081 : 0 : wint_t arg = a.arg[dp->arg_index].a.a_wide_char;
5082 [ # # # # ]: 0 : SNPRINTF_BUF (arg);
5083 : : }
5084 : 0 : break;
5085 : : #endif
5086 : : case TYPE_STRING:
5087 : : {
5088 : 0 : const char *arg = a.arg[dp->arg_index].a.a_string;
5089 [ # # # # ]: 0 : SNPRINTF_BUF (arg);
5090 : : }
5091 : 0 : break;
5092 : : #if HAVE_WCHAR_T
5093 : : case TYPE_WIDE_STRING:
5094 : : {
5095 : 0 : const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
5096 [ # # # # ]: 0 : SNPRINTF_BUF (arg);
5097 : : }
5098 : 0 : break;
5099 : : #endif
5100 : : case TYPE_POINTER:
5101 : : {
5102 : 0 : void *arg = a.arg[dp->arg_index].a.a_pointer;
5103 [ # # # # ]: 0 : SNPRINTF_BUF (arg);
5104 : : }
5105 : 0 : break;
5106 : : default:
5107 : 0 : abort ();
5108 : : }
5109 : :
5110 : : #if USE_SNPRINTF
5111 : : /* Portability: Not all implementations of snprintf()
5112 : : are ISO C 99 compliant. Determine the number of
5113 : : bytes that snprintf() has produced or would have
5114 : : produced. */
5115 [ - + ]: 48 : if (count >= 0)
5116 : : {
5117 : : /* Verify that snprintf() has NUL-terminated its
5118 : : result. */
5119 [ # # ]: 0 : if (count < maxlen
5120 [ # # ]: 0 : && ((TCHAR_T *) (result + length)) [count] != '\0')
5121 : 0 : abort ();
5122 : : /* Portability hack. */
5123 [ # # ]: 0 : if (retcount > count)
5124 : 0 : count = retcount;
5125 : : }
5126 : : else
5127 : : {
5128 : : /* snprintf() doesn't understand the '%n'
5129 : : directive. */
5130 [ - + ]: 48 : if (fbp[1] != '\0')
5131 : : {
5132 : : /* Don't use the '%n' directive; instead, look
5133 : : at the snprintf() return value. */
5134 : 0 : fbp[1] = '\0';
5135 : 0 : continue;
5136 : : }
5137 : : else
5138 : : {
5139 : : /* Look at the snprintf() return value. */
5140 [ + - ]: 48 : if (retcount < 0)
5141 : : {
5142 : : # if !HAVE_SNPRINTF_RETVAL_C99
5143 : : /* HP-UX 10.20 snprintf() is doubly deficient:
5144 : : It doesn't understand the '%n' directive,
5145 : : *and* it returns -1 (rather than the length
5146 : : that would have been required) when the
5147 : : buffer is too small.
5148 : : But a failure at this point can also come
5149 : : from other reasons than a too small buffer,
5150 : : such as an invalid wide string argument to
5151 : : the %ls directive, or possibly an invalid
5152 : : floating-point argument. */
5153 : : size_t tmp_length =
5154 : : MAX_ROOM_NEEDED (&a, dp->arg_index,
5155 : : dp->conversion, type, flags,
5156 : : width, has_precision,
5157 : : precision, pad_ourselves);
5158 : :
5159 : : if (maxlen < tmp_length)
5160 : : {
5161 : : /* Make more room. But try to do through
5162 : : this reallocation only once. */
5163 : : size_t bigger_need =
5164 : : xsum (length,
5165 : : xsum (tmp_length,
5166 : : TCHARS_PER_DCHAR - 1)
5167 : : / TCHARS_PER_DCHAR);
5168 : : /* And always grow proportionally.
5169 : : (There may be several arguments, each
5170 : : needing a little more room than the
5171 : : previous one.) */
5172 : : size_t bigger_need2 =
5173 : : xsum (xtimes (allocated, 2), 12);
5174 : : if (bigger_need < bigger_need2)
5175 : : bigger_need = bigger_need2;
5176 : : ENSURE_ALLOCATION (bigger_need);
5177 : : continue;
5178 : : }
5179 : : # endif
5180 : : }
5181 : : else
5182 : 48 : count = retcount;
5183 : : }
5184 : : }
5185 : : #endif
5186 : :
5187 : : /* Attempt to handle failure. */
5188 [ - + ]: 48 : if (count < 0)
5189 : : {
5190 : : /* SNPRINTF or sprintf failed. Save and use the errno
5191 : : that it has set, if any. */
5192 : 0 : int saved_errno = errno;
5193 : :
5194 [ # # ][ # # ]: 0 : if (!(result == resultbuf || result == NULL))
5195 : 0 : free (result);
5196 [ # # ]: 0 : if (buf_malloced != NULL)
5197 : 0 : free (buf_malloced);
5198 [ # # ][ # # ]: 0 : CLEANUP ();
5199 : 0 : errno =
5200 : : (saved_errno != 0
5201 : : ? saved_errno
5202 [ # # ][ # # ]: 0 : : (dp->conversion == 'c' || dp->conversion == 's'
5203 : : ? EILSEQ
5204 [ # # ]: 0 : : EINVAL));
5205 : 0 : return NULL;
5206 : : }
5207 : :
5208 : : #if USE_SNPRINTF
5209 : : /* Handle overflow of the allocated buffer.
5210 : : If such an overflow occurs, a C99 compliant snprintf()
5211 : : returns a count >= maxlen. However, a non-compliant
5212 : : snprintf() function returns only count = maxlen - 1. To
5213 : : cover both cases, test whether count >= maxlen - 1. */
5214 [ + + ]: 48 : if ((unsigned int) count + 1 >= maxlen)
5215 : : {
5216 : : /* If maxlen already has attained its allowed maximum,
5217 : : allocating more memory will not increase maxlen.
5218 : : Instead of looping, bail out. */
5219 [ - + ]: 12 : if (maxlen == INT_MAX / TCHARS_PER_DCHAR)
5220 : 0 : goto overflow;
5221 : : else
5222 : : {
5223 : : /* Need at least (count + 1) * sizeof (TCHAR_T)
5224 : : bytes. (The +1 is for the trailing NUL.)
5225 : : But ask for (count + 2) * sizeof (TCHAR_T)
5226 : : bytes, so that in the next round, we likely get
5227 : : maxlen > (unsigned int) count + 1
5228 : : and so we don't get here again.
5229 : : And allocate proportionally, to avoid looping
5230 : : eternally if snprintf() reports a too small
5231 : : count. */
5232 : 12 : size_t n =
5233 [ + - ]: 12 : xmax (xsum (length,
5234 : 12 : ((unsigned int) count + 2
5235 : : + TCHARS_PER_DCHAR - 1)
5236 : : / TCHARS_PER_DCHAR),
5237 : 12 : xtimes (allocated, 2));
5238 : :
5239 [ + - ][ + - ]: 12 : ENSURE_ALLOCATION (n);
[ + - ][ + + ]
[ + - ][ + + ]
[ - + ][ + - ]
[ + + ][ - + ]
5240 : 12 : continue;
5241 : : }
5242 : : }
5243 : : #endif
5244 : :
5245 : : #if NEED_PRINTF_UNBOUNDED_PRECISION
5246 : : if (prec_ourselves)
5247 : : {
5248 : : /* Handle the precision. */
5249 : : TCHAR_T *prec_ptr =
5250 : : # if USE_SNPRINTF
5251 : : (TCHAR_T *) (result + length);
5252 : : # else
5253 : : tmp;
5254 : : # endif
5255 : : size_t prefix_count;
5256 : : size_t move;
5257 : :
5258 : : prefix_count = 0;
5259 : : /* Put the additional zeroes after the sign. */
5260 : : if (count >= 1
5261 : : && (*prec_ptr == '-' || *prec_ptr == '+'
5262 : : || *prec_ptr == ' '))
5263 : : prefix_count = 1;
5264 : : /* Put the additional zeroes after the 0x prefix if
5265 : : (flags & FLAG_ALT) || (dp->conversion == 'p'). */
5266 : : else if (count >= 2
5267 : : && prec_ptr[0] == '0'
5268 : : && (prec_ptr[1] == 'x' || prec_ptr[1] == 'X'))
5269 : : prefix_count = 2;
5270 : :
5271 : : move = count - prefix_count;
5272 : : if (precision > move)
5273 : : {
5274 : : /* Insert zeroes. */
5275 : : size_t insert = precision - move;
5276 : : TCHAR_T *prec_end;
5277 : :
5278 : : # if USE_SNPRINTF
5279 : : size_t n =
5280 : : xsum (length,
5281 : : (count + insert + TCHARS_PER_DCHAR - 1)
5282 : : / TCHARS_PER_DCHAR);
5283 : : length += (count + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR;
5284 : : ENSURE_ALLOCATION (n);
5285 : : length -= (count + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR;
5286 : : prec_ptr = (TCHAR_T *) (result + length);
5287 : : # endif
5288 : :
5289 : : prec_end = prec_ptr + count;
5290 : : prec_ptr += prefix_count;
5291 : :
5292 : : while (prec_end > prec_ptr)
5293 : : {
5294 : : prec_end--;
5295 : : prec_end[insert] = prec_end[0];
5296 : : }
5297 : :
5298 : : prec_end += insert;
5299 : : do
5300 : : *--prec_end = '0';
5301 : : while (prec_end > prec_ptr);
5302 : :
5303 : : count += insert;
5304 : : }
5305 : : }
5306 : : #endif
5307 : :
5308 : : #if !USE_SNPRINTF
5309 : : if (count >= tmp_length)
5310 : : /* tmp_length was incorrectly calculated - fix the
5311 : : code above! */
5312 : : abort ();
5313 : : #endif
5314 : :
5315 : : #if !DCHAR_IS_TCHAR
5316 : : /* Convert from TCHAR_T[] to DCHAR_T[]. */
5317 : : if (dp->conversion == 'c' || dp->conversion == 's')
5318 : : {
5319 : : /* type = TYPE_CHAR or TYPE_WIDE_CHAR or TYPE_STRING
5320 : : TYPE_WIDE_STRING.
5321 : : The result string is not certainly ASCII. */
5322 : : const TCHAR_T *tmpsrc;
5323 : : DCHAR_T *tmpdst;
5324 : : size_t tmpdst_len;
5325 : : /* This code assumes that TCHAR_T is 'char'. */
5326 : : verify (sizeof (TCHAR_T) == 1);
5327 : : # if USE_SNPRINTF
5328 : : tmpsrc = (TCHAR_T *) (result + length);
5329 : : # else
5330 : : tmpsrc = tmp;
5331 : : # endif
5332 : : tmpdst =
5333 : : DCHAR_CONV_FROM_ENCODING (locale_charset (),
5334 : : iconveh_question_mark,
5335 : : tmpsrc, count,
5336 : : NULL,
5337 : : NULL, &tmpdst_len);
5338 : : if (tmpdst == NULL)
5339 : : {
5340 : : int saved_errno = errno;
5341 : : if (!(result == resultbuf || result == NULL))
5342 : : free (result);
5343 : : if (buf_malloced != NULL)
5344 : : free (buf_malloced);
5345 : : CLEANUP ();
5346 : : errno = saved_errno;
5347 : : return NULL;
5348 : : }
5349 : : ENSURE_ALLOCATION (xsum (length, tmpdst_len));
5350 : : DCHAR_CPY (result + length, tmpdst, tmpdst_len);
5351 : : free (tmpdst);
5352 : : count = tmpdst_len;
5353 : : }
5354 : : else
5355 : : {
5356 : : /* The result string is ASCII.
5357 : : Simple 1:1 conversion. */
5358 : : # if USE_SNPRINTF
5359 : : /* If sizeof (DCHAR_T) == sizeof (TCHAR_T), it's a
5360 : : no-op conversion, in-place on the array starting
5361 : : at (result + length). */
5362 : : if (sizeof (DCHAR_T) != sizeof (TCHAR_T))
5363 : : # endif
5364 : : {
5365 : : const TCHAR_T *tmpsrc;
5366 : : DCHAR_T *tmpdst;
5367 : : size_t n;
5368 : :
5369 : : # if USE_SNPRINTF
5370 : : if (result == resultbuf)
5371 : : {
5372 : : tmpsrc = (TCHAR_T *) (result + length);
5373 : : /* ENSURE_ALLOCATION will not move tmpsrc
5374 : : (because it's part of resultbuf). */
5375 : : ENSURE_ALLOCATION (xsum (length, count));
5376 : : }
5377 : : else
5378 : : {
5379 : : /* ENSURE_ALLOCATION will move the array
5380 : : (because it uses realloc(). */
5381 : : ENSURE_ALLOCATION (xsum (length, count));
5382 : : tmpsrc = (TCHAR_T *) (result + length);
5383 : : }
5384 : : # else
5385 : : tmpsrc = tmp;
5386 : : ENSURE_ALLOCATION (xsum (length, count));
5387 : : # endif
5388 : : tmpdst = result + length;
5389 : : /* Copy backwards, because of overlapping. */
5390 : : tmpsrc += count;
5391 : : tmpdst += count;
5392 : : for (n = count; n > 0; n--)
5393 : : *--tmpdst = (unsigned char) *--tmpsrc;
5394 : : }
5395 : : }
5396 : : #endif
5397 : :
5398 : : #if DCHAR_IS_TCHAR && !USE_SNPRINTF
5399 : : /* Make room for the result. */
5400 : : if (count > allocated - length)
5401 : : {
5402 : : /* Need at least count elements. But allocate
5403 : : proportionally. */
5404 : : size_t n =
5405 : : xmax (xsum (length, count), xtimes (allocated, 2));
5406 : :
5407 : : ENSURE_ALLOCATION (n);
5408 : : }
5409 : : #endif
5410 : :
5411 : : /* Here count <= allocated - length. */
5412 : :
5413 : : /* Perform padding. */
5414 : : #if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
5415 : : if (pad_ourselves && has_width)
5416 : : {
5417 : : size_t w;
5418 : : # if ENABLE_UNISTDIO
5419 : : /* Outside POSIX, it's preferable to compare the width
5420 : : against the number of _characters_ of the converted
5421 : : value. */
5422 : : w = DCHAR_MBSNLEN (result + length, count);
5423 : : # else
5424 : : /* The width is compared against the number of _bytes_
5425 : : of the converted value, says POSIX. */
5426 : : w = count;
5427 : : # endif
5428 : : if (w < width)
5429 : : {
5430 : : size_t pad = width - w;
5431 : :
5432 : : /* Make room for the result. */
5433 : : if (xsum (count, pad) > allocated - length)
5434 : : {
5435 : : /* Need at least count + pad elements. But
5436 : : allocate proportionally. */
5437 : : size_t n =
5438 : : xmax (xsum3 (length, count, pad),
5439 : : xtimes (allocated, 2));
5440 : :
5441 : : # if USE_SNPRINTF
5442 : : length += count;
5443 : : ENSURE_ALLOCATION (n);
5444 : : length -= count;
5445 : : # else
5446 : : ENSURE_ALLOCATION (n);
5447 : : # endif
5448 : : }
5449 : : /* Here count + pad <= allocated - length. */
5450 : :
5451 : : {
5452 : : # if !DCHAR_IS_TCHAR || USE_SNPRINTF
5453 : : DCHAR_T * const rp = result + length;
5454 : : # else
5455 : : DCHAR_T * const rp = tmp;
5456 : : # endif
5457 : : DCHAR_T *p = rp + count;
5458 : : DCHAR_T *end = p + pad;
5459 : : DCHAR_T *pad_ptr;
5460 : : # if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO
5461 : : if (dp->conversion == 'c'
5462 : : || dp->conversion == 's')
5463 : : /* No zero-padding for string directives. */
5464 : : pad_ptr = NULL;
5465 : : else
5466 : : # endif
5467 : : {
5468 : : pad_ptr = (*rp == '-' ? rp + 1 : rp);
5469 : : /* No zero-padding of "inf" and "nan". */
5470 : : if ((*pad_ptr >= 'A' && *pad_ptr <= 'Z')
5471 : : || (*pad_ptr >= 'a' && *pad_ptr <= 'z'))
5472 : : pad_ptr = NULL;
5473 : : }
5474 : : /* The generated string now extends from rp to p,
5475 : : with the zero padding insertion point being at
5476 : : pad_ptr. */
5477 : :
5478 : : count = count + pad; /* = end - rp */
5479 : :
5480 : : if (flags & FLAG_LEFT)
5481 : : {
5482 : : /* Pad with spaces on the right. */
5483 : : for (; pad > 0; pad--)
5484 : : *p++ = ' ';
5485 : : }
5486 : : else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
5487 : : {
5488 : : /* Pad with zeroes. */
5489 : : DCHAR_T *q = end;
5490 : :
5491 : : while (p > pad_ptr)
5492 : : *--q = *--p;
5493 : : for (; pad > 0; pad--)
5494 : : *p++ = '0';
5495 : : }
5496 : : else
5497 : : {
5498 : : /* Pad with spaces on the left. */
5499 : : DCHAR_T *q = end;
5500 : :
5501 : : while (p > rp)
5502 : : *--q = *--p;
5503 : : for (; pad > 0; pad--)
5504 : : *p++ = ' ';
5505 : : }
5506 : : }
5507 : : }
5508 : : }
5509 : : #endif
5510 : :
5511 : : /* Here still count <= allocated - length. */
5512 : :
5513 : : #if !DCHAR_IS_TCHAR || USE_SNPRINTF
5514 : : /* The snprintf() result did fit. */
5515 : : #else
5516 : : /* Append the sprintf() result. */
5517 : : memcpy (result + length, tmp, count * sizeof (DCHAR_T));
5518 : : #endif
5519 : : #if !USE_SNPRINTF
5520 : : if (tmp != tmpbuf)
5521 : : free (tmp);
5522 : : #endif
5523 : :
5524 : : #if NEED_PRINTF_DIRECTIVE_F
5525 : : if (dp->conversion == 'F')
5526 : : {
5527 : : /* Convert the %f result to upper case for %F. */
5528 : : DCHAR_T *rp = result + length;
5529 : : size_t rc;
5530 : : for (rc = count; rc > 0; rc--, rp++)
5531 : : if (*rp >= 'a' && *rp <= 'z')
5532 : : *rp = *rp - 'a' + 'A';
5533 : : }
5534 : : #endif
5535 : :
5536 : 36 : length += count;
5537 : 36 : break;
5538 : 12 : }
5539 : 36 : errno = orig_errno;
5540 : : #undef pad_ourselves
5541 : : #undef prec_ourselves
5542 : : }
5543 : : }
5544 : 36 : }
5545 : :
5546 : : /* Add the final NUL. */
5547 [ - + ][ # # ]: 36 : ENSURE_ALLOCATION (xsum (length, 1));
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
5548 : 36 : result[length] = '\0';
5549 : :
5550 [ + + ][ + - ]: 36 : if (result != resultbuf && length + 1 < allocated)
5551 : : {
5552 : : /* Shrink the allocated memory if possible. */
5553 : : DCHAR_T *memory;
5554 : :
5555 : 32 : memory = (DCHAR_T *) realloc (result, (length + 1) * sizeof (DCHAR_T));
5556 [ + - ]: 32 : if (memory != NULL)
5557 : 32 : result = memory;
5558 : : }
5559 : :
5560 [ - + ]: 36 : if (buf_malloced != NULL)
5561 : 0 : free (buf_malloced);
5562 [ - + ][ - + ]: 36 : CLEANUP ();
5563 : 36 : *lengthp = length;
5564 : : /* Note that we can produce a big string of a length > INT_MAX. POSIX
5565 : : says that snprintf() fails with errno = EOVERFLOW in this case, but
5566 : : that's only because snprintf() returns an 'int'. This function does
5567 : : not have this limitation. */
5568 : 36 : return result;
5569 : :
5570 : : #if USE_SNPRINTF
5571 : : overflow:
5572 [ # # ][ # # ]: 0 : if (!(result == resultbuf || result == NULL))
5573 : 0 : free (result);
5574 [ # # ]: 0 : if (buf_malloced != NULL)
5575 : 0 : free (buf_malloced);
5576 [ # # ][ # # ]: 0 : CLEANUP ();
5577 : 0 : errno = EOVERFLOW;
5578 : 0 : return NULL;
5579 : : #endif
5580 : :
5581 : : out_of_memory:
5582 [ # # ][ # # ]: 0 : if (!(result == resultbuf || result == NULL))
5583 : 0 : free (result);
5584 [ # # ]: 0 : if (buf_malloced != NULL)
5585 : 0 : free (buf_malloced);
5586 : : out_of_memory_1:
5587 [ # # ][ # # ]: 0 : CLEANUP ();
5588 : 0 : errno = ENOMEM;
5589 : 36 : return NULL;
5590 : : }
5591 : : }
5592 : :
5593 : : #undef MAX_ROOM_NEEDED
5594 : : #undef TCHARS_PER_DCHAR
5595 : : #undef SNPRINTF
5596 : : #undef USE_SNPRINTF
5597 : : #undef DCHAR_SET
5598 : : #undef DCHAR_CPY
5599 : : #undef PRINTF_PARSE
5600 : : #undef DIRECTIVES
5601 : : #undef DIRECTIVE
5602 : : #undef DCHAR_IS_TCHAR
5603 : : #undef TCHAR_T
5604 : : #undef DCHAR_T
5605 : : #undef FCHAR_T
5606 : : #undef VASNPRINTF
|