File: | libgnu/vasnprintf.c |
Location: | line 5203, column 31 |
Description: | Use of memory after it is freed |
1 | /* vsprintf with automatic memory allocation. | |||
2 | Copyright (C) 1999, 2002-2013 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_SOURCE1 | |||
50 | # define _GNU_SOURCE1 1 | |||
51 | #endif | |||
52 | ||||
53 | #ifndef VASNPRINTF | |||
54 | # include <config.h> | |||
55 | #endif | |||
56 | #ifndef IN_LIBINTL | |||
57 | # include <alloca__builtin_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(*__errno_location ()).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__SNPRINTF0 || HAVE_SNPRINTF1) && !defined __BEOS__ && !(__GNU_LIBRARY__6 == 1) | |||
172 | # define USE_SNPRINTF 1 | |||
173 | # else | |||
174 | # define USE_SNPRINTF 0 | |||
175 | # endif | |||
176 | # if HAVE_DECL__SNPRINTF0 | |||
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 expexpo | |||
207 | #define expexpo expo | |||
208 | #undef remainderrem | |||
209 | #define remainderrem rem | |||
210 | ||||
211 | #if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C991) && !WIDE_CHAR_VERSION | |||
212 | # if (HAVE_STRNLEN1 && !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_C991) && WIDE_CHAR_VERSION) || ((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C991 || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && !WIDE_CHAR_VERSION && DCHAR_IS_TCHAR)) && HAVE_WCHAR_T1 | |||
228 | # if HAVE_WCSLEN1 | |||
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_C991) && HAVE_WCHAR_T1 && WIDE_CHAR_VERSION | |||
251 | # if HAVE_WCSNLEN1 | |||
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 Mac OS 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__2 || 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)extern int (*_gl_verify_function2 (void)) [(!!sizeof (struct { unsigned int _gl_verify_error_if_negative: (sizeof (mp_limb_t ) * 8 == GMP_LIMB_BITS) ? 1 : -1; }))]; | |||
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)extern int (*_gl_verify_function3 (void)) [(!!sizeof (struct { unsigned int _gl_verify_error_if_negative: (sizeof (mp_twolimb_t ) * 8 == GMP_TWOLIMB_BITS) ? 1 : -1; }))]; | |||
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((void*)0)) | |||
381 | return NULL((void*)0); | |||
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((void*)0); | |||
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((void*)0)) | |||
484 | return NULL((void*)0); | |||
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 remainderrem = 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) remainderrem << GMP_LIMB_BITS) | *--sourceptr; | |||
529 | *--destptr = num / den; | |||
530 | remainderrem = num % den; | |||
531 | } | |||
532 | /* Normalise and store r. */ | |||
533 | if (remainderrem > 0) | |||
534 | { | |||
535 | r_ptr[0] = remainderrem; | |||
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__4 > 3 || (__GNUC__4 == 3 && __GNUC_MINOR__2 >= 4) | |||
558 | s = __builtin_clz (msd); | |||
559 | # else | |||
560 | # if defined DBL_EXPBIT0_WORD1 && defined DBL_EXPBIT0_BIT20 | |||
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_EXP1024 - DBL_MIN_EXP(-1021)) | 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_WORD1] >> DBL_EXPBIT0_BIT20) & 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((void*)0)) | |||
617 | { | |||
618 | free (roomptr); | |||
619 | return NULL((void*)0); | |||
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((void*)0)) | |||
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((void*)0)) | |||
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 remainderrem = 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) remainderrem << GMP_LIMB_BITS) | *--ptr; | |||
868 | *ptr = num / 1000000000; | |||
869 | remainderrem = num % 1000000000; | |||
870 | } | |||
871 | /* Store the remainder as 9 decimal digits. */ | |||
872 | for (count = 9; count > 0; count--) | |||
873 | { | |||
874 | *d_ptr++ = '0' + (remainderrem % 10); | |||
875 | remainderrem = remainderrem / 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 expexpo; | |||
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((void*)0)) | |||
911 | return NULL((void*)0); | |||
912 | /* Split into exponential part and mantissa. */ | |||
913 | y = frexpl (x, &expexpo); | |||
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 = expexpo - 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 expexpo; | |||
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((void*)0)) | |||
999 | return NULL((void*)0); | |||
1000 | /* Split into exponential part and mantissa. */ | |||
1001 | y = frexp (x, &expexpo); | |||
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 = expexpo - 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((void*)0)) | |||
1088 | return NULL((void*)0); | |||
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((void*)0)) | |||
1112 | { | |||
1113 | free (memory); | |||
1114 | return NULL((void*)0); | |||
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((void*)0)) | |||
1207 | { | |||
1208 | free (pow5_ptr); | |||
1209 | free (memory); | |||
1210 | return NULL((void*)0); | |||
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((void*)0)) | |||
1234 | { | |||
1235 | free (pow5_ptr); | |||
1236 | free (memory); | |||
1237 | return NULL((void*)0); | |||
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((void*)0)) | |||
1280 | return NULL((void*)0); | |||
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 expexpo; | |||
1331 | long double y; | |||
1332 | double z; | |||
1333 | double l; | |||
1334 | ||||
1335 | /* Split into exponential part and mantissa. */ | |||
1336 | y = frexpl (x, &expexpo); | |||
1337 | if (!(y >= 0.0L && y < 1.0L)) | |||
1338 | abort (); | |||
1339 | if (y == 0.0L) | |||
1340 | return INT_MIN(-2147483647 -1); | |||
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 | expexpo -= GMP_LIMB_BITS; | |||
1347 | } | |||
1348 | if (y < (1.0L / (1 << 16))) | |||
1349 | { | |||
1350 | y *= 1.0L * (1 << 16); | |||
1351 | expexpo -= 16; | |||
1352 | } | |||
1353 | if (y < (1.0L / (1 << 8))) | |||
1354 | { | |||
1355 | y *= 1.0L * (1 << 8); | |||
1356 | expexpo -= 8; | |||
1357 | } | |||
1358 | if (y < (1.0L / (1 << 4))) | |||
1359 | { | |||
1360 | y *= 1.0L * (1 << 4); | |||
1361 | expexpo -= 4; | |||
1362 | } | |||
1363 | if (y < (1.0L / (1 << 2))) | |||
1364 | { | |||
1365 | y *= 1.0L * (1 << 2); | |||
1366 | expexpo -= 2; | |||
1367 | } | |||
1368 | if (y < (1.0L / (1 << 1))) | |||
1369 | { | |||
1370 | y *= 1.0L * (1 << 1); | |||
1371 | expexpo -= 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 = expexpo; | |||
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 expexpo; | |||
1422 | double y; | |||
1423 | double z; | |||
1424 | double l; | |||
1425 | ||||
1426 | /* Split into exponential part and mantissa. */ | |||
1427 | y = frexp (x, &expexpo); | |||
1428 | if (!(y >= 0.0 && y < 1.0)) | |||
1429 | abort (); | |||
1430 | if (y == 0.0) | |||
1431 | return INT_MIN(-2147483647 -1); | |||
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 | expexpo -= GMP_LIMB_BITS; | |||
1438 | } | |||
1439 | if (y < (1.0 / (1 << 16))) | |||
1440 | { | |||
1441 | y *= 1.0 * (1 << 16); | |||
1442 | expexpo -= 16; | |||
1443 | } | |||
1444 | if (y < (1.0 / (1 << 8))) | |||
1445 | { | |||
1446 | y *= 1.0 * (1 << 8); | |||
1447 | expexpo -= 8; | |||
1448 | } | |||
1449 | if (y < (1.0 / (1 << 4))) | |||
1450 | { | |||
1451 | y *= 1.0 * (1 << 4); | |||
1452 | expexpo -= 4; | |||
1453 | } | |||
1454 | if (y < (1.0 / (1 << 2))) | |||
1455 | { | |||
1456 | y *= 1.0 * (1 << 2); | |||
1457 | expexpo -= 2; | |||
1458 | } | |||
1459 | if (y < (1.0 / (1 << 1))) | |||
1460 | { | |||
1461 | y *= 1.0 * (1 << 1); | |||
1462 | expexpo -= 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 = expexpo; | |||
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_C991 | |||
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 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_INT1 | |||
1544 | if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) | |||
1545 | tmp_length = | |||
1546 | (unsigned int) (sizeof (unsigned long long) * CHAR_BIT8 | |||
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_BIT8 | |||
1555 | * 0.30103 /* binary -> decimal */ | |||
1556 | ) | |||
1557 | + 1; /* turn floor into ceil */ | |||
1558 | else | |||
1559 | tmp_length = | |||
1560 | (unsigned int) (sizeof (unsigned int) * CHAR_BIT8 | |||
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_INT1 | |||
1574 | if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) | |||
1575 | tmp_length = | |||
1576 | (unsigned int) (sizeof (unsigned long long) * CHAR_BIT8 | |||
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_BIT8 | |||
1585 | * 0.333334 /* binary -> octal */ | |||
1586 | ) | |||
1587 | + 1; /* turn floor into ceil */ | |||
1588 | else | |||
1589 | tmp_length = | |||
1590 | (unsigned int) (sizeof (unsigned int) * CHAR_BIT8 | |||
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_INT1 | |||
1602 | if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) | |||
1603 | tmp_length = | |||
1604 | (unsigned int) (sizeof (unsigned long long) * CHAR_BIT8 | |||
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_BIT8 | |||
1613 | * 0.25 /* binary -> hexadecimal */ | |||
1614 | ) | |||
1615 | + 1; /* turn floor into ceil */ | |||
1616 | else | |||
1617 | tmp_length = | |||
1618 | (unsigned int) (sizeof (unsigned int) * CHAR_BIT8 | |||
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_EXP16384 | |||
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_EXP1024 | |||
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_DIG18 | |||
1658 | * 0.831 /* decimal -> hexadecimal */ | |||
1659 | ) | |||
1660 | + 1; /* turn floor into ceil */ | |||
1661 | else | |||
1662 | tmp_length = | |||
1663 | (unsigned int) (DBL_DIG15 | |||
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_T1 && !WIDE_CHAR_VERSION | |||
1675 | if (type == TYPE_WIDE_CHAR) | |||
1676 | tmp_length = MB_CUR_MAX(__ctype_get_mb_cur_max ()); | |||
1677 | else | |||
1678 | # endif | |||
1679 | tmp_length = 1; | |||
1680 | break; | |||
1681 | ||||
1682 | case 's': | |||
1683 | # if HAVE_WCHAR_T1 | |||
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_BIT8 | |||
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 | VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, | |||
1774 | const FCHAR_T *format, va_list args) | |||
1775 | { | |||
1776 | DIRECTIVES d; | |||
1777 | arguments a; | |||
1778 | ||||
1779 | if (PRINTF_PARSE (format, &d, &a) < 0) | |||
| ||||
1780 | /* errno is already set. */ | |||
1781 | return NULL((void*)0); | |||
1782 | ||||
1783 | #define CLEANUP()if (d.dir != d.direct_alloc_dir) free (d.dir); if (a.arg != a .direct_alloc_arg) free (a.arg); \ | |||
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 | if (PRINTF_FETCHARGSprintf_fetchargs (args, &a) < 0) | |||
1790 | { | |||
1791 | CLEANUP ()if (d.dir != d.direct_alloc_dir) free (d.dir); if (a.arg != a .direct_alloc_arg) free (a.arg);; | |||
1792 | errno(*__errno_location ()) = EINVAL22; | |||
1793 | return NULL((void*)0); | |||
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 | buf_neededlength = | |||
1811 | xsum4 (7, d.max_width_length, d.max_precision_length, 6); | |||
1812 | #if HAVE_ALLOCA1 | |||
1813 | if (buf_neededlength < 4000 / sizeof (TCHAR_T)) | |||
1814 | { | |||
1815 | buf = (TCHAR_T *) alloca__builtin_alloca (buf_neededlength * sizeof (TCHAR_T)); | |||
1816 | buf_malloced = NULL((void*)0); | |||
1817 | } | |||
1818 | else | |||
1819 | #endif | |||
1820 | { | |||
1821 | size_t buf_memsize = xtimes (buf_neededlength, sizeof (TCHAR_T))((buf_neededlength) <= (18446744073709551615UL) / (sizeof ( TCHAR_T)) ? (size_t) (buf_neededlength) * (sizeof (TCHAR_T)) : (18446744073709551615UL)); | |||
1822 | if (size_overflow_p (buf_memsize)((buf_memsize) == (18446744073709551615UL))) | |||
1823 | goto out_of_memory_1; | |||
1824 | buf = (TCHAR_T *) malloc (buf_memsize); | |||
1825 | if (buf == NULL((void*)0)) | |||
1826 | goto out_of_memory_1; | |||
1827 | buf_malloced = buf; | |||
1828 | } | |||
1829 | ||||
1830 | if (resultbuf != NULL((void*)0)) | |||
1831 | { | |||
1832 | result = resultbuf; | |||
1833 | allocated = *lengthp; | |||
1834 | } | |||
1835 | else | |||
1836 | { | |||
1837 | result = NULL((void*)0); | |||
1838 | allocated = 0; | |||
1839 | } | |||
1840 | 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)if ((needed) > allocated) { size_t memory_size; DCHAR_T *memory ; allocated = (allocated > 0 ? ((allocated) <= (18446744073709551615UL ) / (2) ? (size_t) (allocated) * (2) : (18446744073709551615UL )) : 12); if ((needed) > allocated) allocated = (needed); memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T )) ? (size_t) (allocated) * (sizeof (DCHAR_T)) : (18446744073709551615UL )); if (((memory_size) == (18446744073709551615UL))) goto out_of_memory ; if (result == resultbuf || result == ((void*)0)) memory = ( DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size); if (memory == ((void*)0)) goto out_of_memory ; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result, length); result = memory; } \ | |||
1848 | if ((needed) > allocated) \ | |||
1849 | { \ | |||
1850 | size_t memory_size; \ | |||
1851 | DCHAR_T *memory; \ | |||
1852 | \ | |||
1853 | allocated = (allocated > 0 ? xtimes (allocated, 2)((allocated) <= (18446744073709551615UL) / (2) ? (size_t) ( allocated) * (2) : (18446744073709551615UL)) : 12); \ | |||
1854 | if ((needed) > allocated) \ | |||
1855 | allocated = (needed); \ | |||
1856 | memory_size = xtimes (allocated, sizeof (DCHAR_T))((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T )) ? (size_t) (allocated) * (sizeof (DCHAR_T)) : (18446744073709551615UL )); \ | |||
1857 | if (size_overflow_p (memory_size)((memory_size) == (18446744073709551615UL))) \ | |||
1858 | goto out_of_memory; \ | |||
1859 | if (result == resultbuf || result == NULL((void*)0)) \ | |||
1860 | memory = (DCHAR_T *) malloc (memory_size); \ | |||
1861 | else \ | |||
1862 | memory = (DCHAR_T *) realloc (result, memory_size); \ | |||
1863 | if (memory == NULL((void*)0)) \ | |||
1864 | goto out_of_memory; \ | |||
1865 | if (result == resultbuf && length > 0) \ | |||
1866 | DCHAR_CPY (memory, result, length); \ | |||
1867 | result = memory; \ | |||
1868 | } | |||
1869 | ||||
1870 | for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++) | |||
1871 | { | |||
1872 | if (cp != dp->dir_start) | |||
1873 | { | |||
1874 | size_t n = dp->dir_start - cp; | |||
1875 | size_t augmented_length = xsum (length, n); | |||
1876 | ||||
1877 | ENSURE_ALLOCATION (augmented_length)if ((augmented_length) > allocated) { size_t memory_size; DCHAR_T *memory; allocated = (allocated > 0 ? ((allocated) <= ( 18446744073709551615UL) / (2) ? (size_t) (allocated) * (2) : ( 18446744073709551615UL)) : 12); if ((augmented_length) > allocated ) allocated = (augmented_length); memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T)) ? (size_t) (allocated ) * (sizeof (DCHAR_T)) : (18446744073709551615UL)); if (((memory_size ) == (18446744073709551615UL))) goto out_of_memory; if (result == resultbuf || result == ((void*)0)) memory = (DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size ); if (memory == ((void*)0)) goto out_of_memory; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result , length); result = memory; }; | |||
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 | DCHAR_CPY (result + length, (const DCHAR_T *) cp, n); | |||
1884 | length = augmented_length; | |||
1885 | } | |||
1886 | else | |||
1887 | { | |||
1888 | do | |||
1889 | result[length++] = (unsigned char) *cp++; | |||
1890 | while (--n > 0); | |||
1891 | } | |||
1892 | } | |||
1893 | if (i == d.count) | |||
1894 | break; | |||
1895 | ||||
1896 | /* Execute a single directive. */ | |||
1897 | if (dp->conversion == '%') | |||
1898 | { | |||
1899 | size_t augmented_length; | |||
1900 | ||||
1901 | if (!(dp->arg_index == ARG_NONE(~(size_t)0))) | |||
1902 | abort (); | |||
1903 | augmented_length = xsum (length, 1); | |||
1904 | ENSURE_ALLOCATION (augmented_length)if ((augmented_length) > allocated) { size_t memory_size; DCHAR_T *memory; allocated = (allocated > 0 ? ((allocated) <= ( 18446744073709551615UL) / (2) ? (size_t) (allocated) * (2) : ( 18446744073709551615UL)) : 12); if ((augmented_length) > allocated ) allocated = (augmented_length); memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T)) ? (size_t) (allocated ) * (sizeof (DCHAR_T)) : (18446744073709551615UL)); if (((memory_size ) == (18446744073709551615UL))) goto out_of_memory; if (result == resultbuf || result == ((void*)0)) memory = (DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size ); if (memory == ((void*)0)) goto out_of_memory; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result , length); result = memory; }; | |||
1905 | result[length] = '%'; | |||
1906 | length = augmented_length; | |||
1907 | } | |||
1908 | else | |||
1909 | { | |||
1910 | if (!(dp->arg_index != ARG_NONE(~(size_t)0))) | |||
1911 | abort (); | |||
1912 | ||||
1913 | if (dp->conversion == 'n') | |||
1914 | { | |||
1915 | switch (a.arg[dp->arg_index].type) | |||
1916 | { | |||
1917 | case TYPE_COUNT_SCHAR_POINTER: | |||
1918 | *a.arg[dp->arg_index].a.a_count_schar_pointer = length; | |||
1919 | break; | |||
1920 | case TYPE_COUNT_SHORT_POINTER: | |||
1921 | *a.arg[dp->arg_index].a.a_count_short_pointer = length; | |||
1922 | break; | |||
1923 | case TYPE_COUNT_INT_POINTER: | |||
1924 | *a.arg[dp->arg_index].a.a_count_int_pointer = length; | |||
1925 | break; | |||
1926 | case TYPE_COUNT_LONGINT_POINTER: | |||
1927 | *a.arg[dp->arg_index].a.a_count_longint_pointer = length; | |||
1928 | break; | |||
1929 | #if HAVE_LONG_LONG_INT1 | |||
1930 | case TYPE_COUNT_LONGLONGINT_POINTER: | |||
1931 | *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length; | |||
1932 | break; | |||
1933 | #endif | |||
1934 | default: | |||
1935 | 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(~(size_t)0)) | |||
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_LEFT2; | |||
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)((width) <= (18446744073709551615UL) / (10) ? (size_t) (width ) * (10) : (18446744073709551615UL)), *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(~(size_t)0)) | |||
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)((precision) <= (18446744073709551615UL) / (10) ? (size_t) (precision) * (10) : (18446744073709551615UL)), *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((void*)0))) | |||
2032 | free (result); | |||
2033 | if (buf_malloced != NULL((void*)0)) | |||
2034 | free (buf_malloced); | |||
2035 | CLEANUP ()if (d.dir != d.direct_alloc_dir) free (d.dir); if (a.arg != a .direct_alloc_arg) free (a.arg);; | |||
2036 | errno(*__errno_location ()) = EILSEQ84; | |||
2037 | return NULL((void*)0); | |||
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((void*)0))) | |||
2057 | free (result); | |||
2058 | if (buf_malloced != NULL((void*)0)) | |||
2059 | free (buf_malloced); | |||
2060 | CLEANUP ()if (d.dir != d.direct_alloc_dir) free (d.dir); if (a.arg != a .direct_alloc_arg) free (a.arg);; | |||
2061 | errno(*__errno_location ()) = EILSEQ84; | |||
2062 | return NULL((void*)0); | |||
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_LEFT2)) | |||
2078 | { | |||
2079 | size_t n = width - characters; | |||
2080 | ENSURE_ALLOCATION (xsum (length, n))if ((xsum (length, n)) > allocated) { size_t memory_size; DCHAR_T *memory; allocated = (allocated > 0 ? ((allocated) <= ( 18446744073709551615UL) / (2) ? (size_t) (allocated) * (2) : ( 18446744073709551615UL)) : 12); if ((xsum (length, n)) > allocated ) allocated = (xsum (length, n)); memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T)) ? (size_t) (allocated ) * (sizeof (DCHAR_T)) : (18446744073709551615UL)); if (((memory_size ) == (18446744073709551615UL))) goto out_of_memory; if (result == resultbuf || result == ((void*)0)) memory = (DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size ); if (memory == ((void*)0)) goto out_of_memory; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result , length); result = memory; }; | |||
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))if ((xsum (length, n)) > allocated) { size_t memory_size; DCHAR_T *memory; allocated = (allocated > 0 ? ((allocated) <= ( 18446744073709551615UL) / (2) ? (size_t) (allocated) * (2) : ( 18446744073709551615UL)) : 12); if ((xsum (length, n)) > allocated ) allocated = (xsum (length, n)); memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T)) ? (size_t) (allocated ) * (sizeof (DCHAR_T)) : (18446744073709551615UL)); if (((memory_size ) == (18446744073709551615UL))) goto out_of_memory; if (result == resultbuf || result == ((void*)0)) memory = (DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size ); if (memory == ((void*)0)) goto out_of_memory; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result , length); result = memory; }; | |||
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((void*)0), | |||
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((void*)0)) | |||
2110 | { | |||
2111 | int saved_errno = errno(*__errno_location ()); | |||
2112 | if (!(result == resultbuf || result == NULL((void*)0))) | |||
2113 | free (result); | |||
2114 | if (buf_malloced != NULL((void*)0)) | |||
2115 | free (buf_malloced); | |||
2116 | CLEANUP ()if (d.dir != d.direct_alloc_dir) free (d.dir); if (a.arg != a .direct_alloc_arg) free (a.arg);; | |||
2117 | errno(*__errno_location ()) = saved_errno; | |||
2118 | return NULL((void*)0); | |||
2119 | } | |||
2120 | if (converted != result + length) | |||
2121 | { | |||
2122 | ENSURE_ALLOCATION (xsum (length, converted_len))if ((xsum (length, converted_len)) > allocated) { size_t memory_size ; DCHAR_T *memory; allocated = (allocated > 0 ? ((allocated ) <= (18446744073709551615UL) / (2) ? (size_t) (allocated) * (2) : (18446744073709551615UL)) : 12); if ((xsum (length, converted_len )) > allocated) allocated = (xsum (length, converted_len)) ; memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T)) ? (size_t) (allocated) * (sizeof (DCHAR_T )) : (18446744073709551615UL)); if (((memory_size) == (18446744073709551615UL ))) goto out_of_memory; if (result == resultbuf || result == ( (void*)0)) memory = (DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size); if (memory == ( (void*)0)) goto out_of_memory; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result, length); result = memory ; }; | |||
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_LEFT2)) | |||
2132 | { | |||
2133 | size_t n = width - characters; | |||
2134 | ENSURE_ALLOCATION (xsum (length, n))if ((xsum (length, n)) > allocated) { size_t memory_size; DCHAR_T *memory; allocated = (allocated > 0 ? ((allocated) <= ( 18446744073709551615UL) / (2) ? (size_t) (allocated) * (2) : ( 18446744073709551615UL)) : 12); if ((xsum (length, n)) > allocated ) allocated = (xsum (length, n)); memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T)) ? (size_t) (allocated ) * (sizeof (DCHAR_T)) : (18446744073709551615UL)); if (((memory_size ) == (18446744073709551615UL))) goto out_of_memory; if (result == resultbuf || result == ((void*)0)) memory = (DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size ); if (memory == ((void*)0)) goto out_of_memory; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result , length); result = memory; }; | |||
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((void*)0))) | |||
2160 | free (result); | |||
2161 | if (buf_malloced != NULL((void*)0)) | |||
2162 | free (buf_malloced); | |||
2163 | CLEANUP ()if (d.dir != d.direct_alloc_dir) free (d.dir); if (a.arg != a .direct_alloc_arg) free (a.arg);; | |||
2164 | errno(*__errno_location ()) = EILSEQ84; | |||
2165 | return NULL((void*)0); | |||
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((void*)0))) | |||
2185 | free (result); | |||
2186 | if (buf_malloced != NULL((void*)0)) | |||
2187 | free (buf_malloced); | |||
2188 | CLEANUP ()if (d.dir != d.direct_alloc_dir) free (d.dir); if (a.arg != a .direct_alloc_arg) free (a.arg);; | |||
2189 | errno(*__errno_location ()) = EILSEQ84; | |||
2190 | return NULL((void*)0); | |||
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_LEFT2)) | |||
2206 | { | |||
2207 | size_t n = width - characters; | |||
2208 | ENSURE_ALLOCATION (xsum (length, n))if ((xsum (length, n)) > allocated) { size_t memory_size; DCHAR_T *memory; allocated = (allocated > 0 ? ((allocated) <= ( 18446744073709551615UL) / (2) ? (size_t) (allocated) * (2) : ( 18446744073709551615UL)) : 12); if ((xsum (length, n)) > allocated ) allocated = (xsum (length, n)); memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T)) ? (size_t) (allocated ) * (sizeof (DCHAR_T)) : (18446744073709551615UL)); if (((memory_size ) == (18446744073709551615UL))) goto out_of_memory; if (result == resultbuf || result == ((void*)0)) memory = (DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size ); if (memory == ((void*)0)) goto out_of_memory; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result , length); result = memory; }; | |||
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))if ((xsum (length, n)) > allocated) { size_t memory_size; DCHAR_T *memory; allocated = (allocated > 0 ? ((allocated) <= ( 18446744073709551615UL) / (2) ? (size_t) (allocated) * (2) : ( 18446744073709551615UL)) : 12); if ((xsum (length, n)) > allocated ) allocated = (xsum (length, n)); memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T)) ? (size_t) (allocated ) * (sizeof (DCHAR_T)) : (18446744073709551615UL)); if (((memory_size ) == (18446744073709551615UL))) goto out_of_memory; if (result == resultbuf || result == ((void*)0)) memory = (DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size ); if (memory == ((void*)0)) goto out_of_memory; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result , length); result = memory; }; | |||
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((void*)0), | |||
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((void*)0)) | |||
2238 | { | |||
2239 | int saved_errno = errno(*__errno_location ()); | |||
2240 | if (!(result == resultbuf || result == NULL((void*)0))) | |||
2241 | free (result); | |||
2242 | if (buf_malloced != NULL((void*)0)) | |||
2243 | free (buf_malloced); | |||
2244 | CLEANUP ()if (d.dir != d.direct_alloc_dir) free (d.dir); if (a.arg != a .direct_alloc_arg) free (a.arg);; | |||
2245 | errno(*__errno_location ()) = saved_errno; | |||
2246 | return NULL((void*)0); | |||
2247 | } | |||
2248 | if (converted != result + length) | |||
2249 | { | |||
2250 | ENSURE_ALLOCATION (xsum (length, converted_len))if ((xsum (length, converted_len)) > allocated) { size_t memory_size ; DCHAR_T *memory; allocated = (allocated > 0 ? ((allocated ) <= (18446744073709551615UL) / (2) ? (size_t) (allocated) * (2) : (18446744073709551615UL)) : 12); if ((xsum (length, converted_len )) > allocated) allocated = (xsum (length, converted_len)) ; memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T)) ? (size_t) (allocated) * (sizeof (DCHAR_T )) : (18446744073709551615UL)); if (((memory_size) == (18446744073709551615UL ))) goto out_of_memory; if (result == resultbuf || result == ( (void*)0)) memory = (DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size); if (memory == ( (void*)0)) goto out_of_memory; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result, length); result = memory ; }; | |||
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_LEFT2)) | |||
2260 | { | |||
2261 | size_t n = width - characters; | |||
2262 | ENSURE_ALLOCATION (xsum (length, n))if ((xsum (length, n)) > allocated) { size_t memory_size; DCHAR_T *memory; allocated = (allocated > 0 ? ((allocated) <= ( 18446744073709551615UL) / (2) ? (size_t) (allocated) * (2) : ( 18446744073709551615UL)) : 12); if ((xsum (length, n)) > allocated ) allocated = (xsum (length, n)); memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T)) ? (size_t) (allocated ) * (sizeof (DCHAR_T)) : (18446744073709551615UL)); if (((memory_size ) == (18446744073709551615UL))) goto out_of_memory; if (result == resultbuf || result == ((void*)0)) memory = (DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size ); if (memory == ((void*)0)) goto out_of_memory; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result , length); result = memory; }; | |||
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((void*)0))) | |||
2288 | free (result); | |||
2289 | if (buf_malloced != NULL((void*)0)) | |||
2290 | free (buf_malloced); | |||
2291 | CLEANUP ()if (d.dir != d.direct_alloc_dir) free (d.dir); if (a.arg != a .direct_alloc_arg) free (a.arg);; | |||
2292 | errno(*__errno_location ()) = EILSEQ84; | |||
2293 | return NULL((void*)0); | |||
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((void*)0))) | |||
2313 | free (result); | |||
2314 | if (buf_malloced != NULL((void*)0)) | |||
2315 | free (buf_malloced); | |||
2316 | CLEANUP ()if (d.dir != d.direct_alloc_dir) free (d.dir); if (a.arg != a .direct_alloc_arg) free (a.arg);; | |||
2317 | errno(*__errno_location ()) = EILSEQ84; | |||
2318 | return NULL((void*)0); | |||
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_LEFT2)) | |||
2334 | { | |||
2335 | size_t n = width - characters; | |||
2336 | ENSURE_ALLOCATION (xsum (length, n))if ((xsum (length, n)) > allocated) { size_t memory_size; DCHAR_T *memory; allocated = (allocated > 0 ? ((allocated) <= ( 18446744073709551615UL) / (2) ? (size_t) (allocated) * (2) : ( 18446744073709551615UL)) : 12); if ((xsum (length, n)) > allocated ) allocated = (xsum (length, n)); memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T)) ? (size_t) (allocated ) * (sizeof (DCHAR_T)) : (18446744073709551615UL)); if (((memory_size ) == (18446744073709551615UL))) goto out_of_memory; if (result == resultbuf || result == ((void*)0)) memory = (DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size ); if (memory == ((void*)0)) goto out_of_memory; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result , length); result = memory; }; | |||
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))if ((xsum (length, n)) > allocated) { size_t memory_size; DCHAR_T *memory; allocated = (allocated > 0 ? ((allocated) <= ( 18446744073709551615UL) / (2) ? (size_t) (allocated) * (2) : ( 18446744073709551615UL)) : 12); if ((xsum (length, n)) > allocated ) allocated = (xsum (length, n)); memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T)) ? (size_t) (allocated ) * (sizeof (DCHAR_T)) : (18446744073709551615UL)); if (((memory_size ) == (18446744073709551615UL))) goto out_of_memory; if (result == resultbuf || result == ((void*)0)) memory = (DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size ); if (memory == ((void*)0)) goto out_of_memory; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result , length); result = memory; }; | |||
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((void*)0), | |||
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((void*)0)) | |||
2366 | { | |||
2367 | int saved_errno = errno(*__errno_location ()); | |||
2368 | if (!(result == resultbuf || result == NULL((void*)0))) | |||
2369 | free (result); | |||
2370 | if (buf_malloced != NULL((void*)0)) | |||
2371 | free (buf_malloced); | |||
2372 | CLEANUP ()if (d.dir != d.direct_alloc_dir) free (d.dir); if (a.arg != a .direct_alloc_arg) free (a.arg);; | |||
2373 | errno(*__errno_location ()) = saved_errno; | |||
2374 | return NULL((void*)0); | |||
2375 | } | |||
2376 | if (converted != result + length) | |||
2377 | { | |||
2378 | ENSURE_ALLOCATION (xsum (length, converted_len))if ((xsum (length, converted_len)) > allocated) { size_t memory_size ; DCHAR_T *memory; allocated = (allocated > 0 ? ((allocated ) <= (18446744073709551615UL) / (2) ? (size_t) (allocated) * (2) : (18446744073709551615UL)) : 12); if ((xsum (length, converted_len )) > allocated) allocated = (xsum (length, converted_len)) ; memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T)) ? (size_t) (allocated) * (sizeof (DCHAR_T )) : (18446744073709551615UL)); if (((memory_size) == (18446744073709551615UL ))) goto out_of_memory; if (result == resultbuf || result == ( (void*)0)) memory = (DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size); if (memory == ( (void*)0)) goto out_of_memory; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result, length); result = memory ; }; | |||
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_LEFT2)) | |||
2388 | { | |||
2389 | size_t n = width - characters; | |||
2390 | ENSURE_ALLOCATION (xsum (length, n))if ((xsum (length, n)) > allocated) { size_t memory_size; DCHAR_T *memory; allocated = (allocated > 0 ? ((allocated) <= ( 18446744073709551615UL) / (2) ? (size_t) (allocated) * (2) : ( 18446744073709551615UL)) : 12); if ((xsum (length, n)) > allocated ) allocated = (xsum (length, n)); memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T)) ? (size_t) (allocated ) * (sizeof (DCHAR_T)) : (18446744073709551615UL)); if (((memory_size ) == (18446744073709551615UL))) goto out_of_memory; if (result == resultbuf || result == ((void*)0)) memory = (DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size ); if (memory == ((void*)0)) goto out_of_memory; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result , length); result = memory; }; | |||
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_C991 || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && HAVE_WCHAR_T1 | |||
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(~(size_t)0)) | |||
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_LEFT2; | |||
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)((width) <= (18446744073709551615UL) / (10) ? (size_t) (width ) * (10) : (18446744073709551615UL)), *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(~(size_t)0)) | |||
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)((precision) <= (18446744073709551615UL) / (10) ? (size_t) (precision) * (10) : (18446744073709551615UL)), *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_MBRTOWC1 | |||
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_MBRTOWC1 | |||
2510 | count = mbrlen (arg_end, MB_CUR_MAX(__ctype_get_mb_cur_max ()), &state); | |||
2511 | # else | |||
2512 | count = mblen (arg_end, MB_CUR_MAX(__ctype_get_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((void*)0))) | |||
2521 | free (result); | |||
2522 | if (buf_malloced != NULL((void*)0)) | |||
2523 | free (buf_malloced); | |||
2524 | CLEANUP ()if (d.dir != d.direct_alloc_dir) free (d.dir); if (a.arg != a .direct_alloc_arg) free (a.arg);; | |||
2525 | errno(*__errno_location ()) = EILSEQ84; | |||
2526 | return NULL((void*)0); | |||
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_MBRTOWC1 | |||
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_MBRTOWC1 | |||
2546 | count = mbrlen (arg_end, MB_CUR_MAX(__ctype_get_mb_cur_max ()), &state); | |||
2547 | # else | |||
2548 | count = mblen (arg_end, MB_CUR_MAX(__ctype_get_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((void*)0))) | |||
2557 | free (result); | |||
2558 | if (buf_malloced != NULL((void*)0)) | |||
2559 | free (buf_malloced); | |||
2560 | CLEANUP ()if (d.dir != d.direct_alloc_dir) free (d.dir); if (a.arg != a .direct_alloc_arg) free (a.arg);; | |||
2561 | errno(*__errno_location ()) = EILSEQ84; | |||
2562 | return NULL((void*)0); | |||
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_LEFT2)) | |||
2578 | { | |||
2579 | size_t n = width - characters; | |||
2580 | ENSURE_ALLOCATION (xsum (length, n))if ((xsum (length, n)) > allocated) { size_t memory_size; DCHAR_T *memory; allocated = (allocated > 0 ? ((allocated) <= ( 18446744073709551615UL) / (2) ? (size_t) (allocated) * (2) : ( 18446744073709551615UL)) : 12); if ((xsum (length, n)) > allocated ) allocated = (xsum (length, n)); memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T)) ? (size_t) (allocated ) * (sizeof (DCHAR_T)) : (18446744073709551615UL)); if (((memory_size ) == (18446744073709551615UL))) goto out_of_memory; if (result == resultbuf || result == ((void*)0)) memory = (DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size ); if (memory == ((void*)0)) goto out_of_memory; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result , length); result = memory; }; | |||
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_MBRTOWC1 | |||
2590 | mbstate_t state; | |||
2591 | memset (&state, '\0', sizeof (mbstate_t)); | |||
2592 | # endif | |||
2593 | ENSURE_ALLOCATION (xsum (length, characters))if ((xsum (length, characters)) > allocated) { size_t memory_size ; DCHAR_T *memory; allocated = (allocated > 0 ? ((allocated ) <= (18446744073709551615UL) / (2) ? (size_t) (allocated) * (2) : (18446744073709551615UL)) : 12); if ((xsum (length, characters )) > allocated) allocated = (xsum (length, characters)); memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T )) ? (size_t) (allocated) * (sizeof (DCHAR_T)) : (18446744073709551615UL )); if (((memory_size) == (18446744073709551615UL))) goto out_of_memory ; if (result == resultbuf || result == ((void*)0)) memory = ( DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size); if (memory == ((void*)0)) goto out_of_memory ; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result, length); result = memory; }; | |||
2594 | for (remaining = characters; remaining > 0; remaining--) | |||
2595 | { | |||
2596 | wchar_t wc; | |||
2597 | int count; | |||
2598 | # if HAVE_MBRTOWC1 | |||
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_MBRTOWC1 | |||
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_MBRTOWC1 | |||
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))if ((xsum (length, 1)) > allocated) { size_t memory_size; DCHAR_T *memory; allocated = (allocated > 0 ? ((allocated) <= ( 18446744073709551615UL) / (2) ? (size_t) (allocated) * (2) : ( 18446744073709551615UL)) : 12); if ((xsum (length, 1)) > allocated ) allocated = (xsum (length, 1)); memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T)) ? (size_t) (allocated ) * (sizeof (DCHAR_T)) : (18446744073709551615UL)); if (((memory_size ) == (18446744073709551615UL))) goto out_of_memory; if (result == resultbuf || result == ((void*)0)) memory = (DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size ); if (memory == ((void*)0)) goto out_of_memory; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result , length); result = memory; }; | |||
2633 | result[length++] = wc; | |||
2634 | arg += count; | |||
2635 | } | |||
2636 | } | |||
2637 | ||||
2638 | if (has_width && width > characters | |||
2639 | && (dp->flags & FLAG_LEFT2)) | |||
2640 | { | |||
2641 | size_t n = width - characters; | |||
2642 | ENSURE_ALLOCATION (xsum (length, n))if ((xsum (length, n)) > allocated) { size_t memory_size; DCHAR_T *memory; allocated = (allocated > 0 ? ((allocated) <= ( 18446744073709551615UL) / (2) ? (size_t) (allocated) * (2) : ( 18446744073709551615UL)) : 12); if ((xsum (length, n)) > allocated ) allocated = (xsum (length, n)); memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T)) ? (size_t) (allocated ) * (sizeof (DCHAR_T)) : (18446744073709551615UL)); if (((memory_size ) == (18446744073709551615UL))) goto out_of_memory; if (result == resultbuf || result == ((void*)0)) memory = (DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size ); if (memory == ((void*)0)) goto out_of_memory; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result , length); result = memory; }; | |||
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)extern int (*_gl_verify_function4 (void)) [(!!sizeof (struct { unsigned int _gl_verify_error_if_negative: (sizeof (TCHAR_T) == 1) ? 1 : -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_WCRTOMB1 && !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_WCRTOMB1 && !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((void*)0))) | |||
2689 | free (result); | |||
2690 | if (buf_malloced != NULL((void*)0)) | |||
2691 | free (buf_malloced); | |||
2692 | CLEANUP ()if (d.dir != d.direct_alloc_dir) free (d.dir); if (a.arg != a .direct_alloc_arg) free (a.arg);; | |||
2693 | errno(*__errno_location ()) = EILSEQ84; | |||
2694 | return NULL((void*)0); | |||
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_WCRTOMB1 && !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_WCRTOMB1 && !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((void*)0))) | |||
2734 | free (result); | |||
2735 | if (buf_malloced != NULL((void*)0)) | |||
2736 | free (buf_malloced); | |||
2737 | CLEANUP ()if (d.dir != d.direct_alloc_dir) free (d.dir); if (a.arg != a .direct_alloc_arg) free (a.arg);; | |||
2738 | errno(*__errno_location ()) = EILSEQ84; | |||
2739 | return NULL((void*)0); | |||
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((void*)0)) | |||
2759 | goto out_of_memory; | |||
2760 | { | |||
2761 | TCHAR_T *tmpptr = tmpsrc; | |||
2762 | size_t remaining; | |||
2763 | # if HAVE_WCRTOMB1 && !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_WCRTOMB1 && !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((void*)0), | |||
2797 | NULL((void*)0), &tmpdst_len); | |||
2798 | if (tmpdst == NULL((void*)0)) | |||
2799 | { | |||
2800 | int saved_errno = errno(*__errno_location ()); | |||
2801 | free (tmpsrc); | |||
2802 | if (!(result == resultbuf || result == NULL((void*)0))) | |||
2803 | free (result); | |||
2804 | if (buf_malloced != NULL((void*)0)) | |||
2805 | free (buf_malloced); | |||
2806 | CLEANUP ()if (d.dir != d.direct_alloc_dir) free (d.dir); if (a.arg != a .direct_alloc_arg) free (a.arg);; | |||
2807 | errno(*__errno_location ()) = saved_errno; | |||
2808 | return NULL((void*)0); | |||
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_LEFT2)) | |||
2832 | { | |||
2833 | size_t n = width - w; | |||
2834 | ENSURE_ALLOCATION (xsum (length, n))if ((xsum (length, n)) > allocated) { size_t memory_size; DCHAR_T *memory; allocated = (allocated > 0 ? ((allocated) <= ( 18446744073709551615UL) / (2) ? (size_t) (allocated) * (2) : ( 18446744073709551615UL)) : 12); if ((xsum (length, n)) > allocated ) allocated = (xsum (length, n)); memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T)) ? (size_t) (allocated ) * (sizeof (DCHAR_T)) : (18446744073709551615UL)); if (((memory_size ) == (18446744073709551615UL))) goto out_of_memory; if (result == resultbuf || result == ((void*)0)) memory = (DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size ); if (memory == ((void*)0)) goto out_of_memory; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result , length); result = memory; }; | |||
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_WCRTOMB1 && !defined GNULIB_defined_mbstate_t | |||
2845 | mbstate_t state; | |||
2846 | memset (&state, '\0', sizeof (mbstate_t)); | |||
2847 | # endif | |||
2848 | ENSURE_ALLOCATION (xsum (length, characters))if ((xsum (length, characters)) > allocated) { size_t memory_size ; DCHAR_T *memory; allocated = (allocated > 0 ? ((allocated ) <= (18446744073709551615UL) / (2) ? (size_t) (allocated) * (2) : (18446744073709551615UL)) : 12); if ((xsum (length, characters )) > allocated) allocated = (xsum (length, characters)); memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T )) ? (size_t) (allocated) * (sizeof (DCHAR_T)) : (18446744073709551615UL )); if (((memory_size) == (18446744073709551615UL))) goto out_of_memory ; if (result == resultbuf || result == ((void*)0)) memory = ( DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size); if (memory == ((void*)0)) goto out_of_memory ; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result, length); result = memory; }; | |||
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_WCRTOMB1 && !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_WCRTOMB1 && !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_WCRTOMB1 && !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((void*)0))) | |||
2894 | free (result); | |||
2895 | if (buf_malloced != NULL((void*)0)) | |||
2896 | free (buf_malloced); | |||
2897 | CLEANUP ()if (d.dir != d.direct_alloc_dir) free (d.dir); if (a.arg != a .direct_alloc_arg) free (a.arg);; | |||
2898 | errno(*__errno_location ()) = EILSEQ84; | |||
2899 | return NULL((void*)0); | |||
2900 | } | |||
2901 | ENSURE_ALLOCATION (xsum (length, count))if ((xsum (length, count)) > allocated) { size_t memory_size ; DCHAR_T *memory; allocated = (allocated > 0 ? ((allocated ) <= (18446744073709551615UL) / (2) ? (size_t) (allocated) * (2) : (18446744073709551615UL)) : 12); if ((xsum (length, count )) > allocated) allocated = (xsum (length, count)); memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T )) ? (size_t) (allocated) * (sizeof (DCHAR_T)) : (18446744073709551615UL )); if (((memory_size) == (18446744073709551615UL))) goto out_of_memory ; if (result == resultbuf || result == ((void*)0)) memory = ( DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size); if (memory == ((void*)0)) goto out_of_memory ; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result, length); result = memory; }; | |||
2902 | memcpy (result + length, cbuf, count); | |||
2903 | length += count; | |||
2904 | arg++; | |||
2905 | } | |||
2906 | } | |||
2907 | # else | |||
2908 | ENSURE_ALLOCATION (xsum (length, tmpdst_len))if ((xsum (length, tmpdst_len)) > allocated) { size_t memory_size ; DCHAR_T *memory; allocated = (allocated > 0 ? ((allocated ) <= (18446744073709551615UL) / (2) ? (size_t) (allocated) * (2) : (18446744073709551615UL)) : 12); if ((xsum (length, tmpdst_len )) > allocated) allocated = (xsum (length, tmpdst_len)); memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T )) ? (size_t) (allocated) * (sizeof (DCHAR_T)) : (18446744073709551615UL )); if (((memory_size) == (18446744073709551615UL))) goto out_of_memory ; if (result == resultbuf || result == ((void*)0)) memory = ( DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size); if (memory == ((void*)0)) goto out_of_memory ; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result, length); result = memory; }; | |||
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_LEFT2)) | |||
2916 | { | |||
2917 | size_t n = width - w; | |||
2918 | ENSURE_ALLOCATION (xsum (length, n))if ((xsum (length, n)) > allocated) { size_t memory_size; DCHAR_T *memory; allocated = (allocated > 0 ? ((allocated) <= ( 18446744073709551615UL) / (2) ? (size_t) (allocated) * (2) : ( 18446744073709551615UL)) : 12); if ((xsum (length, n)) > allocated ) allocated = (xsum (length, n)); memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T)) ? (size_t) (allocated ) * (sizeof (DCHAR_T)) : (18446744073709551615UL)); if (((memory_size ) == (18446744073709551615UL))) goto out_of_memory; if (result == resultbuf || result == ((void*)0)) memory = (DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size ); if (memory == ((void*)0)) goto out_of_memory; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result , length); result = memory; }; | |||
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(~(size_t)0)) | |||
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_LEFT2; | |||
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)((width) <= (18446744073709551615UL) / (10) ? (size_t) (width ) * (10) : (18446744073709551615UL)), *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(~(size_t)0)) | |||
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)((precision) <= (18446744073709551615UL) / (10) ? (size_t) (precision) * (10) : (18446744073709551615UL)), *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_DIG18 + 1) | |||
3018 | * 0.831 /* decimal -> hexadecimal */ | |||
3019 | ) | |||
3020 | + 1; /* turn floor into ceil */ | |||
3021 | else | |||
3022 | tmp_length = | |||
3023 | (unsigned int) ((DBL_DIG15 + 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))((tmp_length) <= (18446744073709551615UL) / (sizeof (DCHAR_T )) ? (size_t) (tmp_length) * (sizeof (DCHAR_T)) : (18446744073709551615UL )); | |||
3042 | ||||
3043 | if (size_overflow_p (tmp_memsize)((tmp_memsize) == (18446744073709551615UL))) | |||
3044 | /* Overflow, would lead to out of memory. */ | |||
3045 | goto out_of_memory; | |||
3046 | tmp = (DCHAR_T *) malloc (tmp_memsize); | |||
3047 | if (tmp == NULL((void*)0)) | |||
3048 | /* Out of memory. */ | |||
3049 | goto out_of_memory; | |||
3050 | } | |||
3051 | ||||
3052 | pad_ptr = NULL((void*)0); | |||
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_SHOWSIGN4) | |||
3086 | *p++ = '+'; | |||
3087 | else if (flags & FLAG_SPACE8) | |||
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_DIG18 + 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_ALT16) | |||
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_SHOWSIGN4) | |||
3237 | *p++ = '+'; | |||
3238 | else if (flags & FLAG_SPACE8) | |||
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_DIG15 + 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_ALT16) | |||
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_LEFT2) | |||
3365 | { | |||
3366 | /* Pad with spaces on the right. */ | |||
3367 | for (; pad > 0; pad--) | |||
3368 | *p++ = ' '; | |||
3369 | } | |||
3370 | else if ((flags & FLAG_ZERO32) && pad_ptr != NULL((void*)0)) | |||
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)if ((n) > allocated) { size_t memory_size; DCHAR_T *memory ; allocated = (allocated > 0 ? ((allocated) <= (18446744073709551615UL ) / (2) ? (size_t) (allocated) * (2) : (18446744073709551615UL )) : 12); if ((n) > allocated) allocated = (n); memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T )) ? (size_t) (allocated) * (sizeof (DCHAR_T)) : (18446744073709551615UL )); if (((memory_size) == (18446744073709551615UL))) goto out_of_memory ; if (result == resultbuf || result == ((void*)0)) memory = ( DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size); if (memory == ((void*)0)) goto out_of_memory ; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result, length); result = memory; }; | |||
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(~(size_t)0)) | |||
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_LEFT2; | |||
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)((width) <= (18446744073709551615UL) / (10) ? (size_t) (width ) * (10) : (18446744073709551615UL)), *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(~(size_t)0)) | |||
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)((precision) <= (18446744073709551615UL) / (10) ? (size_t) (precision) * (10) : (18446744073709551615UL)), *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_DIG18 + 1 : DBL_DIG15 + 1); | |||
3532 | # elif NEED_PRINTF_INFINITE_DOUBLE && NEED_PRINTF_LONG_DOUBLE | |||
3533 | tmp_length = (type == TYPE_LONGDOUBLE ? LDBL_DIG18 + 1 : 0); | |||
3534 | # elif NEED_PRINTF_LONG_DOUBLE | |||
3535 | tmp_length = LDBL_DIG18 + 1; | |||
3536 | # elif NEED_PRINTF_DOUBLE | |||
3537 | tmp_length = DBL_DIG15 + 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))((tmp_length) <= (18446744073709551615UL) / (sizeof (DCHAR_T )) ? (size_t) (tmp_length) * (sizeof (DCHAR_T)) : (18446744073709551615UL )); | |||
3588 | ||||
3589 | if (size_overflow_p (tmp_memsize)((tmp_memsize) == (18446744073709551615UL))) | |||
3590 | /* Overflow, would lead to out of memory. */ | |||
3591 | goto out_of_memory; | |||
3592 | tmp = (DCHAR_T *) malloc (tmp_memsize); | |||
3593 | if (tmp == NULL((void*)0)) | |||
3594 | /* Out of memory. */ | |||
3595 | goto out_of_memory; | |||
3596 | } | |||
3597 | ||||
3598 | pad_ptr = NULL((void*)0); | |||
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_SHOWSIGN4) | |||
3635 | *p++ = '+'; | |||
3636 | else if (flags & FLAG_SPACE8) | |||
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((void*)0)) | |||
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_ALT16) || 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_ALT16) || 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((void*)0)) | |||
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((void*)0)) | |||
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_ALT16) || 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_ALT16 ? 0 : precision - 1); | |||
3829 | ||||
3830 | --ndigits; | |||
3831 | *p++ = '0'; | |||
3832 | if ((flags & FLAG_ALT16) || 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((void*)0)) | |||
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((void*)0)) | |||
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_ALT16) == 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_ALT16) || 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_ALT16) || 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_ALT16) || 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_ALT16) || 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_ALT16) | |||
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_ALT16) || 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_SHOWSIGN4) | |||
4100 | *p++ = '+'; | |||
4101 | else if (flags & FLAG_SPACE8) | |||
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((void*)0)) | |||
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_ALT16) || 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_ALT16) || 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((void*)0)) | |||
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((void*)0)) | |||
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_ALT16) || 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_ALT16 ? 0 : precision - 1); | |||
4303 | ||||
4304 | --ndigits; | |||
4305 | *p++ = '0'; | |||
4306 | if ((flags & FLAG_ALT16) || 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((void*)0)) | |||
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((void*)0)) | |||
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_ALT16) == 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_ALT16) || 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_ALT16) || 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_ALT16) || 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_ALT16) || 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_ALT16) | |||
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_LEFT2) | |||
4551 | { | |||
4552 | /* Pad with spaces on the right. */ | |||
4553 | for (; pad > 0; pad--) | |||
4554 | *p++ = ' '; | |||
4555 | } | |||
4556 | else if ((flags & FLAG_ZERO32) && pad_ptr != NULL((void*)0)) | |||
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)if ((n) > allocated) { size_t memory_size; DCHAR_T *memory ; allocated = (allocated > 0 ? ((allocated) <= (18446744073709551615UL ) / (2) ? (size_t) (allocated) * (2) : (18446744073709551615UL )) : 12); if ((n) > allocated) allocated = (n); memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T )) ? (size_t) (allocated) * (sizeof (DCHAR_T)) : (18446744073709551615UL )); if (((memory_size) == (18446744073709551615UL))) goto out_of_memory ; if (result == resultbuf || result == ((void*)0)) memory = ( DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size); if (memory == ((void*)0)) goto out_of_memory ; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result, length); result = memory; }; | |||
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 | arg_type type = a.arg[dp->arg_index].type; | |||
4607 | int flags = dp->flags; | |||
4608 | #if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C991 || !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_C991 || 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_C991 || !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(~(size_t)0)) | |||
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_LEFT2; | |||
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)((width) <= (18446744073709551615UL) / (10) ? (size_t) (width ) * (10) : (18446744073709551615UL)), *digitp++ - '0'); | |||
4666 | while (digitp != dp->width_end); | |||
4667 | } | |||
4668 | has_width = 1; | |||
4669 | } | |||
4670 | #endif | |||
4671 | ||||
4672 | #if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C991 || 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(~(size_t)0)) | |||
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)((precision) <= (18446744073709551615UL) / (10) ? (size_t) (precision) * (10) : (18446744073709551615UL)), *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))((tmp_length) <= (18446744073709551615UL) / (sizeof (TCHAR_T )) ? (size_t) (tmp_length) * (sizeof (TCHAR_T)) : (18446744073709551615UL )); | |||
4755 | ||||
4756 | if (size_overflow_p (tmp_memsize)((tmp_memsize) == (18446744073709551615UL))) | |||
4757 | /* Overflow, would lead to out of memory. */ | |||
4758 | goto out_of_memory; | |||
4759 | tmp = (TCHAR_T *) malloc (tmp_memsize); | |||
4760 | if (tmp == NULL((void*)0)) | |||
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 | fbp = buf; | |||
4769 | *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 | if (flags & FLAG_GROUP1) | |||
4776 | *fbp++ = '\''; | |||
4777 | #endif | |||
4778 | if (flags & FLAG_LEFT2) | |||
4779 | *fbp++ = '-'; | |||
4780 | if (flags & FLAG_SHOWSIGN4) | |||
4781 | *fbp++ = '+'; | |||
4782 | if (flags & FLAG_SPACE8) | |||
4783 | *fbp++ = ' '; | |||
4784 | if (flags & FLAG_ALT16) | |||
4785 | *fbp++ = '#'; | |||
4786 | #if __GLIBC__2 >= 2 && !defined __UCLIBC__ | |||
4787 | if (flags & FLAG_LOCALIZED64) | |||
4788 | *fbp++ = 'I'; | |||
4789 | #endif | |||
4790 | if (!pad_ourselves) | |||
4791 | { | |||
4792 | if (flags & FLAG_ZERO32) | |||
4793 | *fbp++ = '0'; | |||
4794 | if (dp->width_start != dp->width_end) | |||
4795 | { | |||
4796 | 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 | memcpy (fbp, dp->width_start, n * sizeof (TCHAR_T)); | |||
4802 | 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 | if (dp->precision_start != dp->precision_end) | |||
4816 | { | |||
4817 | 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 | memcpy (fbp, dp->precision_start, n * sizeof (TCHAR_T)); | |||
4823 | 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 | switch (type) | |||
4836 | { | |||
4837 | #if HAVE_LONG_LONG_INT1 | |||
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 | *fbp++ = 'l'; | |||
4847 | /*FALLTHROUGH*/ | |||
4848 | # endif | |||
4849 | #endif | |||
4850 | case TYPE_LONGINT: | |||
4851 | case TYPE_ULONGINT: | |||
4852 | #if HAVE_WINT_T1 | |||
4853 | case TYPE_WIDE_CHAR: | |||
4854 | #endif | |||
4855 | #if HAVE_WCHAR_T1 | |||
4856 | case TYPE_WIDE_STRING: | |||
4857 | #endif | |||
4858 | *fbp++ = 'l'; | |||
4859 | break; | |||
4860 | case TYPE_LONGDOUBLE: | |||
4861 | *fbp++ = 'L'; | |||
4862 | break; | |||
4863 | default: | |||
4864 | break; | |||
4865 | } | |||
4866 | #if NEED_PRINTF_DIRECTIVE_F | |||
4867 | if (dp->conversion == 'F') | |||
4868 | *fbp = 'f'; | |||
4869 | else | |||
4870 | #endif | |||
4871 | *fbp = dp->conversion; | |||
4872 | #if USE_SNPRINTF | |||
4873 | # if !(((__GLIBC__2 > 2 || (__GLIBC__2 == 2 && __GLIBC_MINOR__17 >= 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 | fbp[1] = '\0'; | |||
4903 | # endif | |||
4904 | #else | |||
4905 | fbp[1] = '\0'; | |||
4906 | #endif | |||
4907 | ||||
4908 | /* Construct the arguments for calling snprintf or sprintf. */ | |||
4909 | prefix_count = 0; | |||
4910 | if (!pad_ourselves && dp->width_arg_index != ARG_NONE(~(size_t)0)) | |||
4911 | { | |||
4912 | if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) | |||
4913 | abort (); | |||
4914 | prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int; | |||
4915 | } | |||
4916 | if (!prec_ourselves && dp->precision_arg_index != ARG_NONE(~(size_t)0)) | |||
4917 | { | |||
4918 | if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) | |||
4919 | abort (); | |||
4920 | 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 | ENSURE_ALLOCATION (xsum (length,if ((xsum (length, (2 + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR )) > allocated) { size_t memory_size; DCHAR_T *memory; allocated = (allocated > 0 ? ((allocated) <= (18446744073709551615UL ) / (2) ? (size_t) (allocated) * (2) : (18446744073709551615UL )) : 12); if ((xsum (length, (2 + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR )) > allocated) allocated = (xsum (length, (2 + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR)); memory_size = ((allocated) <= ( 18446744073709551615UL) / (sizeof (DCHAR_T)) ? (size_t) (allocated ) * (sizeof (DCHAR_T)) : (18446744073709551615UL)); if (((memory_size ) == (18446744073709551615UL))) goto out_of_memory; if (result == resultbuf || result == ((void*)0)) memory = (DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size ); if (memory == ((void*)0)) goto out_of_memory; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result , length); result = memory; } | |||
4933 | (2 + TCHARS_PER_DCHAR - 1)if ((xsum (length, (2 + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR )) > allocated) { size_t memory_size; DCHAR_T *memory; allocated = (allocated > 0 ? ((allocated) <= (18446744073709551615UL ) / (2) ? (size_t) (allocated) * (2) : (18446744073709551615UL )) : 12); if ((xsum (length, (2 + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR )) > allocated) allocated = (xsum (length, (2 + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR)); memory_size = ((allocated) <= ( 18446744073709551615UL) / (sizeof (DCHAR_T)) ? (size_t) (allocated ) * (sizeof (DCHAR_T)) : (18446744073709551615UL)); if (((memory_size ) == (18446744073709551615UL))) goto out_of_memory; if (result == resultbuf || result == ((void*)0)) memory = (DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size ); if (memory == ((void*)0)) goto out_of_memory; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result , length); result = memory; } | |||
4934 | / TCHARS_PER_DCHAR))if ((xsum (length, (2 + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR )) > allocated) { size_t memory_size; DCHAR_T *memory; allocated = (allocated > 0 ? ((allocated) <= (18446744073709551615UL ) / (2) ? (size_t) (allocated) * (2) : (18446744073709551615UL )) : 12); if ((xsum (length, (2 + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR )) > allocated) allocated = (xsum (length, (2 + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR)); memory_size = ((allocated) <= ( 18446744073709551615UL) / (sizeof (DCHAR_T)) ? (size_t) (allocated ) * (sizeof (DCHAR_T)) : (18446744073709551615UL)); if (((memory_size ) == (18446744073709551615UL))) goto out_of_memory; if (result == resultbuf || result == ((void*)0)) memory = (DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size ); if (memory == ((void*)0)) goto out_of_memory; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result , length); result = memory; }; | |||
4935 | /* Prepare checking whether snprintf returns the count | |||
4936 | via %n. */ | |||
4937 | *(TCHAR_T *) (result + length) = '\0'; | |||
4938 | #endif | |||
4939 | ||||
4940 | orig_errno = errno(*__errno_location ()); | |||
4941 | ||||
4942 | for (;;) | |||
4943 | { | |||
4944 | int count = -1; | |||
4945 | ||||
4946 | #if USE_SNPRINTF | |||
4947 | int retcount = 0; | |||
4948 | size_t maxlen = allocated - length; | |||
4949 | /* SNPRINTF can fail if its second argument is | |||
4950 | > INT_MAX. */ | |||
4951 | if (maxlen > INT_MAX2147483647 / TCHARS_PER_DCHAR) | |||
4952 | maxlen = INT_MAX2147483647 / TCHARS_PER_DCHAR; | |||
4953 | maxlen = maxlen * TCHARS_PER_DCHAR; | |||
4954 | # define SNPRINTF_BUF(arg)switch (prefix_count) { case 0: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, arg, &count); break; case 1: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen , buf, prefixes[0], arg, &count); break; case 2: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, prefixes [0], prefixes[1], arg, &count); break; default: abort (); } \ | |||
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)switch (prefix_count) { case 0: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, arg, &count); break; case 1: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen , buf, prefixes[0], arg, &count); break; case 2: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, prefixes [0], prefixes[1], arg, &count); break; default: abort (); } \ | |||
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 | errno(*__errno_location ()) = 0; | |||
4996 | switch (type) | |||
4997 | { | |||
4998 | case TYPE_SCHAR: | |||
4999 | { | |||
5000 | int arg = a.arg[dp->arg_index].a.a_schar; | |||
5001 | SNPRINTF_BUF (arg)switch (prefix_count) { case 0: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, arg, &count); break; case 1: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen , buf, prefixes[0], arg, &count); break; case 2: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, prefixes [0], prefixes[1], arg, &count); break; default: abort (); }; | |||
5002 | } | |||
5003 | break; | |||
5004 | case TYPE_UCHAR: | |||
5005 | { | |||
5006 | unsigned int arg = a.arg[dp->arg_index].a.a_uchar; | |||
5007 | SNPRINTF_BUF (arg)switch (prefix_count) { case 0: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, arg, &count); break; case 1: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen , buf, prefixes[0], arg, &count); break; case 2: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, prefixes [0], prefixes[1], arg, &count); break; default: abort (); }; | |||
5008 | } | |||
5009 | break; | |||
5010 | case TYPE_SHORT: | |||
5011 | { | |||
5012 | int arg = a.arg[dp->arg_index].a.a_short; | |||
5013 | SNPRINTF_BUF (arg)switch (prefix_count) { case 0: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, arg, &count); break; case 1: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen , buf, prefixes[0], arg, &count); break; case 2: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, prefixes [0], prefixes[1], arg, &count); break; default: abort (); }; | |||
5014 | } | |||
5015 | break; | |||
5016 | case TYPE_USHORT: | |||
5017 | { | |||
5018 | unsigned int arg = a.arg[dp->arg_index].a.a_ushort; | |||
5019 | SNPRINTF_BUF (arg)switch (prefix_count) { case 0: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, arg, &count); break; case 1: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen , buf, prefixes[0], arg, &count); break; case 2: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, prefixes [0], prefixes[1], arg, &count); break; default: abort (); }; | |||
5020 | } | |||
5021 | break; | |||
5022 | case TYPE_INT: | |||
5023 | { | |||
5024 | int arg = a.arg[dp->arg_index].a.a_int; | |||
5025 | SNPRINTF_BUF (arg)switch (prefix_count) { case 0: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, arg, &count); break; case 1: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen , buf, prefixes[0], arg, &count); break; case 2: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, prefixes [0], prefixes[1], arg, &count); break; default: abort (); }; | |||
5026 | } | |||
5027 | break; | |||
5028 | case TYPE_UINT: | |||
5029 | { | |||
5030 | unsigned int arg = a.arg[dp->arg_index].a.a_uint; | |||
5031 | SNPRINTF_BUF (arg)switch (prefix_count) { case 0: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, arg, &count); break; case 1: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen , buf, prefixes[0], arg, &count); break; case 2: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, prefixes [0], prefixes[1], arg, &count); break; default: abort (); }; | |||
5032 | } | |||
5033 | break; | |||
5034 | case TYPE_LONGINT: | |||
5035 | { | |||
5036 | long int arg = a.arg[dp->arg_index].a.a_longint; | |||
5037 | SNPRINTF_BUF (arg)switch (prefix_count) { case 0: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, arg, &count); break; case 1: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen , buf, prefixes[0], arg, &count); break; case 2: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, prefixes [0], prefixes[1], arg, &count); break; default: abort (); }; | |||
5038 | } | |||
5039 | break; | |||
5040 | case TYPE_ULONGINT: | |||
5041 | { | |||
5042 | unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint; | |||
5043 | SNPRINTF_BUF (arg)switch (prefix_count) { case 0: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, arg, &count); break; case 1: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen , buf, prefixes[0], arg, &count); break; case 2: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, prefixes [0], prefixes[1], arg, &count); break; default: abort (); }; | |||
5044 | } | |||
5045 | break; | |||
5046 | #if HAVE_LONG_LONG_INT1 | |||
5047 | case TYPE_LONGLONGINT: | |||
5048 | { | |||
5049 | long long int arg = a.arg[dp->arg_index].a.a_longlongint; | |||
5050 | SNPRINTF_BUF (arg)switch (prefix_count) { case 0: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, arg, &count); break; case 1: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen , buf, prefixes[0], arg, &count); break; case 2: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, prefixes [0], prefixes[1], arg, &count); break; default: abort (); }; | |||
5051 | } | |||
5052 | break; | |||
5053 | case TYPE_ULONGLONGINT: | |||
5054 | { | |||
5055 | unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint; | |||
5056 | SNPRINTF_BUF (arg)switch (prefix_count) { case 0: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, arg, &count); break; case 1: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen , buf, prefixes[0], arg, &count); break; case 2: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, prefixes [0], prefixes[1], arg, &count); break; default: abort (); }; | |||
5057 | } | |||
5058 | break; | |||
5059 | #endif | |||
5060 | case TYPE_DOUBLE: | |||
5061 | { | |||
5062 | double arg = a.arg[dp->arg_index].a.a_double; | |||
5063 | SNPRINTF_BUF (arg)switch (prefix_count) { case 0: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, arg, &count); break; case 1: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen , buf, prefixes[0], arg, &count); break; case 2: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, prefixes [0], prefixes[1], arg, &count); break; default: abort (); }; | |||
5064 | } | |||
5065 | break; | |||
5066 | case TYPE_LONGDOUBLE: | |||
5067 | { | |||
5068 | long double arg = a.arg[dp->arg_index].a.a_longdouble; | |||
5069 | SNPRINTF_BUF (arg)switch (prefix_count) { case 0: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, arg, &count); break; case 1: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen , buf, prefixes[0], arg, &count); break; case 2: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, prefixes [0], prefixes[1], arg, &count); break; default: abort (); }; | |||
5070 | } | |||
5071 | break; | |||
5072 | case TYPE_CHAR: | |||
5073 | { | |||
5074 | int arg = a.arg[dp->arg_index].a.a_char; | |||
5075 | SNPRINTF_BUF (arg)switch (prefix_count) { case 0: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, arg, &count); break; case 1: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen , buf, prefixes[0], arg, &count); break; case 2: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, prefixes [0], prefixes[1], arg, &count); break; default: abort (); }; | |||
5076 | } | |||
5077 | break; | |||
5078 | #if HAVE_WINT_T1 | |||
5079 | case TYPE_WIDE_CHAR: | |||
5080 | { | |||
5081 | wint_t arg = a.arg[dp->arg_index].a.a_wide_char; | |||
5082 | SNPRINTF_BUF (arg)switch (prefix_count) { case 0: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, arg, &count); break; case 1: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen , buf, prefixes[0], arg, &count); break; case 2: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, prefixes [0], prefixes[1], arg, &count); break; default: abort (); }; | |||
5083 | } | |||
5084 | break; | |||
5085 | #endif | |||
5086 | case TYPE_STRING: | |||
5087 | { | |||
5088 | const char *arg = a.arg[dp->arg_index].a.a_string; | |||
5089 | SNPRINTF_BUF (arg)switch (prefix_count) { case 0: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, arg, &count); break; case 1: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen , buf, prefixes[0], arg, &count); break; case 2: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, prefixes [0], prefixes[1], arg, &count); break; default: abort (); }; | |||
5090 | } | |||
5091 | break; | |||
5092 | #if HAVE_WCHAR_T1 | |||
5093 | case TYPE_WIDE_STRING: | |||
5094 | { | |||
5095 | const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string; | |||
5096 | SNPRINTF_BUF (arg)switch (prefix_count) { case 0: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, arg, &count); break; case 1: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen , buf, prefixes[0], arg, &count); break; case 2: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, prefixes [0], prefixes[1], arg, &count); break; default: abort (); }; | |||
5097 | } | |||
5098 | break; | |||
5099 | #endif | |||
5100 | case TYPE_POINTER: | |||
5101 | { | |||
5102 | void *arg = a.arg[dp->arg_index].a.a_pointer; | |||
5103 | SNPRINTF_BUF (arg)switch (prefix_count) { case 0: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, arg, &count); break; case 1: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen , buf, prefixes[0], arg, &count); break; case 2: retcount = SNPRINTF ((TCHAR_T *) (result + length), maxlen, buf, prefixes [0], prefixes[1], arg, &count); break; default: abort (); }; | |||
5104 | } | |||
5105 | break; | |||
5106 | default: | |||
5107 | 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 | if (count >= 0) | |||
5116 | { | |||
5117 | /* Verify that snprintf() has NUL-terminated its | |||
5118 | result. */ | |||
5119 | if (count < maxlen | |||
5120 | && ((TCHAR_T *) (result + length)) [count] != '\0') | |||
5121 | abort (); | |||
5122 | /* Portability hack. */ | |||
5123 | if (retcount > count) | |||
5124 | count = retcount; | |||
5125 | } | |||
5126 | else | |||
5127 | { | |||
5128 | /* snprintf() doesn't understand the '%n' | |||
5129 | directive. */ | |||
5130 | if (fbp[1] != '\0') | |||
5131 | { | |||
5132 | /* Don't use the '%n' directive; instead, look | |||
5133 | at the snprintf() return value. */ | |||
5134 | fbp[1] = '\0'; | |||
5135 | continue; | |||
5136 | } | |||
5137 | else | |||
5138 | { | |||
5139 | /* Look at the snprintf() return value. */ | |||
5140 | if (retcount < 0) | |||
5141 | { | |||
5142 | # if !HAVE_SNPRINTF_RETVAL_C991 | |||
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 | has_width ? width : 0, | |||
5157 | has_precision, | |||
5158 | precision, pad_ourselves); | |||
5159 | ||||
5160 | if (maxlen < tmp_length) | |||
5161 | { | |||
5162 | /* Make more room. But try to do through | |||
5163 | this reallocation only once. */ | |||
5164 | size_t bigger_need = | |||
5165 | xsum (length, | |||
5166 | xsum (tmp_length, | |||
5167 | TCHARS_PER_DCHAR - 1) | |||
5168 | / TCHARS_PER_DCHAR); | |||
5169 | /* And always grow proportionally. | |||
5170 | (There may be several arguments, each | |||
5171 | needing a little more room than the | |||
5172 | previous one.) */ | |||
5173 | size_t bigger_need2 = | |||
5174 | xsum (xtimes (allocated, 2)((allocated) <= (18446744073709551615UL) / (2) ? (size_t) ( allocated) * (2) : (18446744073709551615UL)), 12); | |||
5175 | if (bigger_need < bigger_need2) | |||
5176 | bigger_need = bigger_need2; | |||
5177 | ENSURE_ALLOCATION (bigger_need)if ((bigger_need) > allocated) { size_t memory_size; DCHAR_T *memory; allocated = (allocated > 0 ? ((allocated) <= ( 18446744073709551615UL) / (2) ? (size_t) (allocated) * (2) : ( 18446744073709551615UL)) : 12); if ((bigger_need) > allocated ) allocated = (bigger_need); memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T)) ? (size_t) (allocated ) * (sizeof (DCHAR_T)) : (18446744073709551615UL)); if (((memory_size ) == (18446744073709551615UL))) goto out_of_memory; if (result == resultbuf || result == ((void*)0)) memory = (DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size ); if (memory == ((void*)0)) goto out_of_memory; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result , length); result = memory; }; | |||
5178 | continue; | |||
5179 | } | |||
5180 | # endif | |||
5181 | } | |||
5182 | else | |||
5183 | count = retcount; | |||
5184 | } | |||
5185 | } | |||
5186 | #endif | |||
5187 | ||||
5188 | /* Attempt to handle failure. */ | |||
5189 | if (count < 0) | |||
5190 | { | |||
5191 | /* SNPRINTF or sprintf failed. Save and use the errno | |||
5192 | that it has set, if any. */ | |||
5193 | int saved_errno = errno(*__errno_location ()); | |||
5194 | ||||
5195 | if (!(result == resultbuf || result == NULL((void*)0))) | |||
5196 | free (result); | |||
5197 | if (buf_malloced != NULL((void*)0)) | |||
5198 | free (buf_malloced); | |||
5199 | CLEANUP ()if (d.dir != d.direct_alloc_dir) free (d.dir); if (a.arg != a .direct_alloc_arg) free (a.arg);; | |||
5200 | errno(*__errno_location ()) = | |||
5201 | (saved_errno != 0 | |||
5202 | ? saved_errno | |||
5203 | : (dp->conversion == 'c' || dp->conversion == 's' | |||
| ||||
5204 | ? EILSEQ84 | |||
5205 | : EINVAL22)); | |||
5206 | return NULL((void*)0); | |||
5207 | } | |||
5208 | ||||
5209 | #if USE_SNPRINTF | |||
5210 | /* Handle overflow of the allocated buffer. | |||
5211 | If such an overflow occurs, a C99 compliant snprintf() | |||
5212 | returns a count >= maxlen. However, a non-compliant | |||
5213 | snprintf() function returns only count = maxlen - 1. To | |||
5214 | cover both cases, test whether count >= maxlen - 1. */ | |||
5215 | if ((unsigned int) count + 1 >= maxlen) | |||
5216 | { | |||
5217 | /* If maxlen already has attained its allowed maximum, | |||
5218 | allocating more memory will not increase maxlen. | |||
5219 | Instead of looping, bail out. */ | |||
5220 | if (maxlen == INT_MAX2147483647 / TCHARS_PER_DCHAR) | |||
5221 | goto overflow; | |||
5222 | else | |||
5223 | { | |||
5224 | /* Need at least (count + 1) * sizeof (TCHAR_T) | |||
5225 | bytes. (The +1 is for the trailing NUL.) | |||
5226 | But ask for (count + 2) * sizeof (TCHAR_T) | |||
5227 | bytes, so that in the next round, we likely get | |||
5228 | maxlen > (unsigned int) count + 1 | |||
5229 | and so we don't get here again. | |||
5230 | And allocate proportionally, to avoid looping | |||
5231 | eternally if snprintf() reports a too small | |||
5232 | count. */ | |||
5233 | size_t n = | |||
5234 | xmax (xsum (length, | |||
5235 | ((unsigned int) count + 2 | |||
5236 | + TCHARS_PER_DCHAR - 1) | |||
5237 | / TCHARS_PER_DCHAR), | |||
5238 | xtimes (allocated, 2)((allocated) <= (18446744073709551615UL) / (2) ? (size_t) ( allocated) * (2) : (18446744073709551615UL))); | |||
5239 | ||||
5240 | ENSURE_ALLOCATION (n)if ((n) > allocated) { size_t memory_size; DCHAR_T *memory ; allocated = (allocated > 0 ? ((allocated) <= (18446744073709551615UL ) / (2) ? (size_t) (allocated) * (2) : (18446744073709551615UL )) : 12); if ((n) > allocated) allocated = (n); memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T )) ? (size_t) (allocated) * (sizeof (DCHAR_T)) : (18446744073709551615UL )); if (((memory_size) == (18446744073709551615UL))) goto out_of_memory ; if (result == resultbuf || result == ((void*)0)) memory = ( DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size); if (memory == ((void*)0)) goto out_of_memory ; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result, length); result = memory; }; | |||
5241 | continue; | |||
5242 | } | |||
5243 | } | |||
5244 | #endif | |||
5245 | ||||
5246 | #if NEED_PRINTF_UNBOUNDED_PRECISION | |||
5247 | if (prec_ourselves) | |||
5248 | { | |||
5249 | /* Handle the precision. */ | |||
5250 | TCHAR_T *prec_ptr = | |||
5251 | # if USE_SNPRINTF | |||
5252 | (TCHAR_T *) (result + length); | |||
5253 | # else | |||
5254 | tmp; | |||
5255 | # endif | |||
5256 | size_t prefix_count; | |||
5257 | size_t move; | |||
5258 | ||||
5259 | prefix_count = 0; | |||
5260 | /* Put the additional zeroes after the sign. */ | |||
5261 | if (count >= 1 | |||
5262 | && (*prec_ptr == '-' || *prec_ptr == '+' | |||
5263 | || *prec_ptr == ' ')) | |||
5264 | prefix_count = 1; | |||
5265 | /* Put the additional zeroes after the 0x prefix if | |||
5266 | (flags & FLAG_ALT) || (dp->conversion == 'p'). */ | |||
5267 | else if (count >= 2 | |||
5268 | && prec_ptr[0] == '0' | |||
5269 | && (prec_ptr[1] == 'x' || prec_ptr[1] == 'X')) | |||
5270 | prefix_count = 2; | |||
5271 | ||||
5272 | move = count - prefix_count; | |||
5273 | if (precision > move) | |||
5274 | { | |||
5275 | /* Insert zeroes. */ | |||
5276 | size_t insert = precision - move; | |||
5277 | TCHAR_T *prec_end; | |||
5278 | ||||
5279 | # if USE_SNPRINTF | |||
5280 | size_t n = | |||
5281 | xsum (length, | |||
5282 | (count + insert + TCHARS_PER_DCHAR - 1) | |||
5283 | / TCHARS_PER_DCHAR); | |||
5284 | length += (count + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR; | |||
5285 | ENSURE_ALLOCATION (n)if ((n) > allocated) { size_t memory_size; DCHAR_T *memory ; allocated = (allocated > 0 ? ((allocated) <= (18446744073709551615UL ) / (2) ? (size_t) (allocated) * (2) : (18446744073709551615UL )) : 12); if ((n) > allocated) allocated = (n); memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T )) ? (size_t) (allocated) * (sizeof (DCHAR_T)) : (18446744073709551615UL )); if (((memory_size) == (18446744073709551615UL))) goto out_of_memory ; if (result == resultbuf || result == ((void*)0)) memory = ( DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size); if (memory == ((void*)0)) goto out_of_memory ; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result, length); result = memory; }; | |||
5286 | length -= (count + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR; | |||
5287 | prec_ptr = (TCHAR_T *) (result + length); | |||
5288 | # endif | |||
5289 | ||||
5290 | prec_end = prec_ptr + count; | |||
5291 | prec_ptr += prefix_count; | |||
5292 | ||||
5293 | while (prec_end > prec_ptr) | |||
5294 | { | |||
5295 | prec_end--; | |||
5296 | prec_end[insert] = prec_end[0]; | |||
5297 | } | |||
5298 | ||||
5299 | prec_end += insert; | |||
5300 | do | |||
5301 | *--prec_end = '0'; | |||
5302 | while (prec_end > prec_ptr); | |||
5303 | ||||
5304 | count += insert; | |||
5305 | } | |||
5306 | } | |||
5307 | #endif | |||
5308 | ||||
5309 | #if !USE_SNPRINTF | |||
5310 | if (count >= tmp_length) | |||
5311 | /* tmp_length was incorrectly calculated - fix the | |||
5312 | code above! */ | |||
5313 | abort (); | |||
5314 | #endif | |||
5315 | ||||
5316 | #if !DCHAR_IS_TCHAR | |||
5317 | /* Convert from TCHAR_T[] to DCHAR_T[]. */ | |||
5318 | if (dp->conversion == 'c' || dp->conversion == 's') | |||
5319 | { | |||
5320 | /* type = TYPE_CHAR or TYPE_WIDE_CHAR or TYPE_STRING | |||
5321 | TYPE_WIDE_STRING. | |||
5322 | The result string is not certainly ASCII. */ | |||
5323 | const TCHAR_T *tmpsrc; | |||
5324 | DCHAR_T *tmpdst; | |||
5325 | size_t tmpdst_len; | |||
5326 | /* This code assumes that TCHAR_T is 'char'. */ | |||
5327 | verify (sizeof (TCHAR_T) == 1)extern int (*_gl_verify_function5 (void)) [(!!sizeof (struct { unsigned int _gl_verify_error_if_negative: (sizeof (TCHAR_T) == 1) ? 1 : -1; }))]; | |||
5328 | # if USE_SNPRINTF | |||
5329 | tmpsrc = (TCHAR_T *) (result + length); | |||
5330 | # else | |||
5331 | tmpsrc = tmp; | |||
5332 | # endif | |||
5333 | tmpdst = | |||
5334 | DCHAR_CONV_FROM_ENCODING (locale_charset (), | |||
5335 | iconveh_question_mark, | |||
5336 | tmpsrc, count, | |||
5337 | NULL((void*)0), | |||
5338 | NULL((void*)0), &tmpdst_len); | |||
5339 | if (tmpdst == NULL((void*)0)) | |||
5340 | { | |||
5341 | int saved_errno = errno(*__errno_location ()); | |||
5342 | if (!(result == resultbuf || result == NULL((void*)0))) | |||
5343 | free (result); | |||
5344 | if (buf_malloced != NULL((void*)0)) | |||
5345 | free (buf_malloced); | |||
5346 | CLEANUP ()if (d.dir != d.direct_alloc_dir) free (d.dir); if (a.arg != a .direct_alloc_arg) free (a.arg);; | |||
5347 | errno(*__errno_location ()) = saved_errno; | |||
5348 | return NULL((void*)0); | |||
5349 | } | |||
5350 | ENSURE_ALLOCATION (xsum (length, tmpdst_len))if ((xsum (length, tmpdst_len)) > allocated) { size_t memory_size ; DCHAR_T *memory; allocated = (allocated > 0 ? ((allocated ) <= (18446744073709551615UL) / (2) ? (size_t) (allocated) * (2) : (18446744073709551615UL)) : 12); if ((xsum (length, tmpdst_len )) > allocated) allocated = (xsum (length, tmpdst_len)); memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T )) ? (size_t) (allocated) * (sizeof (DCHAR_T)) : (18446744073709551615UL )); if (((memory_size) == (18446744073709551615UL))) goto out_of_memory ; if (result == resultbuf || result == ((void*)0)) memory = ( DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size); if (memory == ((void*)0)) goto out_of_memory ; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result, length); result = memory; }; | |||
5351 | DCHAR_CPY (result + length, tmpdst, tmpdst_len); | |||
5352 | free (tmpdst); | |||
5353 | count = tmpdst_len; | |||
5354 | } | |||
5355 | else | |||
5356 | { | |||
5357 | /* The result string is ASCII. | |||
5358 | Simple 1:1 conversion. */ | |||
5359 | # if USE_SNPRINTF | |||
5360 | /* If sizeof (DCHAR_T) == sizeof (TCHAR_T), it's a | |||
5361 | no-op conversion, in-place on the array starting | |||
5362 | at (result + length). */ | |||
5363 | if (sizeof (DCHAR_T) != sizeof (TCHAR_T)) | |||
5364 | # endif | |||
5365 | { | |||
5366 | const TCHAR_T *tmpsrc; | |||
5367 | DCHAR_T *tmpdst; | |||
5368 | size_t n; | |||
5369 | ||||
5370 | # if USE_SNPRINTF | |||
5371 | if (result == resultbuf) | |||
5372 | { | |||
5373 | tmpsrc = (TCHAR_T *) (result + length); | |||
5374 | /* ENSURE_ALLOCATION will not move tmpsrc | |||
5375 | (because it's part of resultbuf). */ | |||
5376 | ENSURE_ALLOCATION (xsum (length, count))if ((xsum (length, count)) > allocated) { size_t memory_size ; DCHAR_T *memory; allocated = (allocated > 0 ? ((allocated ) <= (18446744073709551615UL) / (2) ? (size_t) (allocated) * (2) : (18446744073709551615UL)) : 12); if ((xsum (length, count )) > allocated) allocated = (xsum (length, count)); memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T )) ? (size_t) (allocated) * (sizeof (DCHAR_T)) : (18446744073709551615UL )); if (((memory_size) == (18446744073709551615UL))) goto out_of_memory ; if (result == resultbuf || result == ((void*)0)) memory = ( DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size); if (memory == ((void*)0)) goto out_of_memory ; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result, length); result = memory; }; | |||
5377 | } | |||
5378 | else | |||
5379 | { | |||
5380 | /* ENSURE_ALLOCATION will move the array | |||
5381 | (because it uses realloc(). */ | |||
5382 | ENSURE_ALLOCATION (xsum (length, count))if ((xsum (length, count)) > allocated) { size_t memory_size ; DCHAR_T *memory; allocated = (allocated > 0 ? ((allocated ) <= (18446744073709551615UL) / (2) ? (size_t) (allocated) * (2) : (18446744073709551615UL)) : 12); if ((xsum (length, count )) > allocated) allocated = (xsum (length, count)); memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T )) ? (size_t) (allocated) * (sizeof (DCHAR_T)) : (18446744073709551615UL )); if (((memory_size) == (18446744073709551615UL))) goto out_of_memory ; if (result == resultbuf || result == ((void*)0)) memory = ( DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size); if (memory == ((void*)0)) goto out_of_memory ; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result, length); result = memory; }; | |||
5383 | tmpsrc = (TCHAR_T *) (result + length); | |||
5384 | } | |||
5385 | # else | |||
5386 | tmpsrc = tmp; | |||
5387 | ENSURE_ALLOCATION (xsum (length, count))if ((xsum (length, count)) > allocated) { size_t memory_size ; DCHAR_T *memory; allocated = (allocated > 0 ? ((allocated ) <= (18446744073709551615UL) / (2) ? (size_t) (allocated) * (2) : (18446744073709551615UL)) : 12); if ((xsum (length, count )) > allocated) allocated = (xsum (length, count)); memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T )) ? (size_t) (allocated) * (sizeof (DCHAR_T)) : (18446744073709551615UL )); if (((memory_size) == (18446744073709551615UL))) goto out_of_memory ; if (result == resultbuf || result == ((void*)0)) memory = ( DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size); if (memory == ((void*)0)) goto out_of_memory ; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result, length); result = memory; }; | |||
5388 | # endif | |||
5389 | tmpdst = result + length; | |||
5390 | /* Copy backwards, because of overlapping. */ | |||
5391 | tmpsrc += count; | |||
5392 | tmpdst += count; | |||
5393 | for (n = count; n > 0; n--) | |||
5394 | *--tmpdst = (unsigned char) *--tmpsrc; | |||
5395 | } | |||
5396 | } | |||
5397 | #endif | |||
5398 | ||||
5399 | #if DCHAR_IS_TCHAR && !USE_SNPRINTF | |||
5400 | /* Make room for the result. */ | |||
5401 | if (count > allocated - length) | |||
5402 | { | |||
5403 | /* Need at least count elements. But allocate | |||
5404 | proportionally. */ | |||
5405 | size_t n = | |||
5406 | xmax (xsum (length, count), xtimes (allocated, 2)((allocated) <= (18446744073709551615UL) / (2) ? (size_t) ( allocated) * (2) : (18446744073709551615UL))); | |||
5407 | ||||
5408 | ENSURE_ALLOCATION (n)if ((n) > allocated) { size_t memory_size; DCHAR_T *memory ; allocated = (allocated > 0 ? ((allocated) <= (18446744073709551615UL ) / (2) ? (size_t) (allocated) * (2) : (18446744073709551615UL )) : 12); if ((n) > allocated) allocated = (n); memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T )) ? (size_t) (allocated) * (sizeof (DCHAR_T)) : (18446744073709551615UL )); if (((memory_size) == (18446744073709551615UL))) goto out_of_memory ; if (result == resultbuf || result == ((void*)0)) memory = ( DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size); if (memory == ((void*)0)) goto out_of_memory ; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result, length); result = memory; }; | |||
5409 | } | |||
5410 | #endif | |||
5411 | ||||
5412 | /* Here count <= allocated - length. */ | |||
5413 | ||||
5414 | /* Perform padding. */ | |||
5415 | #if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION | |||
5416 | if (pad_ourselves && has_width) | |||
5417 | { | |||
5418 | size_t w; | |||
5419 | # if ENABLE_UNISTDIO | |||
5420 | /* Outside POSIX, it's preferable to compare the width | |||
5421 | against the number of _characters_ of the converted | |||
5422 | value. */ | |||
5423 | w = DCHAR_MBSNLEN (result + length, count); | |||
5424 | # else | |||
5425 | /* The width is compared against the number of _bytes_ | |||
5426 | of the converted value, says POSIX. */ | |||
5427 | w = count; | |||
5428 | # endif | |||
5429 | if (w < width) | |||
5430 | { | |||
5431 | size_t pad = width - w; | |||
5432 | ||||
5433 | /* Make room for the result. */ | |||
5434 | if (xsum (count, pad) > allocated - length) | |||
5435 | { | |||
5436 | /* Need at least count + pad elements. But | |||
5437 | allocate proportionally. */ | |||
5438 | size_t n = | |||
5439 | xmax (xsum3 (length, count, pad), | |||
5440 | xtimes (allocated, 2)((allocated) <= (18446744073709551615UL) / (2) ? (size_t) ( allocated) * (2) : (18446744073709551615UL))); | |||
5441 | ||||
5442 | # if USE_SNPRINTF | |||
5443 | length += count; | |||
5444 | ENSURE_ALLOCATION (n)if ((n) > allocated) { size_t memory_size; DCHAR_T *memory ; allocated = (allocated > 0 ? ((allocated) <= (18446744073709551615UL ) / (2) ? (size_t) (allocated) * (2) : (18446744073709551615UL )) : 12); if ((n) > allocated) allocated = (n); memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T )) ? (size_t) (allocated) * (sizeof (DCHAR_T)) : (18446744073709551615UL )); if (((memory_size) == (18446744073709551615UL))) goto out_of_memory ; if (result == resultbuf || result == ((void*)0)) memory = ( DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size); if (memory == ((void*)0)) goto out_of_memory ; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result, length); result = memory; }; | |||
5445 | length -= count; | |||
5446 | # else | |||
5447 | ENSURE_ALLOCATION (n)if ((n) > allocated) { size_t memory_size; DCHAR_T *memory ; allocated = (allocated > 0 ? ((allocated) <= (18446744073709551615UL ) / (2) ? (size_t) (allocated) * (2) : (18446744073709551615UL )) : 12); if ((n) > allocated) allocated = (n); memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T )) ? (size_t) (allocated) * (sizeof (DCHAR_T)) : (18446744073709551615UL )); if (((memory_size) == (18446744073709551615UL))) goto out_of_memory ; if (result == resultbuf || result == ((void*)0)) memory = ( DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size); if (memory == ((void*)0)) goto out_of_memory ; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result, length); result = memory; }; | |||
5448 | # endif | |||
5449 | } | |||
5450 | /* Here count + pad <= allocated - length. */ | |||
5451 | ||||
5452 | { | |||
5453 | # if !DCHAR_IS_TCHAR || USE_SNPRINTF | |||
5454 | DCHAR_T * const rp = result + length; | |||
5455 | # else | |||
5456 | DCHAR_T * const rp = tmp; | |||
5457 | # endif | |||
5458 | DCHAR_T *p = rp + count; | |||
5459 | DCHAR_T *end = p + pad; | |||
5460 | DCHAR_T *pad_ptr; | |||
5461 | # if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO | |||
5462 | if (dp->conversion == 'c' | |||
5463 | || dp->conversion == 's') | |||
5464 | /* No zero-padding for string directives. */ | |||
5465 | pad_ptr = NULL((void*)0); | |||
5466 | else | |||
5467 | # endif | |||
5468 | { | |||
5469 | pad_ptr = (*rp == '-' ? rp + 1 : rp); | |||
5470 | /* No zero-padding of "inf" and "nan". */ | |||
5471 | if ((*pad_ptr >= 'A' && *pad_ptr <= 'Z') | |||
5472 | || (*pad_ptr >= 'a' && *pad_ptr <= 'z')) | |||
5473 | pad_ptr = NULL((void*)0); | |||
5474 | } | |||
5475 | /* The generated string now extends from rp to p, | |||
5476 | with the zero padding insertion point being at | |||
5477 | pad_ptr. */ | |||
5478 | ||||
5479 | count = count + pad; /* = end - rp */ | |||
5480 | ||||
5481 | if (flags & FLAG_LEFT2) | |||
5482 | { | |||
5483 | /* Pad with spaces on the right. */ | |||
5484 | for (; pad > 0; pad--) | |||
5485 | *p++ = ' '; | |||
5486 | } | |||
5487 | else if ((flags & FLAG_ZERO32) && pad_ptr != NULL((void*)0)) | |||
5488 | { | |||
5489 | /* Pad with zeroes. */ | |||
5490 | DCHAR_T *q = end; | |||
5491 | ||||
5492 | while (p > pad_ptr) | |||
5493 | *--q = *--p; | |||
5494 | for (; pad > 0; pad--) | |||
5495 | *p++ = '0'; | |||
5496 | } | |||
5497 | else | |||
5498 | { | |||
5499 | /* Pad with spaces on the left. */ | |||
5500 | DCHAR_T *q = end; | |||
5501 | ||||
5502 | while (p > rp) | |||
5503 | *--q = *--p; | |||
5504 | for (; pad > 0; pad--) | |||
5505 | *p++ = ' '; | |||
5506 | } | |||
5507 | } | |||
5508 | } | |||
5509 | } | |||
5510 | #endif | |||
5511 | ||||
5512 | /* Here still count <= allocated - length. */ | |||
5513 | ||||
5514 | #if !DCHAR_IS_TCHAR || USE_SNPRINTF | |||
5515 | /* The snprintf() result did fit. */ | |||
5516 | #else | |||
5517 | /* Append the sprintf() result. */ | |||
5518 | memcpy (result + length, tmp, count * sizeof (DCHAR_T)); | |||
5519 | #endif | |||
5520 | #if !USE_SNPRINTF | |||
5521 | if (tmp != tmpbuf) | |||
5522 | free (tmp); | |||
5523 | #endif | |||
5524 | ||||
5525 | #if NEED_PRINTF_DIRECTIVE_F | |||
5526 | if (dp->conversion == 'F') | |||
5527 | { | |||
5528 | /* Convert the %f result to upper case for %F. */ | |||
5529 | DCHAR_T *rp = result + length; | |||
5530 | size_t rc; | |||
5531 | for (rc = count; rc > 0; rc--, rp++) | |||
5532 | if (*rp >= 'a' && *rp <= 'z') | |||
5533 | *rp = *rp - 'a' + 'A'; | |||
5534 | } | |||
5535 | #endif | |||
5536 | ||||
5537 | length += count; | |||
5538 | break; | |||
5539 | } | |||
5540 | errno(*__errno_location ()) = orig_errno; | |||
5541 | #undef pad_ourselves | |||
5542 | #undef prec_ourselves | |||
5543 | } | |||
5544 | } | |||
5545 | } | |||
5546 | ||||
5547 | /* Add the final NUL. */ | |||
5548 | ENSURE_ALLOCATION (xsum (length, 1))if ((xsum (length, 1)) > allocated) { size_t memory_size; DCHAR_T *memory; allocated = (allocated > 0 ? ((allocated) <= ( 18446744073709551615UL) / (2) ? (size_t) (allocated) * (2) : ( 18446744073709551615UL)) : 12); if ((xsum (length, 1)) > allocated ) allocated = (xsum (length, 1)); memory_size = ((allocated) <= (18446744073709551615UL) / (sizeof (DCHAR_T)) ? (size_t) (allocated ) * (sizeof (DCHAR_T)) : (18446744073709551615UL)); if (((memory_size ) == (18446744073709551615UL))) goto out_of_memory; if (result == resultbuf || result == ((void*)0)) memory = (DCHAR_T *) malloc (memory_size); else memory = (DCHAR_T *) realloc (result, memory_size ); if (memory == ((void*)0)) goto out_of_memory; if (result == resultbuf && length > 0) DCHAR_CPY (memory, result , length); result = memory; }; | |||
5549 | result[length] = '\0'; | |||
5550 | ||||
5551 | if (result != resultbuf && length + 1 < allocated) | |||
5552 | { | |||
5553 | /* Shrink the allocated memory if possible. */ | |||
5554 | DCHAR_T *memory; | |||
5555 | ||||
5556 | memory = (DCHAR_T *) realloc (result, (length + 1) * sizeof (DCHAR_T)); | |||
5557 | if (memory != NULL((void*)0)) | |||
5558 | result = memory; | |||
5559 | } | |||
5560 | ||||
5561 | if (buf_malloced != NULL((void*)0)) | |||
5562 | free (buf_malloced); | |||
5563 | CLEANUP ()if (d.dir != d.direct_alloc_dir) free (d.dir); if (a.arg != a .direct_alloc_arg) free (a.arg);; | |||
5564 | *lengthp = length; | |||
5565 | /* Note that we can produce a big string of a length > INT_MAX. POSIX | |||
5566 | says that snprintf() fails with errno = EOVERFLOW in this case, but | |||
5567 | that's only because snprintf() returns an 'int'. This function does | |||
5568 | not have this limitation. */ | |||
5569 | return result; | |||
5570 | ||||
5571 | #if USE_SNPRINTF | |||
5572 | overflow: | |||
5573 | if (!(result == resultbuf || result == NULL((void*)0))) | |||
5574 | free (result); | |||
5575 | if (buf_malloced != NULL((void*)0)) | |||
5576 | free (buf_malloced); | |||
5577 | CLEANUP ()if (d.dir != d.direct_alloc_dir) free (d.dir); if (a.arg != a .direct_alloc_arg) free (a.arg);; | |||
5578 | errno(*__errno_location ()) = EOVERFLOW75; | |||
5579 | return NULL((void*)0); | |||
5580 | #endif | |||
5581 | ||||
5582 | out_of_memory: | |||
5583 | if (!(result == resultbuf || result == NULL((void*)0))) | |||
5584 | free (result); | |||
5585 | if (buf_malloced != NULL((void*)0)) | |||
5586 | free (buf_malloced); | |||
5587 | out_of_memory_1: | |||
5588 | CLEANUP ()if (d.dir != d.direct_alloc_dir) free (d.dir); if (a.arg != a .direct_alloc_arg) free (a.arg);; | |||
5589 | errno(*__errno_location ()) = ENOMEM12; | |||
5590 | return NULL((void*)0); | |||
5591 | } | |||
5592 | } | |||
5593 | ||||
5594 | #undef MAX_ROOM_NEEDED | |||
5595 | #undef TCHARS_PER_DCHAR | |||
5596 | #undef SNPRINTF | |||
5597 | #undef USE_SNPRINTF | |||
5598 | #undef DCHAR_SET | |||
5599 | #undef DCHAR_CPY | |||
5600 | #undef PRINTF_PARSE | |||
5601 | #undef DIRECTIVES | |||
5602 | #undef DIRECTIVE | |||
5603 | #undef DCHAR_IS_TCHAR | |||
5604 | #undef TCHAR_T | |||
5605 | #undef DCHAR_T | |||
5606 | #undef FCHAR_T | |||
5607 | #undef VASNPRINTF |