I have been preparing a talk for the upcoming FISL conference in Brazil:
http://fisl.softwarelivre.org/9.0/www/
One of the items I planned to discuss is why Vim has no floating point
support. Well, this turned into actually implementing it.
The main problem with floating point is that the usual notation already
has a meaning:
echo 123.456
123456
That is because "." is the concatenation operator, and numbers are
automatically converted to strings.
I considered a few alternatives:
123,456 used for function arguments
float("123,456") too verbose
#123.456 has a meaning after == and !=
$123.456 confusion with $ENV
The best I could think of was &123.456. It's a bit obscure, you need to
get used to it. But it works.
echo &123.456e-3
0.123456
Feel free to suggest something better, but make sure it doesn't already
mean something in any context in Vim script.
Have fun with the patch!
*** ../vim-7.1.291/runtime/doc/eval.txt Wed Feb 20 20:09:44 2008
--- runtime/doc/eval.txt Tue Apr 8 22:19:37 2008
***************
*** 39,49 ****
*E712*
There are five types of variables:
! Number A 32 bit signed number.
Examples: -123 0x10 0177
String A NUL terminated string of 8-bit unsigned characters
(bytes).
! Examples: "ab\txx\"--" 'x-z''a,c'
Funcref A reference to a function |Funcref|.
Example: function("strlen")
--- 39,53 ----
*E712*
There are five types of variables:
! 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).
! |expr-string| Examples: "ab\txx\"--" 'x-z''a,c'
Funcref A reference to a function |Funcref|.
Example: function("strlen")
***************
*** 92,97 ****
--- 96,105 ----
< *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,270 ****
< 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: >
:let a = 5
:let b = "5"
! echo a == b
< 1 >
! echo [a] == [b]
< 0
--- 266,278 ----
< 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 list: >
:let a = 5
:let b = "5"
! :echo a == b
< 1 >
! :echo [a] == [b]
< 0
***************
*** 797,802 ****
--- 805,812 ----
None of these work for |Funcref|s.
+ . and % do not work for Float. *E804*
+
expr7 *expr7*
-----
***************
*** 909,914 ****
--- 919,945 ----
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,2030 ****
< The current 'encoding' is used. Example for "utf-8": >
char2nr("á") returns 225
char2nr("á"[0]) returns 195
! < nr2char() does the opposite.
cindent({lnum}) *cindent()*
Get the amount of indent for line {lnum} according the C
--- 2058,2064 ----
< The current 'encoding' is used. Example for "utf-8": >
char2nr("á") returns 225
char2nr("á"[0]) returns 195
! < |nr2char()| does the opposite.
cindent({lnum}) *cindent()*
Get the amount of indent for line {lnum} according the C
***************
*** 3893,3898 ****
--- 3928,3936 ----
%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,3956 ****
--- 3989,3996 ----
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,3973 ****
--- 4008,4014 ----
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,3994 ****
--- 4023,4052 ----
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,4786 ****
--- 4841,4859 ----
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,5147 ****
--- 5215,5221 ----
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,5205 ****
--- 5274,5281 ----
< 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
*** ../vim-7.1.291/src/auto/configure Wed Feb 20 12:43:05 2008
--- src/auto/configure Tue Apr 8 22:37:05 2008
***************
*** 10311,10319 ****
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 \
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 \
--- 10311,10320 ----
+
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 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,13088 ****
--- 13084,13221 ----
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.
*** ../vim-7.1.291/src/config.h.in Tue May 1 13:37:23 2007
--- src/config.h.in Sun Apr 6 15:20:29 2008
***************
*** 150,155 ****
--- 150,156 ----
#undef HAVE_MEMSET
#undef HAVE_NANOSLEEP
#undef HAVE_OPENDIR
+ #undef HAVE_POW
#undef HAVE_PUTENV
#undef HAVE_QSORT
#undef HAVE_READLINK
***************
*** 199,204 ****
--- 200,206 ----
#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
*** ../vim-7.1.291/src/configure.in Wed Feb 20 12:43:05 2008
--- src/configure.in Sun Apr 6 15:22:40 2008
***************
*** 2034,2040 ****
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 \
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 \
--- 2034,2040 ----
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 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,2495 ****
--- 2490,2506 ----
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)
*** ../vim-7.1.291/src/eval.c Tue Apr 1 13:10:45 2008
--- src/eval.c Tue Apr 8 22:18:23 2008
***************
*** 30,35 ****
--- 30,39 ----
#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,358 ****
};
/* 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
/*
* The v: variables are stored in dictionary "vimvardict".
--- 353,363 ----
};
/* shorthand */
! #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,455 ****
--- 455,464 ----
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,642 ****
--- 646,654 ----
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,1427 ****
|| defined(FEAT_COMPL_FUNC) || defined(PROTO)
/*
* Call some vimL function and return the result in "*rettv".
! * Uses argv[argc] for the function arguments.
* Returns OK or FAIL.
*/
static int
--- 1433,1440 ----
|| defined(FEAT_COMPL_FUNC) || defined(PROTO)
/*
* Call some vimL function and return the result in "*rettv".
! * Uses argv[argc] for the function arguments. Only Number and String
! * arguments are currently supported.
* Returns OK or FAIL.
*/
static int
***************
*** 2848,2863 ****
{
/* nr += nr or nr -= nr*/
n = get_tv_number(tv1);
! 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
{
/* str .= str */
s = get_tv_string(tv1);
s = concat_str(s, get_tv_string_buf(tv2, numbuf));
--- 2861,2896 ----
{
/* nr += nr or nr -= nr*/
n = get_tv_number(tv1);
! #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
! #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,2871 ****
--- 2899,2925 ----
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,4242 ****
--- 4291,4330 ----
}
}
+ #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,4334 ****
--- 4417,4425 ----
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,4354 ****
if (op != '+' && op != '-' && op != '.')
break;
! if (op != '+' || rettv->v_type != VAR_LIST)
{
/* For "list + ...", an illegal use of the first operand as
* a number cannot be determined before evaluating the 2nd
--- 4439,4449 ----
if (op != '+' && op != '-' && op != '.')
break;
! 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,4440 ****
{
int error = FALSE;
! 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;
}
! n2 = get_tv_number_chk(&var2, &error);
! if (error)
{
! clear_tv(rettv);
! clear_tv(&var2);
! return FAIL;
}
clear_tv(rettv);
! if (op == '+')
! n1 = n1 + n2;
else
! n1 = n1 - n2;
! rettv->v_type = VAR_NUMBER;
! rettv->vval.v_number = n1;
}
clear_tv(&var2);
}
--- 4507,4579 ----
{
int error = FALSE;
! #ifdef FEAT_FLOAT
! if (rettv->v_type == VAR_FLOAT)
{
! f1 = rettv->vval.v_float;
! n1 = 0;
}
! else
! #endif
{
! 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);
!
! #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
! #endif
! {
! if (op == '+')
! n1 = n1 + n2;
! else
! n1 = n1 - n2;
! rettv->v_type = VAR_NUMBER;
! rettv->vval.v_number = n1;
! }
}
clear_tv(&var2);
}
***************
*** 4462,4467 ****
--- 4601,4610 ----
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,4487 ****
if (evaluate)
{
! n1 = get_tv_number_chk(rettv, &error);
clear_tv(rettv);
if (error)
return FAIL;
--- 4624,4639 ----
if (evaluate)
{
! #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,4529 ****
if (evaluate)
{
! n2 = get_tv_number_chk(&var2, &error);
! clear_tv(&var2);
! if (error)
! return FAIL;
/*
* Compute the result.
*/
! if (op == '*')
! n1 = n1 * n2;
! else if (op == '/')
{
! if (n2 == 0) /* give an error message? */
! n1 = 0x7fffffffL;
else
! n1 = n1 / n2;
}
else
{
! if (n2 == 0) /* give an error message? */
! n1 = 0;
else
! n1 = n1 % n2;
}
- rettv->v_type = VAR_NUMBER;
- rettv->vval.v_number = n1;
}
}
--- 4650,4729 ----
if (evaluate)
{
! #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.
*/
! #ifdef FEAT_FLOAT
! if (use_float)
{
! 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
! {
! EMSG(_("E804: Cannot use % with float"));
! return FAIL;
! }
! rettv->v_type = VAR_FLOAT;
! rettv->vval.v_float = f1;
}
else
+ #endif
{
! if (op == '*')
! n1 = n1 * n2;
! else if (op == '/')
! {
! if (n2 == 0) /* give an error message? */
! n1 = 0x7fffffffL;
! else
! n1 = n1 / n2;
! }
else
! {
! if (n2 == 0) /* give an error message? */
! n1 = 0;
! else
! n1 = n1 % n2;
! }
! rettv->v_type = VAR_NUMBER;
! rettv->vval.v_number = n1;
}
}
}
***************
*** 4565,4571 ****
long n;
int len;
char_u *s;
- int val;
char_u *start_leader, *end_leader;
int ret = OK;
char_u *alias;
--- 4765,4770 ----
***************
*** 4635,4641 ****
/*
* Option value: &name
*/
! case '&': ret = get_option_tv(arg, rettv, evaluate);
break;
/*
--- 4834,4846 ----
/*
* Option value: &name
*/
! 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,4741 ****
if (ret == OK && evaluate && end_leader > start_leader)
{
int error = FALSE;
! val = get_tv_number_chk(rettv, &error);
if (error)
{
clear_tv(rettv);
--- 4939,4953 ----
if (ret == OK && evaluate && end_leader > start_leader)
{
int error = FALSE;
+ int val = 0;
+ #ifdef FEAT_FLOAT
+ float_T f = 0;
! 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,4759 ****
{
--end_leader;
if (*end_leader == '!')
! val = !val;
else if (*end_leader == '-')
! val = -val;
}
- clear_tv(rettv);
- rettv->v_type = VAR_NUMBER;
- rettv->vval.v_number = val;
}
}
--- 4959,4995 ----
{
--end_leader;
if (*end_leader == '!')
! {
! #ifdef FEAT_FLOAT
! if (rettv->v_type == VAR_FLOAT)
! f = !f;
! else
! #endif
! val = !val;
! }
else if (*end_leader == '-')
! {
! #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;
}
}
}
***************
*** 4780,4786 ****
char_u *s;
char_u *key = NULL;
! if (rettv->v_type == VAR_FUNC)
{
if (verbose)
EMSG(_("E695: Cannot index a Funcref"));
--- 5016,5026 ----
char_u *s;
char_u *key = NULL;
! if (rettv->v_type == VAR_FUNC
! #ifdef FEAT_FLOAT
! || rettv->v_type == VAR_FLOAT
! #endif
! )
{
if (verbose)
EMSG(_("E695: Cannot index a Funcref"));
***************
*** 5566,5572 ****
/*
* Return TRUE if "tv1" and "tv2" have the same value.
* Compares the items just like "==" would compare them, but strings and
! * numbers are different.
*/
static int
tv_equal(tv1, tv2, ic)
--- 5806,5812 ----
/*
* Return TRUE if "tv1" and "tv2" have the same value.
* Compares the items just like "==" would compare them, but strings and
! * numbers are different. Floats and numbers are also different.
*/
static int
tv_equal(tv1, tv2, ic)
***************
*** 5608,5613 ****
--- 5848,5858 ----
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,6902 ****
--- 7142,7155 ----
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,6934 ****
--- 7182,7190 ----
*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,6989 ****
--- 7240,7310 ----
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,7245 ****
--- 7561,7569 ----
{"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,8805 ****
--- 9124,9134 ----
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,10882 ****
--- 11206,11214 ----
#ifdef FEAT_FIND_ID
"find_in_path",
#endif
+ #ifdef FEAT_FLOAT
+ "float",
+ #endif
#ifdef FEAT_FOLDING
"folding",
#endif
***************
*** 15432,15437 ****
--- 15764,15784 ----
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,16481 ****
--- 16823,16831 ----
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,17667 ****
--- 18012,18020 ----
dict_unref(varp->vval.v_dict);
break;
case VAR_NUMBER:
+ #ifdef FEAT_FLOAT
+ case VAR_FLOAT:
+ #endif
case VAR_UNKNOWN:
break;
default:
***************
*** 17701,17706 ****
--- 18054,18064 ----
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,17754 ****
--- 18107,18117 ----
{
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,17877 ****
--- 18235,18245 ----
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,18415 ****
--- 18778,18788 ----
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,18477 ****
--- 18845,18853 ----
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,20854 ****
#if defined(FEAT_VIMINFO) || defined(FEAT_SESSION)
typedef enum
{
! VAR_FLAVOUR_DEFAULT,
! VAR_FLAVOUR_SESSION,
! VAR_FLAVOUR_VIMINFO
} var_flavour_T;
static var_flavour_T var_flavour __ARGS((char_u *varname));
--- 21222,21230 ----
#if defined(FEAT_VIMINFO) || defined(FEAT_SESSION)
typedef enum
{
! 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,20887 ****
int writing;
{
char_u *tab;
! int is_string = FALSE;
typval_T tv;
if (!writing && (find_viminfo_parameter('!') != NULL))
--- 21257,21263 ----
int writing;
{
char_u *tab;
! int type = VAR_NUMBER;
typval_T tv;
if (!writing && (find_viminfo_parameter('!') != NULL))
***************
*** 20891,20914 ****
{
*tab++ = '\0'; /* isolate the variable name */
if (*tab == 'S') /* string var */
! is_string = TRUE;
tab = vim_strchr(tab, '\t');
if (tab != NULL)
{
! if (is_string)
! {
! tv.v_type = VAR_STRING;
tv.vval.v_string = viminfo_readstring(virp,
(int)(tab - virp->vir_line + 1), TRUE);
! }
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)
vim_free(tv.vval.v_string);
}
}
--- 21267,21293 ----
{
*tab++ = '\0'; /* isolate the variable name */
if (*tab == 'S') /* string var */
! type = VAR_STRING;
! #ifdef FEAT_FLOAT
! else if (*tab == 'F')
! type = VAR_FLOAT;
! #endif
tab = vim_strchr(tab, '\t');
if (tab != NULL)
{
! 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.vval.v_number = atol((char *)tab + 1);
set_var(virp->vir_line + 1, &tv, FALSE);
! if (type == VAR_STRING)
vim_free(tv.vval.v_string);
}
}
***************
*** 20950,20955 ****
--- 21329,21337 ----
{
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,21014 ****
--- 21391,21414 ----
}
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,21086 ****
vim_free(*bufp);
*fnamep = *bufp = newbuf;
! l = GetShortPathName(*fnamep,*fnamep,l+1);
/* Really should always succeed, as the buffer is big enough */
}
--- 21480,21486 ----
vim_free(*bufp);
*fnamep = *bufp = newbuf;
! l = GetShortPathName(*fnamep, *fnamep, l+1);
/* Really should always succeed, as the buffer is big enough */
}
*** ../vim-7.1.291/src/feature.h Fri Aug 3 22:01:35 2007
--- src/feature.h Sun Apr 6 15:24:33 2008
***************
*** 35,41 ****
* +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.
*
* When +small is used, +tiny is also included. +normal implies +small, etc.
*/
--- 35,41 ----
* +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 features enabled.
*
* When +small is used, +tiny is also included. +normal implies +small, etc.
*/
***************
*** 376,384 ****
--- 376,388 ----
/*
* +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
/*
*** ../vim-7.1.291/src/if_python.c Thu Mar 8 10:20:28 2007
--- src/if_python.c Fri Apr 4 21:07:03 2008
***************
*** 1130,1135 ****
--- 1130,1146 ----
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;
*** ../vim-7.1.291/src/message.c Sat Nov 24 15:44:17 2007
--- src/message.c Tue Apr 8 22:19:06 2008
***************
*** 3819,3824 ****
--- 3819,3827 ----
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,3870 ****
--- 3868,3899 ----
}
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,3888 ****
--- 3912,3919 ----
* with flags: '-', '+', ' ', '0' and '#'.
* An asterisk is supported for field width as well as precision.
*
+ * Limited support for 'f' (floating point) was added.
+ *
* Length modifiers 'h' (short int) and 'l' (long int) are supported.
* 'll' (long long int) is not supported.
*
***************
*** 4124,4129 ****
--- 4155,4161 ----
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,4464 ****
--- 4491,4527 ----
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
+ format[0] = '%';
+ l = 1;
+ if (precision_specified)
+ 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,4572 ****
if (justify_left)
{
/* right blank padding to the field width */
! int pn = (int)(min_field_width - (str_arg_l +
number_of_zeros_to_pad));
if (pn > 0)
{
--- 4629,4636 ----
if (justify_left)
{
/* right blank padding to the field width */
! int pn = (int)(min_field_width
! - (str_arg_l + number_of_zeros_to_pad));
if (pn > 0)
{
*** ../vim-7.1.291/src/structs.h Sat Jan 19 15:55:51 2008
--- src/structs.h Fri Apr 4 22:06:03 2008
***************
*** 1005,1010 ****
--- 1005,1011 ----
#else
typedef int varnumber_T;
#endif
+ typedef double float_T;
typedef struct listvar_S list_T;
typedef struct dictvar_S dict_T;
***************
*** 1019,1024 ****
--- 1020,1028 ----
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,1037 ****
--- 1036,1042 ----
#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() */
*** ../vim-7.1.291/src/version.c Tue Apr 1 20:58:23 2008
--- src/version.c Sun Apr 6 15:25:42 2008
***************
*** 217,222 ****
--- 217,227 ----
#else
"-find_in_path",
#endif
+ #ifdef FEAT_FLOAT
+ "+float",
+ #else
+ "-float",
+ #endif
#ifdef FEAT_FOLDING
"+folding",
#else
+** ../vim-7.1.291/src/version.c Tue Apr 1 20:58:23 2008
--- src/version.c Sun Apr 6 15:25:42 2008
**************
"-find_in_path",
#endif
+ #ifdef FEAT_FLOAT
+ "+float",
+ #else
+ "-float",
+ #endif
#ifdef FEAT_FOLDING
"+folding",
--
hundred-and-one symptoms of being an internet addict:
256. You are able to write down over 250 symptoms of being an internet
addict, even though they only asked for 101.
/// Bram Moolenaar -- [EMAIL PROTECTED] -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ download, build and distribute -- http://www.A-A-P.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--~--~---------~--~----~------------~-------~--~----~
You received this message from the "vim_dev" maillist.
For more information, visit http://www.vim.org/maillist.php
-~----------~----~----~----~------~----~------~--~---