Hi

Attached patch fixes further problems with printf()
for floats in Vim-7.4.2290.

Padding with 0 did not work properly when there is a sign:

:echo printf("%06.2f", -1.0)
Actual: "0-1.00"
Expected: "-01.00"

Forcing sign was not honored:

:echo printf("%+.2f", 1.0)
Actual:  "1.00"
Expected: "+1.00"

%F was the same as %f, but it should differ for INF and NAN:

:echo printf("%F", 1.0/0.0)
Actual: inf
Expected: INF

As far as I can tell, all issues I described earlier with
printf() should now be fixed.

Patch also slightly improves test coverage of printf().

Regards
Dominique

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 011807b..82fe052 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -5905,9 +5905,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 +6040,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
diff --git a/src/message.c b/src/message.c
index 92e7353..fbffedf 100644
--- a/src/message.c
+++ b/src/message.c
@@ -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,29 @@ 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 +4808,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 +4865,13 @@ vim_vsnprintf(
 			    }
 			}
 		    }
+		    if (zero_padding && min_field_width > str_arg_l)
+			if (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;
 		}
diff --git a/src/testdir/test_expr.vim b/src/testdir/test_expr.vim
index 11ca288..3097daf 100644
--- a/src/testdir/test_expr.vim
+++ b/src/testdir/test_expr.vim
@@ -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))

Raspunde prin e-mail lui