]> granicus.if.org Git - vim/commitdiff
patch 7.4.2291 v7.4.2291
authorBram Moolenaar <Bram@vim.org>
Mon, 29 Aug 2016 19:55:35 +0000 (21:55 +0200)
committerBram Moolenaar <Bram@vim.org>
Mon, 29 Aug 2016 19:55:35 +0000 (21:55 +0200)
Problem:    printf() handles floats wrong when there is a sign.
Solution:   Fix placing the sign.  Add tests. (Dominique Pelle)

runtime/doc/eval.txt
src/message.c
src/testdir/test_expr.vim
src/version.c

index 011807bfe54c45e6bde132a80f041d907bb8a40c..aa32839a0518d4f39cd5e1e4485b1d9258024d1d 100644 (file)
@@ -1,4 +1,4 @@
-*eval.txt*     For Vim version 7.4.  Last change: 2016 Aug 28
+*eval.txt*     For Vim version 7.4.  Last change: 2016 Aug 29
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -643,7 +643,7 @@ It's possible to form a variable name with curly braces, see
 
 Expression syntax summary, from least to most significant:
 
-|expr1| expr2 ? expr1 : expr1  if-then-else
+|expr1|   expr2 ? expr1 : expr1        if-then-else
 
 |expr2|        expr3 || expr3 ..       logical OR
 
@@ -736,7 +736,9 @@ use in a variable such as "a:1".
 expr2 and expr3                                                *expr2* *expr3*
 ---------------
 
-                                       *expr-barbar* *expr-&&*
+expr3 || expr3 ..      logical OR              *expr-barbar*
+expr4 && expr4 ..      logical AND             *expr-&&*
+
 The "||" and "&&" operators take one argument on each side.  The arguments
 are (converted to) Numbers.  The result is:
 
@@ -1981,7 +1983,7 @@ assert_notmatch({pat}, {text} [, {msg}]) none  assert {pat} not matches {text}
 assert_true({actual} [, {msg}])          none  assert {actual} is true
 asin({expr})                   Float   arc sine of {expr}
 atan({expr})                   Float   arc tangent of {expr}
-atan2({expr}, {expr})          Float   arc tangent of {expr1} / {expr2}
+atan2({expr1}, {expr2})                Float   arc tangent of {expr1} / {expr2}
 browse({save}, {title}, {initdir}, {default})
                                String  put up a file requester
 browsedir({title}, {initdir})  String  put up a directory requester
@@ -5905,9 +5907,10 @@ printf({fmt}, {expr1} ...)                               *printf()*
                  %X    hex number using upper case letters
                  %o    octal number
                  %08b  binary number padded with zeros to at least 8 chars
-                 %f    floating point number in the form 123.456
-                 %e    floating point number in the form 1.234e3
-                 %E    floating point number in the form 1.234E3
+                 %f    floating point number as 12.23, inf, -inf or nan
+                 %F    floating point number as 12.23, INF, -INF or NAN
+                 %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
                  %%    the % character itself
@@ -6039,8 +6042,9 @@ printf({fmt}, {expr1} ...)                                *printf()*
                        digits after the decimal point.  When the precision is
                        zero the decimal point is omitted.  When the precision
                        is not specified 6 is used.  A really big number
-                       (out of range or dividing by zero) results in "inf".
-                       "0.0 / 0.0" results in "nan".
+                       (out of range or dividing by zero) results in "inf"
+                        or "-inf" with %f (INF or -INF with %F).
+                        "0.0 / 0.0" results in "nan" with %f (NAN with %F).
                        Example: >
                                echo printf("%.2f", 12.115)
 <                              12.12
@@ -7507,7 +7511,7 @@ system({expr} [, {input}])                                *system()* *E677*
 
                Pipes are not used, the 'shelltemp' option is not used.
 
-               When prepended by |:silent| the shell will not be set to
+               When prepended by |:silent| the terminal will not be set to
                cooked mode.  This is meant to be used for commands that do
                not need the user to type.  It avoids stray characters showing
                up on the screen which require |CTRL-L| to remove. >
index 92e735349d9e116e66e6d872e92eee09aeed5617..264d15a1219077f31382728a80d67d361252cbd1 100644 (file)
@@ -4030,7 +4030,7 @@ infinity_str(int positive,
  * with flags: '-', '+', ' ', '0' and '#'.
  * An asterisk is supported for field width as well as precision.
  *
- * Limited support for floating point was added: 'f', 'e', 'E', 'g', 'G'.
+ * Limited support for floating point was added: 'f', 'F', 'e', 'E', 'g', 'G'.
  *
  * Length modifiers 'h' (short int) and 'l' (long int) and 'll' (long long int)
  * are supported.
@@ -4286,7 +4286,6 @@ vim_vsnprintf(
                case 'D': fmt_spec = 'd'; length_modifier = 'l'; break;
                case 'U': fmt_spec = 'u'; length_modifier = 'l'; break;
                case 'O': fmt_spec = 'o'; length_modifier = 'l'; break;
-               case 'F': fmt_spec = 'f'; break;
                default: break;
            }
 
@@ -4715,6 +4714,7 @@ vim_vsnprintf(
 
 # ifdef FEAT_FLOAT
            case 'f':
+           case 'F':
            case 'e':
            case 'E':
            case 'g':
@@ -4740,13 +4740,13 @@ vim_vsnprintf(
                         * "1.0" as "1", we don't want that. */
                        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
                            fmt_spec = fmt_spec == 'g' ? 'e' : 'E';
                        remove_trailing_zeroes = TRUE;
                    }
 
-                   if (fmt_spec == 'f' &&
+                   if ((fmt_spec == 'f' || fmt_spec == 'F') &&
 #  ifdef VAX
                            abs_f > 1.0e38
 #  else
@@ -4762,23 +4762,6 @@ vim_vsnprintf(
                    }
                    else
                    {
-                       format[0] = '%';
-                       l = 1;
-                       if (precision_specified)
-                       {
-                           size_t max_prec = TMP_LEN - 10;
-
-                           /* Make sure we don't get more digits than we
-                            * have room for. */
-                           if (fmt_spec == 'f' && abs_f > 1.0)
-                               max_prec -= (size_t)log10(abs_f);
-                           if (precision > max_prec)
-                               precision = max_prec;
-                           l += sprintf(format + 1, ".%d", (int)precision);
-                       }
-                       format[l] = fmt_spec;
-                       format[l + 1] = NUL;
-
                        if (isnan(f))
                        {
                            /* Not a number: nan or NAN */
@@ -4795,8 +4778,30 @@ vim_vsnprintf(
                            zero_padding = 0;
                        }
                        else
+                        {
                            /* Regular float number */
+                           format[0] = '%';
+                           l = 1;
+                           if (force_sign)
+                               format[l++] = space_for_positive ? ' ' : '+';
+                           if (precision_specified)
+                           {
+                               size_t max_prec = TMP_LEN - 10;
+
+                               /* Make sure we don't get more digits than we
+                                * have room for. */
+                               if ((fmt_spec == 'f' || fmt_spec == 'F')
+                                                               && abs_f > 1.0)
+                                   max_prec -= (size_t)log10(abs_f);
+                               if (precision > max_prec)
+                                   precision = max_prec;
+                               l += sprintf(format + l, ".%d", (int)precision);
+                           }
+                           format[l] = fmt_spec;
+                           format[l + 1] = NUL;
+
                            str_arg_l = sprintf(tmp, format, f);
+                        }
 
                        if (remove_trailing_zeroes)
                        {
@@ -4804,7 +4809,7 @@ vim_vsnprintf(
                            char *tp;
 
                            /* Using %g or %G: remove superfluous zeroes. */
-                           if (fmt_spec == 'f')
+                           if (fmt_spec == 'f' || fmt_spec == 'F')
                                tp = tmp + str_arg_l - 1;
                            else
                            {
@@ -4861,6 +4866,13 @@ vim_vsnprintf(
                            }
                        }
                    }
+                   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;
                    break;
                }
index 11ca288dde6894777914a27a6a6d47e4944a5bde..3097daf4437c5325ed431d216f7d29670b0e83fc 100644 (file)
@@ -162,21 +162,44 @@ function Test_printf_misc()
   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('  123', printf('% *d', 5, 123))
   call assert_equal(' +123', printf('%+ *d', 5, 123))
 
-  call assert_equal('123  ', printf('%-5d', 123))
+  " Simple quote (thousand grouping char) is ignored.
+  call assert_equal('+00123456', printf("%+'09d", 123456))
+
+  " 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('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('  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(' 0007b', printf('%6.5x', 123))
@@ -201,6 +224,7 @@ endfunc
 
 function Test_printf_float()
   if has('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('9999999.9', printf('%g', 9999999.9))
@@ -215,10 +239,31 @@ function Test_printf_float()
     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))
-    " FIXME: call assert_equal('-00.33', printf('%06.2f', -1.0/3.0))
-    " FIXME: call assert_equal('-00.33', printf('%+06.2f', -1.0/3.0))
-    " FIXME: call assert_equal('+00.33', printf('%+06.2f', 1.0/3.0))
-    " FIXME: 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(' 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))
@@ -227,6 +272,8 @@ function Test_printf_float()
     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))
@@ -245,6 +292,9 @@ function Test_printf_float()
     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))
@@ -252,22 +302,16 @@ function Test_printf_float()
     call assert_equal('inf', printf('%s', 1.0/0.0))
     call assert_equal('-inf', printf('%s', -1.0/0.0))
 
-    " Float zero can be signed.
-    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 nan (not a number) has no sign.
     call assert_equal('nan', printf('%f', sqrt(-1.0)))
     call assert_equal('nan', printf('%f', 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('%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))
index 3cae92ddeae003abadd8c3abcb68178936f30d2c..0d97662fb9f547385df04e1b5f41000c23ba7e36 100644 (file)
@@ -763,6 +763,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2291,
 /**/
     2290,
 /**/