Hi
I found more unexpected results of printf() with
float infinity and float nan (not a number) values
using Vim-7.4.2275:
:echo printf('%+f', 1.0/0.0)
Expected: '+inf'
Actual: 'inf'
:echo printf('% f', 1.0/0.0)
Expected: ' inf'
Actual: 'inf'
:echo printf('%+06f', 1.0/0.0)
Expected: ' +inf'
Actual: '000inf'
:echo printf('%G', 0.0/0.0)
Expected: 'NAN'
Actual: '-NAN'
:echo printf('%6f', 0.0/0.0)
Expected: ' nan'
Actual: ' nan'
:echo printf('%06f', 0.0/0.0)
Expected: ' nan'
Actual: '00nan'
Code in Vim-7.4.2275 was also using isinf(f) == -1
which I don't think was portable as man isinf states:
=== BEGIN QUOTE man isinf ===
For isinf(), the standards merely say that the return value
is nonzero if and only if the argument has an infinite value.
=== END QUOTE ===
Attached patch fixes all those problems, and adds the
test cases to src/testdir/test_expr.vim. I could only test
it on Linux.
But there are remaining problems which I have not been
able to fix yet (they exist prior to my patch, so they are not
introduced by my patch):
:echo printf('%06.2f', -1.0/3.0)
Expected: '000.33'
Actual: '0-0.33'
:echo printf('%+06.2f', 1.0/3.0)
Expected: '+00.33'
Actual: '000.33'
:echo printf('% 06.2f', 1.0/3.0)
Expected: ' 00.33'
Actual: '000.33'
I added test cases for the remaining problems too, but they are
commented out as they currently fail.
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 vim_dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
diff --git a/src/message.c b/src/message.c
index 037d456..1db1cb3 100644
--- a/src/message.c
+++ b/src/message.c
@@ -3991,6 +3991,24 @@ tv_float(typval_T *tvs, int *idxp)
#endif
/*
+ * Return the representation of infinity for printf() function:
+ * "-inf", "inf", "+inf", " inf", "-INF", "INF", "+INF" or " INF".
+ */
+static const char *infinity_str(int 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];
+}
+
+/*
* This code was included to provide a portable vsnprintf() and snprintf().
* Some systems may provide their own, but we always use this one for
* consistency.
@@ -4008,8 +4026,8 @@ tv_float(typval_T *tvs, int *idxp)
*
* Limited support for floating point was added: 'f', 'e', 'E', 'g', 'G'.
*
- * Length modifiers 'h' (short int) and 'l' (long int) are supported.
- * 'll' (long long int) is not supported.
+ * Length modifiers 'h' (short int) and 'l' (long int) and 'll' (long long int)
+ * are supported.
*
* The locale is not used, the string is used as a byte string. This is only
* relevant for double-byte encodings where the second byte may be '%'.
@@ -4397,7 +4415,7 @@ vim_vsnprintf(
uvarnumber_T ullong_arg = 0;
# endif
- /* only defined for b convertion */
+ /* only defined for b conversion */
uvarnumber_T bin_arg = 0;
/* pointer argument value -only defined for p
@@ -4732,16 +4750,9 @@ vim_vsnprintf(
)
{
/* Avoid a buffer overflow */
- if (f < 0)
- {
- strcpy(tmp, "-inf");
- str_arg_l = 4;
- }
- else
- {
- strcpy(tmp, "inf");
- str_arg_l = 3;
- }
+ STRCPY(tmp, infinity_str(f > 0.0, fmt_spec, force_sign, space_for_positive));
+ str_arg_l = STRLEN(tmp);
+ zero_padding = 0;
}
else
{
@@ -4761,23 +4772,23 @@ vim_vsnprintf(
}
format[l] = fmt_spec;
format[l + 1] = NUL;
- str_arg_l = sprintf(tmp, format, f);
-
- /* Be consistent: Change "1.#IND" to "nan" and
- * "1.#INF" to "inf". */
- s = *tmp == '-' ? tmp + 1 : tmp;
- if (STRNCMP(s, "1.#INF", 6) == 0)
- STRCPY(s, "inf");
- else if (STRNCMP(s, "1.#IND", 6) == 0)
- STRCPY(s, "nan");
-
- /* Remove sign before "nan". */
- if (STRNCMP(tmp, "-nan", 4) == 0)
- STRCPY(tmp, "nan");
-
- /* Add sign before "inf" if needed. */
- if (isinf(f) == -1 && STRNCMP(tmp, "inf", 3) == 0)
- STRCPY(tmp, "-inf");
+
+ if (isnan(f))
+ {
+ /* Not a number: nan or NAN */
+ STRCPY(tmp, ASCII_ISUPPER(fmt_spec) ? "NAN" : "nan");
+ str_arg_l = 3;
+ zero_padding = 0;
+ }
+ else if (isinf(f))
+ {
+ STRCPY(tmp, infinity_str(f > 0.0, fmt_spec, force_sign, space_for_positive));
+ str_arg_l = STRLEN(tmp);
+ zero_padding = 0;
+ }
+ else
+ /* Regular float number */
+ str