Merge #6231 from jbradaric/vim-7.4.2266

vim-patch:7.4.2266,7.4.2280,7.4.2291
This commit is contained in:
Justin M. Keyes
2017-03-22 00:29:58 +01:00
committed by GitHub
4 changed files with 184 additions and 35 deletions

View File

@@ -5683,9 +5683,10 @@ printf({fmt}, {expr1} ...) *printf()*
%04x hex number padded with zeros to at least 4 characters %04x hex number padded with zeros to at least 4 characters
%X hex number using upper case letters %X hex number using upper case letters
%o octal number %o octal number
%f floating point number in the form 123.456 %f floating point number as 12.23, inf, -inf or nan
%e floating point number in the form 1.234e3 %F floating point number as 12.23, INF, -INF or NAN
%E floating point number in the form 1.234E3 %e floating point number as 1.23e3, inf, -inf or nan
%E floating point number as 1.23E3, INF, -INF or NAN
%g floating point number, as %f or %e depending on value %g floating point number, as %f or %e depending on value
%G floating point number, as %f or %E depending on value %G floating point number, as %f or %E depending on value
%% the % character itself %% the % character itself
@@ -5810,8 +5811,9 @@ printf({fmt}, {expr1} ...) *printf()*
digits after the decimal point. When the precision is digits after the decimal point. When the precision is
zero the decimal point is omitted. When the precision zero the decimal point is omitted. When the precision
is not specified 6 is used. A really big number is not specified 6 is used. A really big number
(out of range or dividing by zero) results in "inf". (out of range or dividing by zero) results in "inf"
"0.0 / 0.0" results in "nan". or "-inf" with %f (INF or -INF with %F).
"0.0 / 0.0" results in "nan" with %f (NAN with %F).
Example: > Example: >
echo printf("%.2f", 12.115) echo printf("%.2f", 12.115)
< 12.12 < 12.12

View File

@@ -753,6 +753,22 @@ int vim_snprintf(char *str, size_t str_m, const char *fmt, ...)
return str_l; return str_l;
} }
// Return the representation of infinity for printf() function:
// "-inf", "inf", "+inf", " inf", "-INF", "INF", "+INF" or " INF".
static const char *infinity_str(bool positive, char fmt_spec,
int force_sign, int space_for_positive)
{
static const char *table[] = {
"-inf", "inf", "+inf", " inf",
"-INF", "INF", "+INF", " INF"
};
int idx = positive * (1 + force_sign + force_sign * space_for_positive);
if (ASCII_ISUPPER(fmt_spec)) {
idx += 4;
}
return table[idx];
}
/// Write formatted value to the string /// Write formatted value to the string
/// ///
@@ -909,7 +925,6 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap,
case 'D': fmt_spec = 'd'; length_modifier = 'l'; break; case 'D': fmt_spec = 'd'; length_modifier = 'l'; break;
case 'U': fmt_spec = 'u'; length_modifier = 'l'; break; case 'U': fmt_spec = 'u'; length_modifier = 'l'; break;
case 'O': fmt_spec = 'o'; length_modifier = 'l'; break; case 'O': fmt_spec = 'o'; length_modifier = 'l'; break;
case 'F': fmt_spec = 'f'; break;
default: break; default: break;
} }
@@ -1186,6 +1201,7 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap,
} }
case 'f': case 'f':
case 'F':
case 'e': case 'e':
case 'E': case 'E':
case 'g': case 'g':
@@ -1201,36 +1217,49 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap,
if (fmt_spec == 'g' || fmt_spec == 'G') { if (fmt_spec == 'g' || fmt_spec == 'G') {
// can't use %g directly, cause it prints "1.0" as "1" // can't use %g directly, cause it prints "1.0" as "1"
if ((abs_f >= 0.001 && abs_f < 10000000.0) || abs_f == 0.0) { if ((abs_f >= 0.001 && abs_f < 10000000.0) || abs_f == 0.0) {
fmt_spec = 'f'; fmt_spec = ASCII_ISUPPER(fmt_spec) ? 'F' : 'f';
} else { } else {
fmt_spec = fmt_spec == 'g' ? 'e' : 'E'; fmt_spec = fmt_spec == 'g' ? 'e' : 'E';
} }
remove_trailing_zeroes = true; remove_trailing_zeroes = true;
} }
if (fmt_spec == 'f' && abs_f > 1.0e307) { if (isinf(f)
// avoid a buffer overflow || (strchr("fF", fmt_spec) != NULL && abs_f > 1.0e307)) {
memmove(tmp, "inf", sizeof("inf")); xstrlcpy(tmp, infinity_str(f > 0.0, fmt_spec,
str_arg_l = sizeof("inf") - 1; force_sign, space_for_positive),
sizeof(tmp));
str_arg_l = strlen(tmp);
zero_padding = 0;
} else if (isnan(f)) {
// Not a number: nan or NAN
memmove(tmp, ASCII_ISUPPER(fmt_spec) ? "NAN" : "nan", 4);
str_arg_l = 3;
zero_padding = 0;
} else { } else {
format[0] = '%'; format[0] = '%';
int l = 1; size_t l = 1;
if (force_sign) {
format[l++] = space_for_positive ? ' ' : '+';
}
if (precision_specified) { if (precision_specified) {
size_t max_prec = TMP_LEN - 10; size_t max_prec = TMP_LEN - 10;
// make sure we don't get more digits than we have room for // make sure we don't get more digits than we have room for
if (fmt_spec == 'f' && abs_f > 1.0) { if ((fmt_spec == 'f' || fmt_spec == 'F') && abs_f > 1.0) {
max_prec -= (size_t)log10(abs_f); max_prec -= (size_t)log10(abs_f);
} }
if (precision > max_prec) { if (precision > max_prec) {
precision = max_prec; precision = max_prec;
} }
l += snprintf(format + 1, sizeof(format) - 1, ".%d", l += (size_t)snprintf(format + l, sizeof(format) - l, ".%d",
(int)precision); (int)precision);
} }
format[l] = (char)(fmt_spec == 'F' ? 'f' : fmt_spec); format[l] = fmt_spec == 'F' ? 'f' : fmt_spec;
format[l + 1] = NUL; format[l + 1] = NUL;
assert(l + 1 < (int)sizeof(format));
// Regular float number
assert(l + 1 < sizeof(format));
str_arg_l = (size_t)snprintf(tmp, sizeof(tmp), format, f); str_arg_l = (size_t)snprintf(tmp, sizeof(tmp), format, f);
assert(str_arg_l < sizeof(tmp)); assert(str_arg_l < sizeof(tmp));
@@ -1239,7 +1268,7 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap,
char *tp; char *tp;
// using %g or %G: remove superfluous zeroes // using %g or %G: remove superfluous zeroes
if (fmt_spec == 'f') { if (fmt_spec == 'f' || fmt_spec == 'F') {
tp = tmp + str_arg_l - 1; tp = tmp + str_arg_l - 1;
} else { } else {
tp = (char *)vim_strchr((char_u *)tmp, tp = (char *)vim_strchr((char_u *)tmp,
@@ -1281,6 +1310,12 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap,
} }
} }
} }
if (zero_padding && min_field_width > str_arg_l
&& (tmp[0] == '-' || force_sign)) {
// Padding 0's should be inserted after the sign.
number_of_zeros_to_pad = min_field_width - str_arg_l;
zero_padding_insertion_ind = 1;
}
str_arg = tmp; str_arg = tmp;
break; break;
} }

View File

@@ -152,20 +152,52 @@ function Test_printf_misc()
call assert_equal(' 123', printf('% d', 123)) call assert_equal(' 123', printf('% d', 123))
call assert_equal('-123', printf('% d', -123)) call assert_equal('-123', printf('% d', -123))
call assert_equal('123', printf('%2d', 123))
call assert_equal(' 123', printf('%6d', 123))
call assert_equal('000123', printf('%06d', 123))
call assert_equal('+00123', printf('%+06d', 123))
call assert_equal(' 00123', printf('% 06d', 123))
call assert_equal(' +123', printf('%+6d', 123))
call assert_equal(' 123', printf('% 6d', 123))
call assert_equal(' -123', printf('% 6d', -123))
" Test left adjusted.
call assert_equal('123 ', printf('%-6d', 123))
call assert_equal('+123 ', printf('%-+6d', 123))
call assert_equal(' 123 ', printf('%- 6d', 123))
call assert_equal('-123 ', printf('%- 6d', -123))
call assert_equal(' 00123', printf('%7.5d', 123))
call assert_equal(' -00123', printf('%7.5d', -123))
call assert_equal(' +00123', printf('%+7.5d', 123))
" Precision field should not be used when combined with %0
call assert_equal(' 00123', printf('%07.5d', 123))
call assert_equal(' -00123', printf('%07.5d', -123))
call assert_equal(' 123', printf('%*d', 5, 123))
call assert_equal('123 ', printf('%*d', -5, 123))
call assert_equal('00123', printf('%.*d', 5, 123)) call assert_equal('00123', printf('%.*d', 5, 123))
call assert_equal(' 123', printf('% *d', 5, 123)) call assert_equal(' 123', printf('% *d', 5, 123))
call assert_equal(' +123', printf('%+ *d', 5, 123)) call assert_equal(' +123', printf('%+ *d', 5, 123))
call assert_equal('123', printf('%2d', 123)) " Simple quote (thousand grouping char) is ignored.
call assert_equal(' 123', printf('%5d', 123)) call assert_equal('+00123456', printf("%+'09d", 123456))
call assert_equal('00123', printf('%05d', 123))
call assert_equal('123 ', printf('%-5d', 123)) " Unrecognized format specifier kept as-is.
call assert_equal('_123', printf("%_%d", 123))
" Test alternate forms.
call assert_equal('0x7b', printf('%#x', 123)) call assert_equal('0x7b', printf('%#x', 123))
call assert_equal('0X7B', printf('%#X', 123)) call assert_equal('0X7B', printf('%#X', 123))
call assert_equal('0173', printf('%#o', 123)) call assert_equal('0173', printf('%#o', 123))
call assert_equal('0173', printf('%#O', 123)) call assert_equal('0173', printf('%#O', 123))
call assert_equal('abc', printf('%#s', 'abc')) call assert_equal('abc', printf('%#s', 'abc'))
call assert_equal('abc', printf('%#S', 'abc')) call assert_equal('abc', printf('%#S', 'abc'))
call assert_equal(' 0173', printf('%#6o', 123))
call assert_equal(' 00173', printf('%#6.5o', 123))
call assert_equal(' 0173', printf('%#6.2o', 123))
call assert_equal(' 0173', printf('%#6.2o', 123))
call assert_equal('0173', printf('%#2.2o', 123))
call assert_equal(' 00123', printf('%6.5d', 123)) call assert_equal(' 00123', printf('%6.5d', 123))
call assert_equal(' 0007b', printf('%6.5x', 123)) call assert_equal(' 0007b', printf('%6.5x', 123))
@@ -189,24 +221,104 @@ function Test_printf_misc()
endfunc endfunc
function Test_printf_float() function Test_printf_float()
call assert_equal('1.000000', printf('%f', 1))
call assert_equal('1.230000', printf('%f', 1.23)) call assert_equal('1.230000', printf('%f', 1.23))
call assert_equal('1.230000', printf('%F', 1.23)) call assert_equal('1.230000', printf('%F', 1.23))
call assert_equal('1.23', printf('%g', 1.23)) call assert_equal('9999999.9', printf('%g', 9999999.9))
call assert_equal('1.23', printf('%G', 1.23)) call assert_equal('9999999.9', printf('%G', 9999999.9))
call assert_equal('1.00000001e7', printf('%.8g', 10000000.1))
call assert_equal('1.00000001E7', printf('%.8G', 10000000.1))
call assert_equal('1.230000e+00', printf('%e', 1.23)) call assert_equal('1.230000e+00', printf('%e', 1.23))
call assert_equal('1.230000E+00', printf('%E', 1.23)) call assert_equal('1.230000E+00', printf('%E', 1.23))
call assert_equal('1.200000e-02', printf('%e', 0.012)) call assert_equal('1.200000e-02', printf('%e', 0.012))
call assert_equal('-1.200000e-02', printf('%e', -0.012)) call assert_equal('-1.200000e-02', printf('%e', -0.012))
call assert_equal('1.2', printf('%.1f', 1.23)) call assert_equal('0.33', printf('%.2f', 1.0/3.0))
call assert_equal(' 0.33', printf('%6.2f', 1.0/3.0))
call assert_equal(' -0.33', printf('%6.2f', -1.0/3.0))
call assert_equal('000.33', printf('%06.2f', 1.0/3.0))
call assert_equal('-00.33', printf('%06.2f', -1.0/3.0))
call assert_equal('-00.33', printf('%+06.2f', -1.0/3.0))
call assert_equal('+00.33', printf('%+06.2f', 1.0/3.0))
call assert_equal(' 00.33', printf('% 06.2f', 1.0/3.0))
call assert_equal('000.33', printf('%06.2g', 1.0/3.0))
call assert_equal('-00.33', printf('%06.2g', -1.0/3.0))
call assert_equal('0.33', printf('%3.2f', 1.0/3.0))
call assert_equal('003.33e-01', printf('%010.2e', 1.0/3.0))
call assert_equal(' 03.33e-01', printf('% 010.2e', 1.0/3.0))
call assert_equal('+03.33e-01', printf('%+010.2e', 1.0/3.0))
call assert_equal('-03.33e-01', printf('%010.2e', -1.0/3.0))
" When precision is 0, the dot should be omitted.
call assert_equal(' 2', printf('%3.f', 7.0/3.0))
call assert_equal(' 2', printf('%3.g', 7.0/3.0))
call assert_equal(' 2e+00', printf('%7.e', 7.0/3.0))
" Float zero can be signed.
call assert_equal('+0.000000', printf('%+f', 0.0))
call assert_equal('0.000000', printf('%f', 1.0/(1.0/0.0)))
call assert_equal('-0.000000', printf('%f', 1.0/(-1.0/0.0)))
call assert_equal('0.0', printf('%s', 1.0/(1.0/0.0)))
call assert_equal('-0.0', printf('%s', 1.0/(-1.0/0.0)))
call assert_equal('0.0', printf('%S', 1.0/(1.0/0.0)))
call assert_equal('-0.0', printf('%S', 1.0/(-1.0/0.0)))
" Float infinity can be signed.
call assert_equal('inf', printf('%f', 1.0/0.0)) call assert_equal('inf', printf('%f', 1.0/0.0))
call assert_equal('-inf', printf('%f', -1.0/0.0))
call assert_equal('inf', printf('%g', 1.0/0.0))
call assert_equal('-inf', printf('%g', -1.0/0.0))
call assert_equal('inf', printf('%e', 1.0/0.0))
call assert_equal('-inf', printf('%e', -1.0/0.0))
call assert_equal('INF', printf('%F', 1.0/0.0))
call assert_equal('-INF', printf('%F', -1.0/0.0))
call assert_equal('INF', printf('%E', 1.0/0.0))
call assert_equal('-INF', printf('%E', -1.0/0.0))
call assert_equal('INF', printf('%E', 1.0/0.0))
call assert_equal('-INF', printf('%G', -1.0/0.0))
call assert_equal('+inf', printf('%+f', 1.0/0.0))
call assert_equal('-inf', printf('%+f', -1.0/0.0))
call assert_equal(' inf', printf('% f', 1.0/0.0))
call assert_equal(' inf', printf('%6f', 1.0/0.0))
call assert_equal(' -inf', printf('%6f', -1.0/0.0))
call assert_equal(' inf', printf('%6g', 1.0/0.0))
call assert_equal(' -inf', printf('%6g', -1.0/0.0))
call assert_equal(' +inf', printf('%+6f', 1.0/0.0))
call assert_equal(' inf', printf('% 6f', 1.0/0.0))
call assert_equal(' +inf', printf('%+06f', 1.0/0.0))
call assert_equal('inf ', printf('%-6f', 1.0/0.0))
call assert_equal('-inf ', printf('%-6f', -1.0/0.0))
call assert_equal('+inf ', printf('%-+6f', 1.0/0.0))
call assert_equal(' inf ', printf('%- 6f', 1.0/0.0))
call assert_equal('-INF ', printf('%-6F', -1.0/0.0))
call assert_equal('+INF ', printf('%-+6F', 1.0/0.0))
call assert_equal(' INF ', printf('%- 6F', 1.0/0.0))
call assert_equal('INF ', printf('%-6G', 1.0/0.0))
call assert_equal('-INF ', printf('%-6G', -1.0/0.0))
call assert_equal('INF ', printf('%-6E', 1.0/0.0))
call assert_equal('-INF ', printf('%-6E', -1.0/0.0))
call assert_equal("str2float('inf')", printf('%s', 1.0/0.0))
call assert_equal("-str2float('inf')", printf('%s', -1.0/0.0))
" This prints inf but shouldn't it print -inf instead? " Float nan (not a number) has no sign.
call assert_match('^-\?inf$', printf('%f', -1.0/0.0)) call assert_equal('nan', printf('%f', sqrt(-1.0)))
call assert_equal('nan', printf('%f', 0.0/0.0))
" This prints -nan but shouldn't it print nan instead? call assert_equal('nan', printf('%f', -0.0/0.0))
call assert_match('^-\?nan$', printf('%f', sqrt(-1.0))) call assert_equal('nan', printf('%g', 0.0/0.0))
call assert_match('^-\?nan$', printf('%f', 0.0/0.0)) call assert_equal('nan', printf('%e', 0.0/0.0))
call assert_equal('NAN', printf('%F', 0.0/0.0))
call assert_equal('NAN', printf('%G', 0.0/0.0))
call assert_equal('NAN', printf('%E', 0.0/0.0))
call assert_equal('NAN', printf('%F', -0.0/0.0))
call assert_equal('NAN', printf('%G', -0.0/0.0))
call assert_equal('NAN', printf('%E', -0.0/0.0))
call assert_equal(' nan', printf('%6f', 0.0/0.0))
call assert_equal(' nan', printf('%06f', 0.0/0.0))
call assert_equal('nan ', printf('%-6f', 0.0/0.0))
call assert_equal('nan ', printf('%- 6f', 0.0/0.0))
call assert_equal("str2float('nan')", printf('%s', 0.0/0.0))
call assert_equal("str2float('nan')", printf('%s', -0.0/0.0))
call assert_equal("str2float('nan')", printf('%S', 0.0/0.0))
call assert_equal("str2float('nan')", printf('%S', -0.0/0.0))
call assert_fails('echo printf("%f", "a")', 'E807:') call assert_fails('echo printf("%f", "a")', 'E807:')
endfunc endfunc

View File

@@ -150,7 +150,7 @@ static int included_patches[] = {
2294, 2294,
2293, 2293,
2292, 2292,
// 2291, 2291,
// 2290 NA // 2290 NA
// 2289 NA // 2289 NA
// 2288 NA // 2288 NA
@@ -161,7 +161,7 @@ static int included_patches[] = {
// 2283, // 2283,
// 2282 NA // 2282 NA
// 2281 NA // 2281 NA
// 2280, 2280,
2279, 2279,
// 2278 NA // 2278 NA
2277, 2277,
@@ -175,7 +175,7 @@ static int included_patches[] = {
// 2269, // 2269,
// 2268, // 2268,
// 2267 NA // 2267 NA
// 2266, 2266,
2265, 2265,
2264, 2264,
// 2263, // 2263,
@@ -220,7 +220,7 @@ static int included_patches[] = {
// 2224, // 2224,
2223, 2223,
2222, 2222,
// 2221, 2221,
2220, 2220,
2219, 2219,
// 2218 NA // 2218 NA