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 |
