diff options
Diffstat (limited to 'gl/vasnprintf.c')
-rw-r--r-- | gl/vasnprintf.c | 361 |
1 files changed, 272 insertions, 89 deletions
diff --git a/gl/vasnprintf.c b/gl/vasnprintf.c index d5b40286..93aef6f2 100644 --- a/gl/vasnprintf.c +++ b/gl/vasnprintf.c | |||
@@ -95,7 +95,7 @@ | |||
95 | 95 | ||
96 | #if (NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL | 96 | #if (NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL |
97 | # include <math.h> | 97 | # include <math.h> |
98 | # include "isnand.h" | 98 | # include "isnand-nolibm.h" |
99 | #endif | 99 | #endif |
100 | 100 | ||
101 | #if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE) && !defined IN_LIBINTL | 101 | #if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE) && !defined IN_LIBINTL |
@@ -106,7 +106,7 @@ | |||
106 | 106 | ||
107 | #if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL | 107 | #if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL |
108 | # include <math.h> | 108 | # include <math.h> |
109 | # include "isnand.h" | 109 | # include "isnand-nolibm.h" |
110 | # include "printf-frexp.h" | 110 | # include "printf-frexp.h" |
111 | #endif | 111 | #endif |
112 | 112 | ||
@@ -117,11 +117,6 @@ | |||
117 | # include "fpucw.h" | 117 | # include "fpucw.h" |
118 | #endif | 118 | #endif |
119 | 119 | ||
120 | /* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW. */ | ||
121 | #ifndef EOVERFLOW | ||
122 | # define EOVERFLOW E2BIG | ||
123 | #endif | ||
124 | |||
125 | #if HAVE_WCHAR_T | 120 | #if HAVE_WCHAR_T |
126 | # if HAVE_WCSLEN | 121 | # if HAVE_WCSLEN |
127 | # define local_wcslen wcslen | 122 | # define local_wcslen wcslen |
@@ -182,10 +177,12 @@ local_wcslen (const wchar_t *s) | |||
182 | # endif | 177 | # endif |
183 | #else | 178 | #else |
184 | /* TCHAR_T is char. */ | 179 | /* TCHAR_T is char. */ |
185 | # /* Use snprintf if it exists under the name 'snprintf' or '_snprintf'. | 180 | /* Use snprintf if it exists under the name 'snprintf' or '_snprintf'. |
186 | But don't use it on BeOS, since BeOS snprintf produces no output if the | 181 | But don't use it on BeOS, since BeOS snprintf produces no output if the |
187 | size argument is >= 0x3000000. */ | 182 | size argument is >= 0x3000000. |
188 | # if (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF) && !defined __BEOS__ | 183 | Also don't use it on Linux libc5, since there snprintf with size = 1 |
184 | writes any output without bounds, like sprintf. */ | ||
185 | # if (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF) && !defined __BEOS__ && !(__GNU_LIBRARY__ == 1) | ||
189 | # define USE_SNPRINTF 1 | 186 | # define USE_SNPRINTF 1 |
190 | # else | 187 | # else |
191 | # define USE_SNPRINTF 0 | 188 | # define USE_SNPRINTF 0 |
@@ -203,7 +200,22 @@ local_wcslen (const wchar_t *s) | |||
203 | /* Here we need to call the native sprintf, not rpl_sprintf. */ | 200 | /* Here we need to call the native sprintf, not rpl_sprintf. */ |
204 | #undef sprintf | 201 | #undef sprintf |
205 | 202 | ||
206 | #if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL | 203 | /* GCC >= 4.0 with -Wall emits unjustified "... may be used uninitialized" |
204 | warnings in this file. Use -Dlint to suppress them. */ | ||
205 | #ifdef lint | ||
206 | # define IF_LINT(Code) Code | ||
207 | #else | ||
208 | # define IF_LINT(Code) /* empty */ | ||
209 | #endif | ||
210 | |||
211 | /* Avoid some warnings from "gcc -Wshadow". | ||
212 | This file doesn't use the exp() and remainder() functions. */ | ||
213 | #undef exp | ||
214 | #define exp expo | ||
215 | #undef remainder | ||
216 | #define remainder rem | ||
217 | |||
218 | #if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL | ||
207 | /* Determine the decimal-point character according to the current locale. */ | 219 | /* Determine the decimal-point character according to the current locale. */ |
208 | # ifndef decimal_point_char_defined | 220 | # ifndef decimal_point_char_defined |
209 | # define decimal_point_char_defined 1 | 221 | # define decimal_point_char_defined 1 |
@@ -243,11 +255,11 @@ is_infinite_or_zero (double x) | |||
243 | 255 | ||
244 | #if NEED_PRINTF_INFINITE_LONG_DOUBLE && !NEED_PRINTF_LONG_DOUBLE && !defined IN_LIBINTL | 256 | #if NEED_PRINTF_INFINITE_LONG_DOUBLE && !NEED_PRINTF_LONG_DOUBLE && !defined IN_LIBINTL |
245 | 257 | ||
246 | /* Equivalent to !isfinite(x), but does not require libm. */ | 258 | /* Equivalent to !isfinite(x) || x == 0, but does not require libm. */ |
247 | static int | 259 | static int |
248 | is_infinitel (long double x) | 260 | is_infinite_or_zerol (long double x) |
249 | { | 261 | { |
250 | return isnanl (x) || (x + x == x && x != 0.0L); | 262 | return isnanl (x) || x + x == x; |
251 | } | 263 | } |
252 | 264 | ||
253 | #endif | 265 | #endif |
@@ -1201,7 +1213,7 @@ scale10_round_decimal_decoded (int e, mpn_t m, void *memory, int n) | |||
1201 | static char * | 1213 | static char * |
1202 | scale10_round_decimal_long_double (long double x, int n) | 1214 | scale10_round_decimal_long_double (long double x, int n) |
1203 | { | 1215 | { |
1204 | int e; | 1216 | int e IF_LINT(= 0); |
1205 | mpn_t m; | 1217 | mpn_t m; |
1206 | void *memory = decode_long_double (x, &e, &m); | 1218 | void *memory = decode_long_double (x, &e, &m); |
1207 | return scale10_round_decimal_decoded (e, m, memory, n); | 1219 | return scale10_round_decimal_decoded (e, m, memory, n); |
@@ -1219,7 +1231,7 @@ scale10_round_decimal_long_double (long double x, int n) | |||
1219 | static char * | 1231 | static char * |
1220 | scale10_round_decimal_double (double x, int n) | 1232 | scale10_round_decimal_double (double x, int n) |
1221 | { | 1233 | { |
1222 | int e; | 1234 | int e IF_LINT(= 0); |
1223 | mpn_t m; | 1235 | mpn_t m; |
1224 | void *memory = decode_double (x, &e, &m); | 1236 | void *memory = decode_double (x, &e, &m); |
1225 | return scale10_round_decimal_decoded (e, m, memory, n); | 1237 | return scale10_round_decimal_decoded (e, m, memory, n); |
@@ -1306,9 +1318,9 @@ floorlog10l (long double x) | |||
1306 | } | 1318 | } |
1307 | /* Now 0.95 <= z <= 1.01. */ | 1319 | /* Now 0.95 <= z <= 1.01. */ |
1308 | z = 1 - z; | 1320 | z = 1 - z; |
1309 | /* log(1-z) = - z - z^2/2 - z^3/3 - z^4/4 - ... | 1321 | /* log2(1-z) = 1/log(2) * (- z - z^2/2 - z^3/3 - z^4/4 - ...) |
1310 | Four terms are enough to get an approximation with error < 10^-7. */ | 1322 | Four terms are enough to get an approximation with error < 10^-7. */ |
1311 | l -= z * (1.0 + z * (0.5 + z * ((1.0 / 3) + z * 0.25))); | 1323 | l -= 1.4426950408889634074 * z * (1.0 + z * (0.5 + z * ((1.0 / 3) + z * 0.25))); |
1312 | /* Finally multiply with log(2)/log(10), yields an approximation for | 1324 | /* Finally multiply with log(2)/log(10), yields an approximation for |
1313 | log10(x). */ | 1325 | log10(x). */ |
1314 | l *= 0.30102999566398119523; | 1326 | l *= 0.30102999566398119523; |
@@ -1397,9 +1409,9 @@ floorlog10 (double x) | |||
1397 | } | 1409 | } |
1398 | /* Now 0.95 <= z <= 1.01. */ | 1410 | /* Now 0.95 <= z <= 1.01. */ |
1399 | z = 1 - z; | 1411 | z = 1 - z; |
1400 | /* log(1-z) = - z - z^2/2 - z^3/3 - z^4/4 - ... | 1412 | /* log2(1-z) = 1/log(2) * (- z - z^2/2 - z^3/3 - z^4/4 - ...) |
1401 | Four terms are enough to get an approximation with error < 10^-7. */ | 1413 | Four terms are enough to get an approximation with error < 10^-7. */ |
1402 | l -= z * (1.0 + z * (0.5 + z * ((1.0 / 3) + z * 0.25))); | 1414 | l -= 1.4426950408889634074 * z * (1.0 + z * (0.5 + z * ((1.0 / 3) + z * 0.25))); |
1403 | /* Finally multiply with log(2)/log(10), yields an approximation for | 1415 | /* Finally multiply with log(2)/log(10), yields an approximation for |
1404 | log10(x). */ | 1416 | log10(x). */ |
1405 | l *= 0.30102999566398119523; | 1417 | l *= 0.30102999566398119523; |
@@ -1409,6 +1421,20 @@ floorlog10 (double x) | |||
1409 | 1421 | ||
1410 | # endif | 1422 | # endif |
1411 | 1423 | ||
1424 | /* Tests whether a string of digits consists of exactly PRECISION zeroes and | ||
1425 | a single '1' digit. */ | ||
1426 | static int | ||
1427 | is_borderline (const char *digits, size_t precision) | ||
1428 | { | ||
1429 | for (; precision > 0; precision--, digits++) | ||
1430 | if (*digits != '0') | ||
1431 | return 0; | ||
1432 | if (*digits != '1') | ||
1433 | return 0; | ||
1434 | digits++; | ||
1435 | return *digits == '\0'; | ||
1436 | } | ||
1437 | |||
1412 | #endif | 1438 | #endif |
1413 | 1439 | ||
1414 | DCHAR_T * | 1440 | DCHAR_T * |
@@ -2552,8 +2578,10 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, | |||
2552 | # elif NEED_PRINTF_INFINITE_LONG_DOUBLE | 2578 | # elif NEED_PRINTF_INFINITE_LONG_DOUBLE |
2553 | || (a.arg[dp->arg_index].type == TYPE_LONGDOUBLE | 2579 | || (a.arg[dp->arg_index].type == TYPE_LONGDOUBLE |
2554 | /* Some systems produce wrong output for Inf, | 2580 | /* Some systems produce wrong output for Inf, |
2555 | -Inf, and NaN. */ | 2581 | -Inf, and NaN. Some systems in this category |
2556 | && is_infinitel (a.arg[dp->arg_index].a.a_longdouble)) | 2582 | (IRIX 5.3) also do so for -0.0. Therefore we |
2583 | treat this case here as well. */ | ||
2584 | && is_infinite_or_zerol (a.arg[dp->arg_index].a.a_longdouble)) | ||
2557 | # endif | 2585 | # endif |
2558 | )) | 2586 | )) |
2559 | { | 2587 | { |
@@ -2635,9 +2663,11 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, | |||
2635 | 2663 | ||
2636 | /* POSIX specifies the default precision to be 6 for %f, %F, | 2664 | /* POSIX specifies the default precision to be 6 for %f, %F, |
2637 | %e, %E, but not for %g, %G. Implementations appear to use | 2665 | %e, %E, but not for %g, %G. Implementations appear to use |
2638 | the same default precision also for %g, %G. */ | 2666 | the same default precision also for %g, %G. But for %a, %A, |
2667 | the default precision is 0. */ | ||
2639 | if (!has_precision) | 2668 | if (!has_precision) |
2640 | precision = 6; | 2669 | if (!(dp->conversion == 'a' || dp->conversion == 'A')) |
2670 | precision = 6; | ||
2641 | 2671 | ||
2642 | /* Allocate a temporary buffer of sufficient size. */ | 2672 | /* Allocate a temporary buffer of sufficient size. */ |
2643 | # if NEED_PRINTF_DOUBLE && NEED_PRINTF_LONG_DOUBLE | 2673 | # if NEED_PRINTF_DOUBLE && NEED_PRINTF_LONG_DOUBLE |
@@ -2858,8 +2888,32 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, | |||
2858 | exponent += 1; | 2888 | exponent += 1; |
2859 | adjusted = 1; | 2889 | adjusted = 1; |
2860 | } | 2890 | } |
2861 | |||
2862 | /* Here ndigits = precision+1. */ | 2891 | /* Here ndigits = precision+1. */ |
2892 | if (is_borderline (digits, precision)) | ||
2893 | { | ||
2894 | /* Maybe the exponent guess was too high | ||
2895 | and a smaller exponent can be reached | ||
2896 | by turning a 10...0 into 9...9x. */ | ||
2897 | char *digits2 = | ||
2898 | scale10_round_decimal_long_double (arg, | ||
2899 | (int)precision - exponent + 1); | ||
2900 | if (digits2 == NULL) | ||
2901 | { | ||
2902 | free (digits); | ||
2903 | END_LONG_DOUBLE_ROUNDING (); | ||
2904 | goto out_of_memory; | ||
2905 | } | ||
2906 | if (strlen (digits2) == precision + 1) | ||
2907 | { | ||
2908 | free (digits); | ||
2909 | digits = digits2; | ||
2910 | exponent -= 1; | ||
2911 | } | ||
2912 | else | ||
2913 | free (digits2); | ||
2914 | } | ||
2915 | /* Here ndigits = precision+1. */ | ||
2916 | |||
2863 | *p++ = digits[--ndigits]; | 2917 | *p++ = digits[--ndigits]; |
2864 | if ((flags & FLAG_ALT) || precision > 0) | 2918 | if ((flags & FLAG_ALT) || precision > 0) |
2865 | { | 2919 | { |
@@ -2971,6 +3025,30 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, | |||
2971 | adjusted = 1; | 3025 | adjusted = 1; |
2972 | } | 3026 | } |
2973 | /* Here ndigits = precision. */ | 3027 | /* Here ndigits = precision. */ |
3028 | if (is_borderline (digits, precision - 1)) | ||
3029 | { | ||
3030 | /* Maybe the exponent guess was too high | ||
3031 | and a smaller exponent can be reached | ||
3032 | by turning a 10...0 into 9...9x. */ | ||
3033 | char *digits2 = | ||
3034 | scale10_round_decimal_long_double (arg, | ||
3035 | (int)(precision - 1) - exponent + 1); | ||
3036 | if (digits2 == NULL) | ||
3037 | { | ||
3038 | free (digits); | ||
3039 | END_LONG_DOUBLE_ROUNDING (); | ||
3040 | goto out_of_memory; | ||
3041 | } | ||
3042 | if (strlen (digits2) == precision) | ||
3043 | { | ||
3044 | free (digits); | ||
3045 | digits = digits2; | ||
3046 | exponent -= 1; | ||
3047 | } | ||
3048 | else | ||
3049 | free (digits2); | ||
3050 | } | ||
3051 | /* Here ndigits = precision. */ | ||
2974 | 3052 | ||
2975 | /* Determine the number of trailing zeroes | 3053 | /* Determine the number of trailing zeroes |
2976 | that have to be dropped. */ | 3054 | that have to be dropped. */ |
@@ -3065,7 +3143,65 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, | |||
3065 | abort (); | 3143 | abort (); |
3066 | # else | 3144 | # else |
3067 | /* arg is finite. */ | 3145 | /* arg is finite. */ |
3068 | abort (); | 3146 | if (!(arg == 0.0L)) |
3147 | abort (); | ||
3148 | |||
3149 | pad_ptr = p; | ||
3150 | |||
3151 | if (dp->conversion == 'f' || dp->conversion == 'F') | ||
3152 | { | ||
3153 | *p++ = '0'; | ||
3154 | if ((flags & FLAG_ALT) || precision > 0) | ||
3155 | { | ||
3156 | *p++ = decimal_point_char (); | ||
3157 | for (; precision > 0; precision--) | ||
3158 | *p++ = '0'; | ||
3159 | } | ||
3160 | } | ||
3161 | else if (dp->conversion == 'e' || dp->conversion == 'E') | ||
3162 | { | ||
3163 | *p++ = '0'; | ||
3164 | if ((flags & FLAG_ALT) || precision > 0) | ||
3165 | { | ||
3166 | *p++ = decimal_point_char (); | ||
3167 | for (; precision > 0; precision--) | ||
3168 | *p++ = '0'; | ||
3169 | } | ||
3170 | *p++ = dp->conversion; /* 'e' or 'E' */ | ||
3171 | *p++ = '+'; | ||
3172 | *p++ = '0'; | ||
3173 | *p++ = '0'; | ||
3174 | } | ||
3175 | else if (dp->conversion == 'g' || dp->conversion == 'G') | ||
3176 | { | ||
3177 | *p++ = '0'; | ||
3178 | if (flags & FLAG_ALT) | ||
3179 | { | ||
3180 | size_t ndigits = | ||
3181 | (precision > 0 ? precision - 1 : 0); | ||
3182 | *p++ = decimal_point_char (); | ||
3183 | for (; ndigits > 0; --ndigits) | ||
3184 | *p++ = '0'; | ||
3185 | } | ||
3186 | } | ||
3187 | else if (dp->conversion == 'a' || dp->conversion == 'A') | ||
3188 | { | ||
3189 | *p++ = '0'; | ||
3190 | *p++ = dp->conversion - 'A' + 'X'; | ||
3191 | pad_ptr = p; | ||
3192 | *p++ = '0'; | ||
3193 | if ((flags & FLAG_ALT) || precision > 0) | ||
3194 | { | ||
3195 | *p++ = decimal_point_char (); | ||
3196 | for (; precision > 0; precision--) | ||
3197 | *p++ = '0'; | ||
3198 | } | ||
3199 | *p++ = dp->conversion - 'A' + 'P'; | ||
3200 | *p++ = '+'; | ||
3201 | *p++ = '0'; | ||
3202 | } | ||
3203 | else | ||
3204 | abort (); | ||
3069 | # endif | 3205 | # endif |
3070 | } | 3206 | } |
3071 | 3207 | ||
@@ -3211,8 +3347,31 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, | |||
3211 | exponent += 1; | 3347 | exponent += 1; |
3212 | adjusted = 1; | 3348 | adjusted = 1; |
3213 | } | 3349 | } |
3214 | |||
3215 | /* Here ndigits = precision+1. */ | 3350 | /* Here ndigits = precision+1. */ |
3351 | if (is_borderline (digits, precision)) | ||
3352 | { | ||
3353 | /* Maybe the exponent guess was too high | ||
3354 | and a smaller exponent can be reached | ||
3355 | by turning a 10...0 into 9...9x. */ | ||
3356 | char *digits2 = | ||
3357 | scale10_round_decimal_double (arg, | ||
3358 | (int)precision - exponent + 1); | ||
3359 | if (digits2 == NULL) | ||
3360 | { | ||
3361 | free (digits); | ||
3362 | goto out_of_memory; | ||
3363 | } | ||
3364 | if (strlen (digits2) == precision + 1) | ||
3365 | { | ||
3366 | free (digits); | ||
3367 | digits = digits2; | ||
3368 | exponent -= 1; | ||
3369 | } | ||
3370 | else | ||
3371 | free (digits2); | ||
3372 | } | ||
3373 | /* Here ndigits = precision+1. */ | ||
3374 | |||
3216 | *p++ = digits[--ndigits]; | 3375 | *p++ = digits[--ndigits]; |
3217 | if ((flags & FLAG_ALT) || precision > 0) | 3376 | if ((flags & FLAG_ALT) || precision > 0) |
3218 | { | 3377 | { |
@@ -3337,6 +3496,29 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, | |||
3337 | adjusted = 1; | 3496 | adjusted = 1; |
3338 | } | 3497 | } |
3339 | /* Here ndigits = precision. */ | 3498 | /* Here ndigits = precision. */ |
3499 | if (is_borderline (digits, precision - 1)) | ||
3500 | { | ||
3501 | /* Maybe the exponent guess was too high | ||
3502 | and a smaller exponent can be reached | ||
3503 | by turning a 10...0 into 9...9x. */ | ||
3504 | char *digits2 = | ||
3505 | scale10_round_decimal_double (arg, | ||
3506 | (int)(precision - 1) - exponent + 1); | ||
3507 | if (digits2 == NULL) | ||
3508 | { | ||
3509 | free (digits); | ||
3510 | goto out_of_memory; | ||
3511 | } | ||
3512 | if (strlen (digits2) == precision) | ||
3513 | { | ||
3514 | free (digits); | ||
3515 | digits = digits2; | ||
3516 | exponent -= 1; | ||
3517 | } | ||
3518 | else | ||
3519 | free (digits2); | ||
3520 | } | ||
3521 | /* Here ndigits = precision. */ | ||
3340 | 3522 | ||
3341 | /* Determine the number of trailing zeroes | 3523 | /* Determine the number of trailing zeroes |
3342 | that have to be dropped. */ | 3524 | that have to be dropped. */ |
@@ -3588,7 +3770,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, | |||
3588 | #endif | 3770 | #endif |
3589 | TCHAR_T *fbp; | 3771 | TCHAR_T *fbp; |
3590 | unsigned int prefix_count; | 3772 | unsigned int prefix_count; |
3591 | int prefixes[2]; | 3773 | int prefixes[2] IF_LINT (= { 0 }); |
3592 | #if !USE_SNPRINTF | 3774 | #if !USE_SNPRINTF |
3593 | size_t tmp_length; | 3775 | size_t tmp_length; |
3594 | TCHAR_T tmpbuf[700]; | 3776 | TCHAR_T tmpbuf[700]; |
@@ -3661,6 +3843,44 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, | |||
3661 | } | 3843 | } |
3662 | #endif | 3844 | #endif |
3663 | 3845 | ||
3846 | /* Decide whether to handle the precision ourselves. */ | ||
3847 | #if NEED_PRINTF_UNBOUNDED_PRECISION | ||
3848 | switch (dp->conversion) | ||
3849 | { | ||
3850 | case 'd': case 'i': case 'u': | ||
3851 | case 'o': | ||
3852 | case 'x': case 'X': case 'p': | ||
3853 | prec_ourselves = has_precision && (precision > 0); | ||
3854 | break; | ||
3855 | default: | ||
3856 | prec_ourselves = 0; | ||
3857 | break; | ||
3858 | } | ||
3859 | #endif | ||
3860 | |||
3861 | /* Decide whether to perform the padding ourselves. */ | ||
3862 | #if !NEED_PRINTF_FLAG_LEFTADJUST && (!DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION) | ||
3863 | switch (dp->conversion) | ||
3864 | { | ||
3865 | # if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO | ||
3866 | /* If we need conversion from TCHAR_T[] to DCHAR_T[], we need | ||
3867 | to perform the padding after this conversion. Functions | ||
3868 | with unistdio extensions perform the padding based on | ||
3869 | character count rather than element count. */ | ||
3870 | case 'c': case 's': | ||
3871 | # endif | ||
3872 | # if NEED_PRINTF_FLAG_ZERO | ||
3873 | case 'f': case 'F': case 'e': case 'E': case 'g': case 'G': | ||
3874 | case 'a': case 'A': | ||
3875 | # endif | ||
3876 | pad_ourselves = 1; | ||
3877 | break; | ||
3878 | default: | ||
3879 | pad_ourselves = prec_ourselves; | ||
3880 | break; | ||
3881 | } | ||
3882 | #endif | ||
3883 | |||
3664 | #if !USE_SNPRINTF | 3884 | #if !USE_SNPRINTF |
3665 | /* Allocate a temporary buffer of sufficient size for calling | 3885 | /* Allocate a temporary buffer of sufficient size for calling |
3666 | sprintf. */ | 3886 | sprintf. */ |
@@ -3837,18 +4057,22 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, | |||
3837 | abort (); | 4057 | abort (); |
3838 | } | 4058 | } |
3839 | 4059 | ||
4060 | if (!pad_ourselves) | ||
4061 | { | ||
3840 | # if ENABLE_UNISTDIO | 4062 | # if ENABLE_UNISTDIO |
3841 | /* Padding considers the number of characters, therefore the | 4063 | /* Padding considers the number of characters, therefore |
3842 | number of elements after padding may be | 4064 | the number of elements after padding may be |
3843 | > max (tmp_length, width) | 4065 | > max (tmp_length, width) |
3844 | but is certainly | 4066 | but is certainly |
3845 | <= tmp_length + width. */ | 4067 | <= tmp_length + width. */ |
3846 | tmp_length = xsum (tmp_length, width); | 4068 | tmp_length = xsum (tmp_length, width); |
3847 | # else | 4069 | # else |
3848 | /* Padding considers the number of elements, says POSIX. */ | 4070 | /* Padding considers the number of elements, |
3849 | if (tmp_length < width) | 4071 | says POSIX. */ |
3850 | tmp_length = width; | 4072 | if (tmp_length < width) |
4073 | tmp_length = width; | ||
3851 | # endif | 4074 | # endif |
4075 | } | ||
3852 | 4076 | ||
3853 | tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */ | 4077 | tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */ |
3854 | } | 4078 | } |
@@ -3869,44 +4093,6 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, | |||
3869 | } | 4093 | } |
3870 | #endif | 4094 | #endif |
3871 | 4095 | ||
3872 | /* Decide whether to handle the precision ourselves. */ | ||
3873 | #if NEED_PRINTF_UNBOUNDED_PRECISION | ||
3874 | switch (dp->conversion) | ||
3875 | { | ||
3876 | case 'd': case 'i': case 'u': | ||
3877 | case 'o': | ||
3878 | case 'x': case 'X': case 'p': | ||
3879 | prec_ourselves = has_precision && (precision > 0); | ||
3880 | break; | ||
3881 | default: | ||
3882 | prec_ourselves = 0; | ||
3883 | break; | ||
3884 | } | ||
3885 | #endif | ||
3886 | |||
3887 | /* Decide whether to perform the padding ourselves. */ | ||
3888 | #if !NEED_PRINTF_FLAG_LEFTADJUST && (!DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION) | ||
3889 | switch (dp->conversion) | ||
3890 | { | ||
3891 | # if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO | ||
3892 | /* If we need conversion from TCHAR_T[] to DCHAR_T[], we need | ||
3893 | to perform the padding after this conversion. Functions | ||
3894 | with unistdio extensions perform the padding based on | ||
3895 | character count rather than element count. */ | ||
3896 | case 'c': case 's': | ||
3897 | # endif | ||
3898 | # if NEED_PRINTF_FLAG_ZERO | ||
3899 | case 'f': case 'F': case 'e': case 'E': case 'g': case 'G': | ||
3900 | case 'a': case 'A': | ||
3901 | # endif | ||
3902 | pad_ourselves = 1; | ||
3903 | break; | ||
3904 | default: | ||
3905 | pad_ourselves = prec_ourselves; | ||
3906 | break; | ||
3907 | } | ||
3908 | #endif | ||
3909 | |||
3910 | /* Construct the format string for calling snprintf or | 4096 | /* Construct the format string for calling snprintf or |
3911 | sprintf. */ | 4097 | sprintf. */ |
3912 | fbp = buf; | 4098 | fbp = buf; |
@@ -4052,7 +4238,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, | |||
4052 | abort (); | 4238 | abort (); |
4053 | prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int; | 4239 | prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int; |
4054 | } | 4240 | } |
4055 | if (dp->precision_arg_index != ARG_NONE) | 4241 | if (!prec_ourselves && dp->precision_arg_index != ARG_NONE) |
4056 | { | 4242 | { |
4057 | if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) | 4243 | if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) |
4058 | abort (); | 4244 | abort (); |
@@ -4403,14 +4589,14 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, | |||
4403 | } | 4589 | } |
4404 | #endif | 4590 | #endif |
4405 | 4591 | ||
4406 | #if !DCHAR_IS_TCHAR | 4592 | #if !USE_SNPRINTF |
4407 | # if !USE_SNPRINTF | ||
4408 | if (count >= tmp_length) | 4593 | if (count >= tmp_length) |
4409 | /* tmp_length was incorrectly calculated - fix the | 4594 | /* tmp_length was incorrectly calculated - fix the |
4410 | code above! */ | 4595 | code above! */ |
4411 | abort (); | 4596 | abort (); |
4412 | # endif | 4597 | #endif |
4413 | 4598 | ||
4599 | #if !DCHAR_IS_TCHAR | ||
4414 | /* Convert from TCHAR_T[] to DCHAR_T[]. */ | 4600 | /* Convert from TCHAR_T[] to DCHAR_T[]. */ |
4415 | if (dp->conversion == 'c' || dp->conversion == 's') | 4601 | if (dp->conversion == 'c' || dp->conversion == 's') |
4416 | { | 4602 | { |
@@ -4528,7 +4714,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, | |||
4528 | if (w < width) | 4714 | if (w < width) |
4529 | { | 4715 | { |
4530 | size_t pad = width - w; | 4716 | size_t pad = width - w; |
4531 | # if USE_SNPRINTF | 4717 | |
4532 | /* Make room for the result. */ | 4718 | /* Make room for the result. */ |
4533 | if (xsum (count, pad) > allocated - length) | 4719 | if (xsum (count, pad) > allocated - length) |
4534 | { | 4720 | { |
@@ -4538,12 +4724,16 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, | |||
4538 | xmax (xsum3 (length, count, pad), | 4724 | xmax (xsum3 (length, count, pad), |
4539 | xtimes (allocated, 2)); | 4725 | xtimes (allocated, 2)); |
4540 | 4726 | ||
4727 | # if USE_SNPRINTF | ||
4541 | length += count; | 4728 | length += count; |
4542 | ENSURE_ALLOCATION (n); | 4729 | ENSURE_ALLOCATION (n); |
4543 | length -= count; | 4730 | length -= count; |
4731 | # else | ||
4732 | ENSURE_ALLOCATION (n); | ||
4733 | # endif | ||
4544 | } | 4734 | } |
4545 | /* Here count + pad <= allocated - length. */ | 4735 | /* Here count + pad <= allocated - length. */ |
4546 | # endif | 4736 | |
4547 | { | 4737 | { |
4548 | # if !DCHAR_IS_TCHAR || USE_SNPRINTF | 4738 | # if !DCHAR_IS_TCHAR || USE_SNPRINTF |
4549 | DCHAR_T * const rp = result + length; | 4739 | DCHAR_T * const rp = result + length; |
@@ -4553,7 +4743,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, | |||
4553 | DCHAR_T *p = rp + count; | 4743 | DCHAR_T *p = rp + count; |
4554 | DCHAR_T *end = p + pad; | 4744 | DCHAR_T *end = p + pad; |
4555 | DCHAR_T *pad_ptr; | 4745 | DCHAR_T *pad_ptr; |
4556 | # if !DCHAR_IS_TCHAR | 4746 | # if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO |
4557 | if (dp->conversion == 'c' | 4747 | if (dp->conversion == 'c' |
4558 | || dp->conversion == 's') | 4748 | || dp->conversion == 's') |
4559 | /* No zero-padding for string directives. */ | 4749 | /* No zero-padding for string directives. */ |
@@ -4604,13 +4794,6 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, | |||
4604 | } | 4794 | } |
4605 | #endif | 4795 | #endif |
4606 | 4796 | ||
4607 | #if DCHAR_IS_TCHAR && !USE_SNPRINTF | ||
4608 | if (count >= tmp_length) | ||
4609 | /* tmp_length was incorrectly calculated - fix the | ||
4610 | code above! */ | ||
4611 | abort (); | ||
4612 | #endif | ||
4613 | |||
4614 | /* Here still count <= allocated - length. */ | 4797 | /* Here still count <= allocated - length. */ |
4615 | 4798 | ||
4616 | #if !DCHAR_IS_TCHAR || USE_SNPRINTF | 4799 | #if !DCHAR_IS_TCHAR || USE_SNPRINTF |