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
-~----------~----~----~----~------~----~------~--~---

Raspunde prin e-mail lui