On Wed, Apr 09, at 04:15 Charles E Campbell Jr wrote:
>
> Bram Moolenaar wrote:
> >
> > OK, so we do need to worry about this.
> >
> > This patch to message.c, replacing the previous one, should do it.
> >
> Hello!
>
> I applied the first patch, and it worked. However, the second one...
>
> vim71/ djinni? patch -p0 < ../diff_float2.ptch
> patching file src/message.c
> Hunk #2 FAILED at 3823.
> Hunk #3 succeeded at 3819 with fuzz 2 (offset -53 lines).
> Hunk #4 succeeded at 4000 with fuzz 2 (offset 84 lines).
> Hunk #5 succeeded at 3965 (offset -53 lines).
> Hunk #6 FAILED at 4113.
> Hunk #7 succeeded at 4618 with fuzz 2 (offset 116 lines).
> Hunk #8 FAILED at 4772.
> 3 out of 8 hunks FAILED -- saving rejects to file src/message.c.rej
>
Please try the attached patch on top of patch level 292.
Apply with -p1.
echo len(printf('%.350f', &100 / 3))
341
By the way, Thanks Bram!
--~--~---------~--~----~------------~-------~--~----~
You received this message from the "vim_dev" maillist.
For more information, visit http://www.vim.org/maillist.php
-~----------~----~----~----~------~----~------~--~---
diff -Naur vim71.orig/runtime/doc/eval.txt vim71/runtime/doc/eval.txt
--- vim71.orig/runtime/doc/eval.txt 2008-04-10 21:44:22.122448331 +0300
+++ vim71/runtime/doc/eval.txt 2008-04-10 21:40:51.361980814 +0300
@@ -39,11 +39,15 @@
*E712*
There are five types of variables:
-Number A 32 bit signed number.
+Number A 32 bit signed number. |expr-number|
Examples: -123 0x10 0177
+Float A floating point number. |floating-point-format|
+ {only when compiled with the |+float| feature}
+ Examples: 123.456 1.15e-6 -1.1e3
+
String A NUL terminated string of 8-bit unsigned characters (bytes).
- Examples: "ab\txx\"--" 'x-z''a,c'
+ |expr-string| Examples: "ab\txx\"--" 'x-z''a,c'
Funcref A reference to a function |Funcref|.
Example: function("strlen")
@@ -92,6 +96,10 @@
< *E745* *E728* *E703* *E729* *E730* *E731*
List, Dictionary and Funcref types are not automatically converted.
+ *E805* *E806*
+When mixing Number and Float the Number is converted to Float. Otherwise
+there is no automatic conversion of Float.
+
*E706*
You will get an error if you try to change the type of a variable. You need
to |:unlet| it first to avoid this error. String and Number are considered
@@ -258,13 +266,13 @@
< 0
Thus comparing Lists is more strict than comparing numbers and strings. You
-can compare simple values this way too by putting them in a string: >
+can compare simple values this way too by putting them in a list: >
:let a = 5
:let b = "5"
- echo a == b
+ :echo a == b
< 1 >
- echo [a] == [b]
+ :echo [a] == [b]
< 0
@@ -797,6 +805,8 @@
None of these work for |Funcref|s.
+. and % do not work for Float. *E804*
+
expr7 *expr7*
-----
@@ -909,6 +919,27 @@
Decimal, Hexadecimal (starting with 0x or 0X), or Octal (starting with 0).
+ *floating-point-format*
+Floating point numbers can be written in two forms:
+- &N.M, where N and M are numbers. The .M can be omitted. The N cannot be
+ omitted. There can be a minus sign in the N. Examples:
+ &123.456
+ &0.0001
+ &55
+ &-0.123
+ Only a decimal point is accepted, not a comma. No matter what the current
+ locale is.
+- Same, with a following exponent in the form "eX", where X is a decimal
+ number with an optional minus sign. The 'e' can also be upper case.
+ Examples:
+ &1.234e3
+ &1E-6
+ &-3.1416e88
+The precision and range of floating points numbers depends on the library Vim
+was compiled with. There is no way to change this at runtime.
+{only when compiled with the |+float| feature}
+
+
string *expr-string* *E114*
------
@@ -2024,7 +2055,7 @@
< The current 'encoding' is used. Example for "utf-8": >
char2nr("�") returns 225
char2nr("�"[0]) returns 195
-< nr2char() does the opposite.
+< |nr2char()| does the opposite.
cindent({lnum}) *cindent()*
Get the amount of indent for line {lnum} according the C
@@ -3893,6 +3924,9 @@
%04x hex number padded with zeros to at least 4 characters
%X hex number using upper case letters
%o octal number
+ %f floating point number in the form 123.456
+ %e floating point number in the form 1.234e3
+ %E floating pointer number in the form 1.234E3
%% the % character itself
Conversion specifications start with '%' and end with the
@@ -3951,6 +3985,8 @@
This gives the minimum number of digits to appear for
d, o, x, and X conversions, or the maximum number of
bytes to be printed from a string for s conversions.
+ For floating point it is the number of digits after
+ the decimal point.
type
A character that specifies the type of conversion to
@@ -3968,6 +4004,7 @@
The conversion specifiers and their meanings are:
+ *printf-d* *printf-o* *printf-x* *printf-X*
doxX The Number argument is converted to signed decimal
(d), unsigned octal (o), or unsigned hexadecimal (x
and X) notation. The letters "abcdef" are used for
@@ -3982,13 +4019,30 @@
a conversion is wider than the field width, the field
is expanded to contain the conversion result.
+ *printf-c*
c The Number argument is converted to a byte, and the
resulting character is written.
+ *printf-s*
s The text of the String argument is used. If a
precision is specified, no more bytes than the number
specified are used.
+ *printf-f* *E807*
+ f The Float argument is converted into a string of the
+ form 123.456. Currently doesn't do any padding. The
+ precision specifies the number of digits after the
+ decimal point. When the precision is zero the decimal
+ point is omitted. When the precision is not specified
+ 6 is used.
+
+ *printf-e* *printf-E*
+ e E The Float argument is converted into a string of the
+ form 1.234e3 or 1.234E3 (when using 'E'). The
+ precision specifies the number of digits after the
+ decimal point, like with 'f'.
+
+ *printf-%*
% A '%' is written. No argument is converted. The
complete conversion specification is "%%".
@@ -4781,6 +4835,19 @@
Text after the number is silently ignored.
+str2float( {expr}) *str2float()*
+ Convert string {expr} to a Float. This works the same as when
+ using a floating point number directly, see
+ |floating-point-format|, but without the leading '&'.
+ A comma is also accepted for a decimal point.
+ Text after the number is silently ignored.
+ A second comma or decimal point also ends the number:
+ "12,345.67" is converted to 12.345. You can strip out
+ thousands separators with |substitute()|: >
+ let f = str2float(substitute(text, ',', '', 'g'))
+< {only when compiled with the |+float| feature}
+
+
strftime({format} [, {time}]) *strftime()*
The result is a String, which is a formatted date and time, as
specified by the {format} string. The given {time} is used,
@@ -5142,6 +5209,7 @@
Funcref: 2
List: 3
Dictionary: 4
+ Float: 5
To avoid the magic numbers it should be used this way: >
:if type(myvar) == type(0)
:if type(myvar) == type("")
@@ -5200,6 +5268,8 @@
< This enters the same Visual mode as before. It is also useful
in scripts if you wish to act differently depending on the
Visual mode that was used.
+ If Visual mode is active, use |mode()| to get the Visual mode
+ (e.g., in a |:vmap|).
If an expression is supplied that results in a non-zero number
or a non-empty string, then the Visual mode will be cleared
diff -Naur vim71.orig/src/auto/configure vim71/src/auto/configure
--- vim71.orig/src/auto/configure 2008-04-10 21:44:22.135444043 +0300
+++ vim71/src/auto/configure 2008-04-10 21:40:51.366978946 +0300
@@ -10311,9 +10311,10 @@
+
for ac_header in stdarg.h stdlib.h string.h sys/select.h sys/utsname.h \
termcap.h fcntl.h sgtty.h sys/ioctl.h sys/time.h sys/types.h termio.h \
- iconv.h langinfo.h unistd.h stropts.h errno.h \
+ iconv.h langinfo.h math.h unistd.h stropts.h errno.h \
sys/resource.h sys/systeminfo.h locale.h \
sys/stream.h sys/ptem.h termios.h libc.h sys/statfs.h \
poll.h sys/poll.h pwd.h utime.h sys/param.h libintl.h \
@@ -13083,6 +13084,138 @@
rm -f conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
+
+echo "$as_me:$LINENO: checking for pow in -lm" >&5
+echo $ECHO_N "checking for pow in -lm... $ECHO_C" >&6
+if test "${ac_cv_lib_m_pow+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lm $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char pow ();
+int
+main ()
+{
+pow ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_m_pow=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_m_pow=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_m_pow" >&5
+echo "${ECHO_T}$ac_cv_lib_m_pow" >&6
+if test $ac_cv_lib_m_pow = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBM 1
+_ACEOF
+
+ LIBS="-lm $LIBS"
+
+fi
+
+echo "$as_me:$LINENO: checking for pow()" >&5
+echo $ECHO_N "checking for pow()... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#ifdef HAVE_MATH_H
+# include <math.h>
+#endif
+
+int
+main ()
+{
+double f = pow(1.1, 3.0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; cat >>confdefs.h <<\_ACEOF
+#define HAVE_POW 1
+_ACEOF
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+
echo "$as_me:$LINENO: checking --disable-acl argument" >&5
echo $ECHO_N "checking --disable-acl argument... $ECHO_C" >&6
# Check whether --enable-acl or --disable-acl was given.
diff -Naur vim71.orig/src/config.h.in vim71/src/config.h.in
--- vim71.orig/src/config.h.in 2007-04-26 17:40:34.000000000 +0300
+++ vim71/src/config.h.in 2008-04-10 21:40:51.367978692 +0300
@@ -150,6 +150,7 @@
#undef HAVE_MEMSET
#undef HAVE_NANOSLEEP
#undef HAVE_OPENDIR
+#undef HAVE_POW
#undef HAVE_PUTENV
#undef HAVE_QSORT
#undef HAVE_READLINK
@@ -199,6 +200,7 @@
#undef HAVE_LIBGEN_H
#undef HAVE_LIBINTL_H
#undef HAVE_LOCALE_H
+#undef HAVE_MATH_H
#undef HAVE_NDIR_H
#undef HAVE_POLL_H
#undef HAVE_PTHREAD_NP_H
diff -Naur vim71.orig/src/configure.in vim71/src/configure.in
--- vim71.orig/src/configure.in 2008-04-10 21:44:22.151439060 +0300
+++ vim71/src/configure.in 2008-04-10 21:40:51.368978290 +0300
@@ -2034,7 +2034,7 @@
AC_CHECK_HEADERS(stdarg.h stdlib.h string.h sys/select.h sys/utsname.h \
termcap.h fcntl.h sgtty.h sys/ioctl.h sys/time.h sys/types.h termio.h \
- iconv.h langinfo.h unistd.h stropts.h errno.h \
+ iconv.h langinfo.h math.h unistd.h stropts.h errno.h \
sys/resource.h sys/systeminfo.h locale.h \
sys/stream.h sys/ptem.h termios.h libc.h sys/statfs.h \
poll.h sys/poll.h pwd.h utime.h sys/param.h libintl.h \
@@ -2490,6 +2490,17 @@
AC_MSG_RESULT(yes); AC_DEFINE(HAVE_NL_LANGINFO_CODESET),
AC_MSG_RESULT(no))
+dnl Need pow() for floating point support.
+AC_CHECK_LIB(m, pow)
+AC_MSG_CHECKING(for pow())
+AC_TRY_LINK([
+#ifdef HAVE_MATH_H
+# include <math.h>
+#endif
+], [double f = pow(1.1, 3.0);],
+ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_POW),
+ AC_MSG_RESULT(no))
+
dnl Link with -lposix1e for ACL stuff; if not found, try -lacl for SGI
dnl when -lacl works, also try to use -lattr (required for Debian).
AC_MSG_CHECKING(--disable-acl argument)
diff -Naur vim71.orig/src/eval.c vim71/src/eval.c
--- vim71.orig/src/eval.c 2008-04-10 21:44:22.174431146 +0300
+++ vim71/src/eval.c 2008-04-10 21:40:51.381974296 +0300
@@ -30,6 +30,10 @@
#if defined(FEAT_EVAL) || defined(PROTO)
+#if defined(FEAT_FLOAT) && defined(HAVE_MATH_H)
+# include <math.h>
+#endif
+
#define DICT_MAXNEST 100 /* maximum nesting of lists and dicts */
/*
@@ -349,10 +353,11 @@
};
/* shorthand */
-#define vv_type vv_di.di_tv.v_type
-#define vv_nr vv_di.di_tv.vval.v_number
-#define vv_str vv_di.di_tv.vval.v_string
-#define vv_tv vv_di.di_tv
+#define vv_type vv_di.di_tv.v_type
+#define vv_nr vv_di.di_tv.vval.v_number
+#define vv_float vv_di.di_tv.vval.v_float
+#define vv_str vv_di.di_tv.vval.v_string
+#define vv_tv vv_di.di_tv
/*
* The v: variables are stored in dictionary "vimvardict".
@@ -450,6 +455,10 @@
static char_u *echo_string __ARGS((typval_T *tv, char_u **tofree, char_u
*numbuf, int copyID));
static char_u *tv2string __ARGS((typval_T *tv, char_u **tofree, char_u
*numbuf, int copyID));
static char_u *string_quote __ARGS((char_u *str, int function));
+#ifdef FEAT_FLOAT
+static void get_float_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
+static int string2float __ARGS((char_u *text, float_T *value, int comma));
+#endif
static int get_env_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
static int find_internal_func __ARGS((char_u *name));
static char_u *deref_func_name __ARGS((char_u *name, int *lenp));
@@ -637,6 +646,9 @@
static void f_spellbadword __ARGS((typval_T *argvars, typval_T *rettv));
static void f_spellsuggest __ARGS((typval_T *argvars, typval_T *rettv));
static void f_split __ARGS((typval_T *argvars, typval_T *rettv));
+#ifdef FEAT_FLOAT
+static void f_str2float __ARGS((typval_T *argvars, typval_T *rettv));
+#endif
static void f_str2nr __ARGS((typval_T *argvars, typval_T *rettv));
#ifdef HAVE_STRFTIME
static void f_strftime __ARGS((typval_T *argvars, typval_T *rettv));
@@ -1421,7 +1433,8 @@
|| defined(FEAT_COMPL_FUNC) || defined(PROTO)
/*
* Call some vimL function and return the result in "*rettv".
- * Uses argv[argc] for the function arguments.
+ * Uses argv[argc] for the function arguments. Only Number and String
+ * arguments are currently supported.
* Returns OK or FAIL.
*/
static int
@@ -2848,16 +2861,36 @@
{
/* nr += nr or nr -= nr*/
n = get_tv_number(tv1);
- if (*op == '+')
- n += get_tv_number(tv2);
+#ifdef FEAT_FLOAT
+ if (tv2->v_type == VAR_FLOAT)
+ {
+ float_T f = n;
+
+ if (*op == '+')
+ f += tv2->vval.v_float;
+ else
+ f -= tv2->vval.v_float;
+ clear_tv(tv1);
+ tv1->v_type = VAR_FLOAT;
+ tv1->vval.v_float = f;
+ }
else
- n -= get_tv_number(tv2);
- clear_tv(tv1);
- tv1->v_type = VAR_NUMBER;
- tv1->vval.v_number = n;
+#endif
+ {
+ if (*op == '+')
+ n += get_tv_number(tv2);
+ else
+ n -= get_tv_number(tv2);
+ clear_tv(tv1);
+ tv1->v_type = VAR_NUMBER;
+ tv1->vval.v_number = n;
+ }
}
else
{
+ if (tv2->v_type == VAR_FLOAT)
+ break;
+
/* str .= str */
s = get_tv_string(tv1);
s = concat_str(s, get_tv_string_buf(tv2, numbuf));
@@ -2866,6 +2899,27 @@
tv1->vval.v_string = s;
}
return OK;
+
+#ifdef FEAT_FLOAT
+ case VAR_FLOAT:
+ {
+ float_T f;
+
+ if (*op == '.' || (tv2->v_type != VAR_FLOAT
+ && tv2->v_type != VAR_NUMBER
+ && tv2->v_type != VAR_STRING))
+ break;
+ if (tv2->v_type == VAR_FLOAT)
+ f = tv2->vval.v_float;
+ else
+ f = get_tv_number(tv2);
+ if (*op == '+')
+ tv1->vval.v_float += f;
+ else
+ tv1->vval.v_float -= f;
+ }
+ return OK;
+#endif
}
}
@@ -4237,6 +4291,40 @@
}
}
+#ifdef FEAT_FLOAT
+ /*
+ * If one of the two variables is a float, compare as a float.
+ * When using "=~" or "!~", always compare as string.
+ */
+ else if ((rettv->v_type == VAR_FLOAT || var2.v_type == VAR_FLOAT)
+ && type != TYPE_MATCH && type != TYPE_NOMATCH)
+ {
+ float_T f1, f2;
+
+ if (rettv->v_type == VAR_FLOAT)
+ f1 = rettv->vval.v_float;
+ else
+ f1 = get_tv_number(rettv);
+ if (var2.v_type == VAR_FLOAT)
+ f2 = var2.vval.v_float;
+ else
+ f2 = get_tv_number(&var2);
+ n1 = FALSE;
+ switch (type)
+ {
+ case TYPE_EQUAL: n1 = (f1 == f2); break;
+ case TYPE_NEQUAL: n1 = (f1 != f2); break;
+ case TYPE_GREATER: n1 = (f1 > f2); break;
+ case TYPE_GEQUAL: n1 = (f1 >= f2); break;
+ case TYPE_SMALLER: n1 = (f1 < f2); break;
+ case TYPE_SEQUAL: n1 = (f1 <= f2); break;
+ case TYPE_UNKNOWN:
+ case TYPE_MATCH:
+ case TYPE_NOMATCH: break; /* avoid gcc warning */
+ }
+ }
+#endif
+
/*
* If one of the two variables is a number, compare as a number.
* When using "=~" or "!~", always compare as string.
@@ -4329,6 +4417,9 @@
typval_T var3;
int op;
long n1, n2;
+#ifdef FEAT_FLOAT
+ float_T f1 = 0, f2 = 0;
+#endif
char_u *s1, *s2;
char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
char_u *p;
@@ -4348,7 +4439,11 @@
if (op != '+' && op != '-' && op != '.')
break;
- if (op != '+' || rettv->v_type != VAR_LIST)
+ if ((op != '+' || rettv->v_type != VAR_LIST)
+#ifdef FEAT_FLOAT
+ && (op == '.' || rettv->v_type != VAR_FLOAT)
+#endif
+ )
{
/* For "list + ...", an illegal use of the first operand as
* a number cannot be determined before evaluating the 2nd
@@ -4412,29 +4507,73 @@
{
int error = FALSE;
- n1 = get_tv_number_chk(rettv, &error);
- if (error)
+#ifdef FEAT_FLOAT
+ if (rettv->v_type == VAR_FLOAT)
{
- /* This can only happen for "list + non-list".
- * For "non-list + ..." or "something - ...", we returned
- * before evaluating the 2nd operand. */
- clear_tv(rettv);
- return FAIL;
+ f1 = rettv->vval.v_float;
+ n1 = 0;
}
- n2 = get_tv_number_chk(&var2, &error);
- if (error)
+ else
+#endif
{
- clear_tv(rettv);
- clear_tv(&var2);
- return FAIL;
+ n1 = get_tv_number_chk(rettv, &error);
+ if (error)
+ {
+ /* This can only happen for "list + non-list". For
+ * "non-list + ..." or "something - ...", we returned
+ * before evaluating the 2nd operand. */
+ clear_tv(rettv);
+ return FAIL;
+ }
+#ifdef FEAT_FLOAT
+ if (var2.v_type == VAR_FLOAT)
+ f1 = n1;
+#endif
+ }
+#ifdef FEAT_FLOAT
+ if (var2.v_type == VAR_FLOAT)
+ {
+ f2 = var2.vval.v_float;
+ n2 = 0;
+ }
+ else
+#endif
+ {
+ n2 = get_tv_number_chk(&var2, &error);
+ if (error)
+ {
+ clear_tv(rettv);
+ clear_tv(&var2);
+ return FAIL;
+ }
+#ifdef FEAT_FLOAT
+ if (rettv->v_type == VAR_FLOAT)
+ f2 = n2;
+#endif
}
clear_tv(rettv);
- if (op == '+')
- n1 = n1 + n2;
+
+#ifdef FEAT_FLOAT
+ /* If there is a float on either side the result is a float. */
+ if (rettv->v_type == VAR_FLOAT || var2.v_type == VAR_FLOAT)
+ {
+ if (op == '+')
+ f1 = f1 + f2;
+ else
+ f1 = f1 - f2;
+ rettv->v_type = VAR_FLOAT;
+ rettv->vval.v_float = f1;
+ }
else
- n1 = n1 - n2;
- rettv->v_type = VAR_NUMBER;
- rettv->vval.v_number = n1;
+#endif
+ {
+ if (op == '+')
+ n1 = n1 + n2;
+ else
+ n1 = n1 - n2;
+ rettv->v_type = VAR_NUMBER;
+ rettv->vval.v_number = n1;
+ }
}
clear_tv(&var2);
}
@@ -4462,6 +4601,10 @@
typval_T var2;
int op;
long n1, n2;
+#ifdef FEAT_FLOAT
+ int use_float = FALSE;
+ float_T f1 = 0, f2;
+#endif
int error = FALSE;
/*
@@ -4481,7 +4624,16 @@
if (evaluate)
{
- n1 = get_tv_number_chk(rettv, &error);
+#ifdef FEAT_FLOAT
+ if (rettv->v_type == VAR_FLOAT)
+ {
+ f1 = rettv->vval.v_float;
+ use_float = TRUE;
+ n1 = 0;
+ }
+ else
+#endif
+ n1 = get_tv_number_chk(rettv, &error);
clear_tv(rettv);
if (error)
return FAIL;
@@ -4498,32 +4650,80 @@
if (evaluate)
{
- n2 = get_tv_number_chk(&var2, &error);
- clear_tv(&var2);
- if (error)
- return FAIL;
+#ifdef FEAT_FLOAT
+ if (var2.v_type == VAR_FLOAT)
+ {
+ if (!use_float)
+ {
+ f1 = n1;
+ use_float = TRUE;
+ }
+ f2 = var2.vval.v_float;
+ n2 = 0;
+ }
+ else
+#endif
+ {
+ n2 = get_tv_number_chk(&var2, &error);
+ clear_tv(&var2);
+ if (error)
+ return FAIL;
+#ifdef FEAT_FLOAT
+ if (use_float)
+ f2 = n2;
+#endif
+ }
/*
* Compute the result.
+ * When either side is a float the result is a float.
*/
- if (op == '*')
- n1 = n1 * n2;
- else if (op == '/')
+#ifdef FEAT_FLOAT
+ if (use_float)
{
- if (n2 == 0) /* give an error message? */
- n1 = 0x7fffffffL;
+ if (op == '*')
+ f1 = f1 * f2;
+ else if (op == '/')
+ {
+ if (f2 == 0.0) /* give an error message? */
+# ifdef INFINITY
+ f1 = INFINITY;
+# else
+ f1 = 0x7fffffffL;
+# endif
+ else
+ f1 = f1 / f2;
+ }
else
- n1 = n1 / n2;
+ {
+ EMSG(_("E804: Cannot use % with float"));
+ return FAIL;
+ }
+ rettv->v_type = VAR_FLOAT;
+ rettv->vval.v_float = f1;
}
else
+#endif
{
- if (n2 == 0) /* give an error message? */
- n1 = 0;
+ if (op == '*')
+ n1 = n1 * n2;
+ else if (op == '/')
+ {
+ if (n2 == 0) /* give an error message? */
+ n1 = 0x7fffffffL;
+ else
+ n1 = n1 / n2;
+ }
else
- n1 = n1 % n2;
+ {
+ if (n2 == 0) /* give an error message? */
+ n1 = 0;
+ else
+ n1 = n1 % n2;
+ }
+ rettv->v_type = VAR_NUMBER;
+ rettv->vval.v_number = n1;
}
- rettv->v_type = VAR_NUMBER;
- rettv->vval.v_number = n1;
}
}
@@ -4565,7 +4765,6 @@
long n;
int len;
char_u *s;
- int val;
char_u *start_leader, *end_leader;
int ret = OK;
char_u *alias;
@@ -4635,7 +4834,13 @@
/*
* Option value: &name
*/
- case '&': ret = get_option_tv(arg, rettv, evaluate);
+ case '&':
+#ifdef FEAT_FLOAT
+ if (vim_isdigit(*(*arg + 1)))
+ get_float_tv(arg, rettv, evaluate);
+ else
+#endif
+ ret = get_option_tv(arg, rettv, evaluate);
break;
/*
@@ -4734,8 +4939,15 @@
if (ret == OK && evaluate && end_leader > start_leader)
{
int error = FALSE;
+ int val = 0;
+#ifdef FEAT_FLOAT
+ float_T f = 0;
- val = get_tv_number_chk(rettv, &error);
+ if (rettv->v_type == VAR_FLOAT)
+ f = rettv->vval.v_float;
+ else
+#endif
+ val = get_tv_number_chk(rettv, &error);
if (error)
{
clear_tv(rettv);
@@ -4747,13 +4959,37 @@
{
--end_leader;
if (*end_leader == '!')
- val = !val;
+ {
+#ifdef FEAT_FLOAT
+ if (rettv->v_type == VAR_FLOAT)
+ f = !f;
+ else
+#endif
+ val = !val;
+ }
else if (*end_leader == '-')
- val = -val;
+ {
+#ifdef FEAT_FLOAT
+ if (rettv->v_type == VAR_FLOAT)
+ f = -f;
+ else
+#endif
+ val = -val;
+ }
+ }
+#ifdef FEAT_FLOAT
+ if (rettv->v_type == VAR_FLOAT)
+ {
+ clear_tv(rettv);
+ rettv->vval.v_float = f;
+ }
+ else
+#endif
+ {
+ clear_tv(rettv);
+ rettv->v_type = VAR_NUMBER;
+ rettv->vval.v_number = val;
}
- clear_tv(rettv);
- rettv->v_type = VAR_NUMBER;
- rettv->vval.v_number = val;
}
}
@@ -4780,7 +5016,11 @@
char_u *s;
char_u *key = NULL;
- if (rettv->v_type == VAR_FUNC)
+ if (rettv->v_type == VAR_FUNC
+#ifdef FEAT_FLOAT
+ || rettv->v_type == VAR_FLOAT
+#endif
+ )
{
if (verbose)
EMSG(_("E695: Cannot index a Funcref"));
@@ -5566,7 +5806,7 @@
/*
* Return TRUE if "tv1" and "tv2" have the same value.
* Compares the items just like "==" would compare them, but strings and
- * numbers are different.
+ * numbers are different. Floats and numbers are also different.
*/
static int
tv_equal(tv1, tv2, ic)
@@ -5608,6 +5848,11 @@
case VAR_NUMBER:
return tv1->vval.v_number == tv2->vval.v_number;
+#ifdef FEAT_FLOAT
+ case VAR_FLOAT:
+ return tv1->vval.v_float == tv2->vval.v_float;
+#endif
+
case VAR_STRING:
s1 = get_tv_string_buf(tv1, buf1);
s2 = get_tv_string_buf(tv2, buf2);
@@ -6897,6 +7142,14 @@
r = get_tv_string_buf(tv, numbuf);
break;
+#ifdef FEAT_FLOAT
+ case VAR_FLOAT:
+ *tofree = NULL;
+ vim_snprintf(numbuf, NUMBUFLEN, "%f", tv->vval.v_float);
+ r = numbuf;
+ break;
+#endif
+
default:
EMSG2(_(e_intern2), "echo_string()");
*tofree = NULL;
@@ -6929,6 +7182,9 @@
*tofree = string_quote(tv->vval.v_string, FALSE);
return *tofree;
case VAR_NUMBER:
+#ifdef FEAT_FLOAT
+ case VAR_FLOAT:
+#endif
case VAR_LIST:
case VAR_DICT:
break;
@@ -6984,6 +7240,71 @@
return s;
}
+#ifdef FEAT_FLOAT
+/*
+ * Get the value of a floating point number: &123.456
+ * "arg" is pointing to the '&'. It is advanced to after the number.
+ */
+ static void
+get_float_tv(arg, rettv, evaluate)
+ char_u **arg;
+ typval_T *rettv;
+ int evaluate;
+{
+ float_T f;
+
+ ++*arg;
+ *arg += string2float(*arg, &f, FALSE);
+ if (evaluate)
+ {
+ rettv->v_type = VAR_FLOAT;
+ rettv->vval.v_float = f;
+ }
+}
+
+/*
+ * Convert the sting "text" to a floating point number.
+ * Returns the length of the text that was consumed.
+ */
+ static int
+string2float(text, value, comma)
+ char_u *text;
+ float_T *value; /* result stored here */
+ int comma; /* accept a comma as decimal separator */
+{
+ char_u *s = text;
+ int len;
+ long n;
+ float_T f;
+
+ vim_str2nr(s, NULL, &len, FALSE, FALSE, &n, NULL);
+ s += len;
+ f = n;
+
+ if ((*s == '.' || (comma && *s == ',')) && s[1] != '-')
+ {
+ ++s;
+ vim_str2nr(s, NULL, &len, FALSE, FALSE, &n, NULL);
+ s += len;
+ f += (float_T)n / pow(10.0, (double)len);
+ }
+
+ /* 1.234e-20 */
+ if (*s == 'e' || *s == 'E')
+ {
+ ++s;
+ if (*s == '+') /* accept 1.234e+3 */
+ ++s;
+ vim_str2nr(s, NULL, &len, FALSE, FALSE, &n, NULL);
+ s += len;
+ f *= pow(10.0, (double)n);
+ }
+
+ *value = f;
+ return (int)(s - text);
+}
+#endif
+
/*
* Get the value of an environment variable.
* "arg" is pointing to the '$'. It is advanced to after the name.
@@ -7240,6 +7561,9 @@
{"spellbadword", 0, 1, f_spellbadword},
{"spellsuggest", 1, 3, f_spellsuggest},
{"split", 1, 3, f_split},
+#ifdef FEAT_FLOAT
+ {"str2float", 1, 1, f_str2float},
+#endif
{"str2nr", 1, 2, f_str2nr},
#ifdef HAVE_STRFTIME
{"strftime", 1, 2, f_strftime},
@@ -8800,6 +9124,11 @@
case VAR_NUMBER:
n = argvars[0].vval.v_number == 0;
break;
+#ifdef FEAT_FLOAT
+ case VAR_FLOAT:
+ n = argvars[0].vval.v_float == 0.0;
+ break;
+#endif
case VAR_LIST:
n = argvars[0].vval.v_list == NULL
|| argvars[0].vval.v_list->lv_first == NULL;
@@ -10877,6 +11206,9 @@
#ifdef FEAT_FIND_ID
"find_in_path",
#endif
+#ifdef FEAT_FLOAT
+ "float",
+#endif
#ifdef FEAT_FOLDING
"folding",
#endif
@@ -15432,6 +15764,21 @@
p_cpo = save_cpo;
}
+#ifdef FEAT_FLOAT
+/*
+ * "str2float()" function
+ */
+ static void
+f_str2float(argvars, rettv)
+ typval_T *argvars;
+ typval_T *rettv;
+{
+ (void)string2float(skipwhite(get_tv_string(&argvars[0])),
+ &rettv->vval.v_float, TRUE);
+ rettv->v_type = VAR_FLOAT;
+}
+#endif
+
/*
* "str2nr()" function
*/
@@ -16476,6 +16823,9 @@
case VAR_FUNC: n = 2; break;
case VAR_LIST: n = 3; break;
case VAR_DICT: n = 4; break;
+#ifdef FEAT_FLOAT
+ case VAR_FLOAT: n = 5; break;
+#endif
default: EMSG2(_(e_intern2), "f_type()"); n = 0; break;
}
rettv->vval.v_number = n;
@@ -17662,6 +18012,9 @@
dict_unref(varp->vval.v_dict);
break;
case VAR_NUMBER:
+#ifdef FEAT_FLOAT
+ case VAR_FLOAT:
+#endif
case VAR_UNKNOWN:
break;
default:
@@ -17701,6 +18054,11 @@
case VAR_NUMBER:
varp->vval.v_number = 0;
break;
+#ifdef FEAT_FLOAT
+ case VAR_FLOAT:
+ varp->vval.v_float = 0;
+ break;
+#endif
case VAR_UNKNOWN:
break;
default:
@@ -17749,6 +18107,11 @@
{
case VAR_NUMBER:
return (long)(varp->vval.v_number);
+#ifdef FEAT_FLOAT
+ case VAR_FLOAT:
+ EMSG(_("E805: Using a Float as a number"));
+ break;
+#endif
case VAR_FUNC:
EMSG(_("E703: Using a Funcref as a number"));
break;
@@ -17872,6 +18235,11 @@
case VAR_DICT:
EMSG(_("E731: using Dictionary as a String"));
break;
+#ifdef FEAT_FLOAT
+ case VAR_FLOAT:
+ EMSG(_("E806: using Float as a String"));
+ break;
+#endif
case VAR_STRING:
if (varp->vval.v_string != NULL)
return varp->vval.v_string;
@@ -18410,6 +18778,11 @@
case VAR_NUMBER:
to->vval.v_number = from->vval.v_number;
break;
+#ifdef FEAT_FLOAT
+ case VAR_FLOAT:
+ to->vval.v_float = from->vval.v_float;
+ break;
+#endif
case VAR_STRING:
case VAR_FUNC:
if (from->vval.v_string == NULL)
@@ -18472,6 +18845,9 @@
switch (from->v_type)
{
case VAR_NUMBER:
+#ifdef FEAT_FLOAT
+ case VAR_FLOAT:
+#endif
case VAR_STRING:
case VAR_FUNC:
copy_tv(from, to);
@@ -20846,9 +21222,9 @@
#if defined(FEAT_VIMINFO) || defined(FEAT_SESSION)
typedef enum
{
- VAR_FLAVOUR_DEFAULT,
- VAR_FLAVOUR_SESSION,
- VAR_FLAVOUR_VIMINFO
+ VAR_FLAVOUR_DEFAULT, /* doesn't start with uppercase */
+ VAR_FLAVOUR_SESSION, /* starts with uppercase, some lower */
+ VAR_FLAVOUR_VIMINFO /* all uppercase */
} var_flavour_T;
static var_flavour_T var_flavour __ARGS((char_u *varname));
@@ -20881,7 +21257,7 @@
int writing;
{
char_u *tab;
- int is_string = FALSE;
+ int type = VAR_NUMBER;
typval_T tv;
if (!writing && (find_viminfo_parameter('!') != NULL))
@@ -20891,24 +21267,27 @@
{
*tab++ = '\0'; /* isolate the variable name */
if (*tab == 'S') /* string var */
- is_string = TRUE;
+ type = VAR_STRING;
+#ifdef FEAT_FLOAT
+ else if (*tab == 'F')
+ type = VAR_FLOAT;
+#endif
tab = vim_strchr(tab, '\t');
if (tab != NULL)
{
- if (is_string)
- {
- tv.v_type = VAR_STRING;
+ tv.v_type = type;
+ if (type == VAR_STRING)
tv.vval.v_string = viminfo_readstring(virp,
(int)(tab - virp->vir_line + 1), TRUE);
- }
+#ifdef FEAT_FLOAT
+ else if (type == VAR_FLOAT)
+ (void)string2float(tab + 1, &tv.vval.v_float, TRUE);
+#endif
else
- {
- tv.v_type = VAR_NUMBER;
tv.vval.v_number = atol((char *)tab + 1);
- }
set_var(virp->vir_line + 1, &tv, FALSE);
- if (is_string)
+ if (type == VAR_STRING)
vim_free(tv.vval.v_string);
}
}
@@ -20950,6 +21329,9 @@
{
case VAR_STRING: s = "STR"; break;
case VAR_NUMBER: s = "NUM"; break;
+#ifdef FEAT_FLOAT
+ case VAR_FLOAT: s = "FLO"; break;
+#endif
default: continue;
}
fprintf(fp, "!%s\t%s\t", this_var->di_key, s);
@@ -21009,6 +21391,24 @@
}
vim_free(p);
}
+#ifdef FEAT_FLOAT
+ else if (this_var->di_tv.v_type == VAR_FLOAT
+ && var_flavour(this_var->di_key) == VAR_FLAVOUR_SESSION)
+ {
+ float_T f = this_var->di_tv.vval.v_float;
+ int sign = ' ';
+
+ if (f < 0)
+ {
+ f = -f;
+ sign = '-';
+ }
+ if ((fprintf(fd, "let %s = %c&%f",
+ this_var->di_key, sign, f) < 0)
+ || put_eol(fd) == FAIL)
+ return FAIL;
+ }
+#endif
}
}
return OK;
@@ -21080,7 +21480,7 @@
vim_free(*bufp);
*fnamep = *bufp = newbuf;
- l = GetShortPathName(*fnamep,*fnamep,l+1);
+ l = GetShortPathName(*fnamep, *fnamep, l+1);
/* Really should always succeed, as the buffer is big enough */
}
diff -Naur vim71.orig/src/feature.h vim71/src/feature.h
--- vim71.orig/src/feature.h 2008-04-10 21:44:22.195424329 +0300
+++ vim71/src/feature.h 2008-04-10 21:40:51.381974296 +0300
@@ -35,7 +35,7 @@
* +small few features enabled, as basic as possible
* +normal A default selection of features enabled
* +big many features enabled, as rich as possible.
- * +huge all possible featues enabled.
+ * +huge all possible features enabled.
*
* When +small is used, +tiny is also included. +normal implies +small, etc.
*/
@@ -376,9 +376,13 @@
/*
* +eval Built-in script language and expression evaluation,
* ":let", ":if", etc.
+ * +float Floating point variables.
*/
#ifdef FEAT_NORMAL
# define FEAT_EVAL
+# if defined(HAVE_POW)
+# define FEAT_FLOAT
+# endif
#endif
/*
diff -Naur vim71.orig/src/if_python.c vim71/src/if_python.c
--- vim71.orig/src/if_python.c 2007-03-07 00:00:53.000000000 +0200
+++ vim71/src/if_python.c 2008-04-10 21:40:51.382974351 +0300
@@ -1130,6 +1130,17 @@
result = Py_BuildValue("s", buf);
PyDict_SetItemString(lookupDict, ptrBuf, result);
}
+#ifdef FEAT_FLOAT
+ else if (our_tv->v_type == VAR_FLOAT)
+ {
+ char buf[NUMBUFLEN];
+
+ /* For backwards compatibility numbers are stored as strings. */
+ sprintf(buf, "%f", (long)our_tv->vval.v_float);
+ result = Py_BuildValue("s", buf);
+ PyDict_SetItemString(lookupDict, ptrBuf, result);
+ }
+#endif
else if (our_tv->v_type == VAR_LIST)
{
list_T *list = our_tv->vval.v_list;
diff -Naur vim71.orig/src/message.c vim71/src/message.c
--- vim71.orig/src/message.c 2008-04-10 21:44:22.230412683 +0300
+++ vim71/src/message.c 2008-04-10 21:40:45.664888239 +0300
@@ -15,6 +15,10 @@
#include "vim.h"
+#if defined(FEAT_FLOAT) && defined(HAVE_MATH_H)
+# include <math.h>
+#endif
+
static int other_sourcing_name __ARGS((void));
static char_u *get_emsg_source __ARGS((void));
static char_u *get_emsg_lnum __ARGS((void));
@@ -3819,6 +3823,9 @@
static long tv_nr __ARGS((typval_T *tvs, int *idxp));
static char *tv_str __ARGS((typval_T *tvs, int *idxp));
+# ifdef FEAT_FLOAT
+static double tv_float __ARGS((typval_T *tvs, int *idxp));
+# endif
/*
* Get number argument from "idxp" entry in "tvs". First entry is 1.
@@ -3865,6 +3872,32 @@
}
return s;
}
+
+# ifdef FEAT_FLOAT
+/*
+ * Get float argument from "idxp" entry in "tvs". First entry is 1.
+ */
+ static double
+tv_float(tvs, idxp)
+ typval_T *tvs;
+ int *idxp;
+{
+ int idx = *idxp - 1;
+ double f = 0;
+
+ if (tvs[idx].v_type == VAR_UNKNOWN)
+ EMSG(_(e_printf));
+ else
+ {
+ ++*idxp;
+ if (tvs[idx].v_type == VAR_FLOAT)
+ f = tvs[idx].vval.v_float;
+ else
+ EMSG(_("E807: Expected Float argument for printf()"));
+ }
+ return f;
+}
+# endif
#endif
/*
@@ -3883,6 +3916,8 @@
* with flags: '-', '+', ' ', '0' and '#'.
* An asterisk is supported for field width as well as precision.
*
+ * Limited support for 'f', 'e' and 'E' (floating point) was added.
+ *
* Length modifiers 'h' (short int) and 'l' (long int) are supported.
* 'll' (long long int) is not supported.
*
@@ -3983,7 +4018,14 @@
char length_modifier = '\0';
/* temporary buffer for simple numeric->string conversion */
- char tmp[32];
+#ifdef FEAT_FLOAT
+# define TMP_LEN 350 /* On my system 1e308 is the biggest number possible.
+ * That sounds reasonable to use as the maximum
+ * printable. */
+#else
+# define TMP_LEN 32
+#endif
+ char tmp[TMP_LEN];
/* string address in case of string argument */
char *str_arg;
@@ -4124,6 +4166,7 @@
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;
}
@@ -4459,6 +4502,53 @@
break;
}
+#ifdef FEAT_FLOAT
+ case 'f':
+ case 'e':
+ case 'E':
+ {
+ /* Floating point. Very limited at the moment. */
+ double f;
+ char format[40];
+ int l;
+
+ f =
+# ifndef HAVE_STDARG_H
+ get_a_arg(arg_idx);
+# else
+# if defined(FEAT_EVAL)
+ tvs != NULL ? tv_float(tvs, &arg_idx) :
+# endif
+ va_arg(ap, double);
+# endif
+ if (fmt_spec == 'f' && f > 1.0e307)
+ {
+ /* Avoid a buffer overflow */
+ strcpy(tmp, "inf");
+ str_arg_l = 3;
+ }
+ else
+ {
+ format[0] = '%';
+ l = 1;
+ if (precision_specified)
+ {
+ if (fmt_spec == 'f'
+ && log10(f) + precision > TMP_LEN - 10)
+ precision = TMP_LEN - 10 - log10(f);
+ else if (precision > TMP_LEN - 10)
+ precision = TMP_LEN - 10;
+ l += sprintf(format + 1, ".%d", precision);
+ }
+ format[l] = fmt_spec;
+ format[l + 1] = NUL;
+ str_arg_l = sprintf(tmp, format, f);
+ }
+ str_arg = tmp;
+ break;
+ }
+#endif
+
default:
/* unrecognized conversion specifier, keep format string
* as-is */
@@ -4566,7 +4656,8 @@
if (justify_left)
{
/* right blank padding to the field width */
- int pn = (int)(min_field_width - (str_arg_l +
number_of_zeros_to_pad));
+ int pn = (int)(min_field_width
+ - (str_arg_l + number_of_zeros_to_pad));
if (pn > 0)
{
diff -Naur vim71.orig/src/structs.h vim71/src/structs.h
--- vim71.orig/src/structs.h 2008-04-10 21:44:22.288393601 +0300
+++ vim71/src/structs.h 2008-04-10 21:40:51.384973103 +0300
@@ -1005,6 +1005,7 @@
#else
typedef int varnumber_T;
#endif
+typedef double float_T;
typedef struct listvar_S list_T;
typedef struct dictvar_S dict_T;
@@ -1019,6 +1020,9 @@
union
{
varnumber_T v_number; /* number value */
+#ifdef FEAT_FLOAT
+ float_T v_float; /* floating number value */
+#endif
char_u *v_string; /* string value (can be NULL!) */
list_T *v_list; /* list value (can be NULL!) */
dict_T *v_dict; /* dict value (can be NULL!) */
@@ -1032,6 +1036,7 @@
#define VAR_FUNC 3 /* "v_string" is function name */
#define VAR_LIST 4 /* "v_list" is used */
#define VAR_DICT 5 /* "v_dict" is used */
+#define VAR_FLOAT 6 /* "v_float" is used */
/* Values for "v_lock". */
#define VAR_LOCKED 1 /* locked with lock(), can use unlock() */
diff -Naur vim71.orig/src/version.c vim71/src/version.c
--- vim71.orig/src/version.c 2008-04-10 21:44:22.301389216 +0300
+++ vim71/src/version.c 2008-04-10 21:40:51.385973840 +0300
@@ -217,6 +217,11 @@
#else
"-find_in_path",
#endif
+#ifdef FEAT_FLOAT
+ "+float",
+#else
+ "-float",
+#endif
#ifdef FEAT_FOLDING
"+folding",
#else