summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2008-06-24 22:58:06 +0000
committerBram Moolenaar <Bram@vim.org>2008-06-24 22:58:06 +0000
commit8c8de839325eda0bed68917d18179d2003b344d1 (patch)
treec65b80f0a627f2e77385a07a62ee4206465cbc22 /src
parent864207de089119377a1e1e5d411307d8eb57399e (diff)
updated for version 7.2av7.2a
Diffstat (limited to 'src')
-rw-r--r--src/config.mk.in3
-rw-r--r--src/digraph.c7
-rw-r--r--src/eval.c1005
-rw-r--r--src/ex_cmds.c13
-rw-r--r--src/ex_cmds.h12
-rw-r--r--src/ex_cmds2.c23
-rw-r--r--src/farsi.c4
-rw-r--r--src/fold.c2
-rw-r--r--src/gui_gtk_x11.c5
-rw-r--r--src/main.c10
-rw-r--r--src/memfile.c4
-rw-r--r--src/memline.c8
-rw-r--r--src/menu.c8
-rw-r--r--src/misc1.c8
-rw-r--r--src/nbdebug.h2
-rw-r--r--src/os_amiga.c4
-rw-r--r--src/os_win16.c1
-rw-r--r--src/os_win16.h1
-rw-r--r--src/po/ca.po2362
-rw-r--r--src/po/fi.po6216
-rw-r--r--src/po/ga.po1756
-rw-r--r--src/po/it.po212
-rw-r--r--src/po/ru.cp1251.po16
-rw-r--r--src/po/ru.po16
-rw-r--r--src/po/sv.po8
-rw-r--r--src/po/uk.po5018
-rw-r--r--src/proto/misc2.pro8
-rw-r--r--src/proto/search.pro1
-rw-r--r--src/pty.c4
-rw-r--r--src/search.c61
-rw-r--r--src/syntax.c70
-rw-r--r--src/testdir/Make_vms.mms4
-rw-r--r--src/testdir/Makefile2
-rw-r--r--src/testdir/test11.in12
-rw-r--r--src/testdir/test3.in2
-rw-r--r--src/testdir/test65.in78
36 files changed, 13808 insertions, 3158 deletions
diff --git a/src/config.mk.in b/src/config.mk.in
index 759559a4e8..9590d445a1 100644
--- a/src/config.mk.in
+++ b/src/config.mk.in
@@ -109,6 +109,9 @@ exec_prefix = @exec_prefix@
### Prefix for location of data files
BINDIR = @bindir@
+### For autoconf 2.60 and later (avoid a warning)
+datarootdir = @datarootdir@
+
### Prefix for location of data files
DATADIR = @datadir@
diff --git a/src/digraph.c b/src/digraph.c
index 9d04af6197..b867598a62 100644
--- a/src/digraph.c
+++ b/src/digraph.c
@@ -2538,6 +2538,7 @@ keymap_unload()
char_u buf[KMAP_MAXLEN + 10];
int i;
char_u *save_cpo = p_cpo;
+ kmap_T *kp;
if (!(curbuf->b_kmap_state & KEYMAP_LOADED))
return;
@@ -2546,11 +2547,13 @@ keymap_unload()
p_cpo = (char_u *)"C";
/* clear the ":lmap"s */
+ kp = (kmap_T *)curbuf->b_kmap_ga.ga_data;
for (i = 0; i < curbuf->b_kmap_ga.ga_len; ++i)
{
- vim_snprintf((char *)buf, sizeof(buf), "<buffer> %s",
- ((kmap_T *)curbuf->b_kmap_ga.ga_data)[i].from);
+ vim_snprintf((char *)buf, sizeof(buf), "<buffer> %s", kp[i].from);
(void)do_map(1, buf, LANGMAP, FALSE);
+ vim_free(kp[i].from);
+ vim_free(kp[i].to);
}
p_cpo = save_cpo;
diff --git a/src/eval.c b/src/eval.c
index 54ca054ca1..fada51d646 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -16,6 +16,8 @@
#include "vim.h"
+#if defined(FEAT_EVAL) || defined(PROTO)
+
#ifdef AMIGA
# include <time.h> /* for strftime() */
#endif
@@ -24,12 +26,10 @@
# include <time.h> /* for time_t */
#endif
-#ifdef HAVE_FCNTL_H
-# include <fcntl.h>
+#if defined(FEAT_FLOAT) && defined(HAVE_MATH_H)
+# include <math.h>
#endif
-#if defined(FEAT_EVAL) || defined(PROTO)
-
#define DICT_MAXNEST 100 /* maximum nesting of lists and dicts */
/*
@@ -108,6 +108,7 @@ static char *e_dictrange = N_("E719: Cannot use [:] with a Dictionary");
static char *e_letwrong = N_("E734: Wrong variable type for %s=");
static char *e_nofunc = N_("E130: Unknown function: %s");
static char *e_illvar = N_("E461: Illegal variable name: %s");
+
/*
* All user-defined global variables are stored in dictionary "globvardict".
* "globvars_var" is the variable that is used for "g:".
@@ -164,13 +165,13 @@ struct ufunc
int uf_profiling; /* TRUE when func is being profiled */
/* profiling the function as a whole */
int uf_tm_count; /* nr of calls */
- proftime_T uf_tm_total; /* time spend in function + children */
- proftime_T uf_tm_self; /* time spend in function itself */
+ proftime_T uf_tm_total; /* time spent in function + children */
+ proftime_T uf_tm_self; /* time spent in function itself */
proftime_T uf_tm_children; /* time spent in children this call */
/* profiling the function per line */
int *uf_tml_count; /* nr of times line was executed */
- proftime_T *uf_tml_total; /* time spend in a line + children */
- proftime_T *uf_tml_self; /* time spend in a line itself */
+ proftime_T *uf_tml_total; /* time spent in a line + children */
+ proftime_T *uf_tml_self; /* time spent in a line itself */
proftime_T uf_tml_start; /* start time for current line */
proftime_T uf_tml_children; /* time spent in children for this line */
proftime_T uf_tml_wait; /* start wait time for current line */
@@ -346,13 +347,15 @@ static struct vimvar
{VV_NAME("mouse_lnum", VAR_NUMBER), 0},
{VV_NAME("mouse_col", VAR_NUMBER), 0},
{VV_NAME("operator", VAR_STRING), VV_RO},
+ {VV_NAME("searchforward", VAR_NUMBER), 0},
};
/* shorthand */
-#define vv_type vv_di.di_tv.v_type
-#define vv_nr vv_di.di_tv.vval.v_number
-#define vv_str vv_di.di_tv.vval.v_string
-#define vv_tv vv_di.di_tv
+#define vv_type vv_di.di_tv.v_type
+#define vv_nr vv_di.di_tv.vval.v_number
+#define vv_float vv_di.di_tv.vval.v_float
+#define vv_str vv_di.di_tv.vval.v_string
+#define vv_tv vv_di.di_tv
/*
* The v: variables are stored in dictionary "vimvardict".
@@ -450,6 +453,9 @@ static int get_dict_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
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 int string2float __ARGS((char_u *text, float_T *value));
+#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));
@@ -457,11 +463,17 @@ static int get_func_tv __ARGS((char_u *name, int len, typval_T *rettv, char_u **
static int call_func __ARGS((char_u *name, int len, typval_T *rettv, int argcount, typval_T *argvars, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict));
static void emsg_funcname __ARGS((char *ermsg, char_u *name));
+#ifdef FEAT_FLOAT
+static void f_abs __ARGS((typval_T *argvars, typval_T *rettv));
+#endif
static void f_add __ARGS((typval_T *argvars, typval_T *rettv));
static void f_append __ARGS((typval_T *argvars, typval_T *rettv));
static void f_argc __ARGS((typval_T *argvars, typval_T *rettv));
static void f_argidx __ARGS((typval_T *argvars, typval_T *rettv));
static void f_argv __ARGS((typval_T *argvars, typval_T *rettv));
+#ifdef FEAT_FLOAT
+static void f_atan __ARGS((typval_T *argvars, typval_T *rettv));
+#endif
static void f_browse __ARGS((typval_T *argvars, typval_T *rettv));
static void f_browsedir __ARGS((typval_T *argvars, typval_T *rettv));
static void f_bufexists __ARGS((typval_T *argvars, typval_T *rettv));
@@ -473,6 +485,9 @@ static void f_bufwinnr __ARGS((typval_T *argvars, typval_T *rettv));
static void f_byte2line __ARGS((typval_T *argvars, typval_T *rettv));
static void f_byteidx __ARGS((typval_T *argvars, typval_T *rettv));
static void f_call __ARGS((typval_T *argvars, typval_T *rettv));
+#ifdef FEAT_FLOAT
+static void f_ceil __ARGS((typval_T *argvars, typval_T *rettv));
+#endif
static void f_changenr __ARGS((typval_T *argvars, typval_T *rettv));
static void f_char2nr __ARGS((typval_T *argvars, typval_T *rettv));
static void f_cindent __ARGS((typval_T *argvars, typval_T *rettv));
@@ -485,6 +500,9 @@ static void f_complete_check __ARGS((typval_T *argvars, typval_T *rettv));
#endif
static void f_confirm __ARGS((typval_T *argvars, typval_T *rettv));
static void f_copy __ARGS((typval_T *argvars, typval_T *rettv));
+#ifdef FEAT_FLOAT
+static void f_cos __ARGS((typval_T *argvars, typval_T *rettv));
+#endif
static void f_count __ARGS((typval_T *argvars, typval_T *rettv));
static void f_cscope_connection __ARGS((typval_T *argvars, typval_T *rettv));
static void f_cursor __ARGS((typval_T *argsvars, typval_T *rettv));
@@ -507,6 +525,10 @@ static void f_filewritable __ARGS((typval_T *argvars, typval_T *rettv));
static void f_filter __ARGS((typval_T *argvars, typval_T *rettv));
static void f_finddir __ARGS((typval_T *argvars, typval_T *rettv));
static void f_findfile __ARGS((typval_T *argvars, typval_T *rettv));
+#ifdef FEAT_FLOAT
+static void f_float2nr __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_floor __ARGS((typval_T *argvars, typval_T *rettv));
+#endif
static void f_fnameescape __ARGS((typval_T *argvars, typval_T *rettv));
static void f_fnamemodify __ARGS((typval_T *argvars, typval_T *rettv));
static void f_foldclosed __ARGS((typval_T *argvars, typval_T *rettv));
@@ -578,6 +600,9 @@ static void f_line __ARGS((typval_T *argvars, typval_T *rettv));
static void f_line2byte __ARGS((typval_T *argvars, typval_T *rettv));
static void f_lispindent __ARGS((typval_T *argvars, typval_T *rettv));
static void f_localtime __ARGS((typval_T *argvars, typval_T *rettv));
+#ifdef FEAT_FLOAT
+static void f_log10 __ARGS((typval_T *argvars, typval_T *rettv));
+#endif
static void f_map __ARGS((typval_T *argvars, typval_T *rettv));
static void f_maparg __ARGS((typval_T *argvars, typval_T *rettv));
static void f_mapcheck __ARGS((typval_T *argvars, typval_T *rettv));
@@ -597,6 +622,9 @@ static void f_mode __ARGS((typval_T *argvars, typval_T *rettv));
static void f_nextnonblank __ARGS((typval_T *argvars, typval_T *rettv));
static void f_nr2char __ARGS((typval_T *argvars, typval_T *rettv));
static void f_pathshorten __ARGS((typval_T *argvars, typval_T *rettv));
+#ifdef FEAT_FLOAT
+static void f_pow __ARGS((typval_T *argvars, typval_T *rettv));
+#endif
static void f_prevnonblank __ARGS((typval_T *argvars, typval_T *rettv));
static void f_printf __ARGS((typval_T *argvars, typval_T *rettv));
static void f_pumvisible __ARGS((typval_T *argvars, typval_T *rettv));
@@ -614,6 +642,9 @@ static void f_rename __ARGS((typval_T *argvars, typval_T *rettv));
static void f_repeat __ARGS((typval_T *argvars, typval_T *rettv));
static void f_resolve __ARGS((typval_T *argvars, typval_T *rettv));
static void f_reverse __ARGS((typval_T *argvars, typval_T *rettv));
+#ifdef FEAT_FLOAT
+static void f_round __ARGS((typval_T *argvars, typval_T *rettv));
+#endif
static void f_search __ARGS((typval_T *argvars, typval_T *rettv));
static void f_searchdecl __ARGS((typval_T *argvars, typval_T *rettv));
static void f_searchpair __ARGS((typval_T *argvars, typval_T *rettv));
@@ -633,11 +664,18 @@ static void f_settabwinvar __ARGS((typval_T *argvars, typval_T *rettv));
static void f_setwinvar __ARGS((typval_T *argvars, typval_T *rettv));
static void f_shellescape __ARGS((typval_T *argvars, typval_T *rettv));
static void f_simplify __ARGS((typval_T *argvars, typval_T *rettv));
+#ifdef FEAT_FLOAT
+static void f_sin __ARGS((typval_T *argvars, typval_T *rettv));
+#endif
static void f_sort __ARGS((typval_T *argvars, typval_T *rettv));
static void f_soundfold __ARGS((typval_T *argvars, typval_T *rettv));
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_sqrt __ARGS((typval_T *argvars, typval_T *rettv));
+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));
@@ -665,6 +703,9 @@ static void f_test __ARGS((typval_T *argvars, typval_T *rettv));
static void f_tolower __ARGS((typval_T *argvars, typval_T *rettv));
static void f_toupper __ARGS((typval_T *argvars, typval_T *rettv));
static void f_tr __ARGS((typval_T *argvars, typval_T *rettv));
+#ifdef FEAT_FLOAT
+static void f_trunc __ARGS((typval_T *argvars, typval_T *rettv));
+#endif
static void f_type __ARGS((typval_T *argvars, typval_T *rettv));
static void f_values __ARGS((typval_T *argvars, typval_T *rettv));
static void f_virtcol __ARGS((typval_T *argvars, typval_T *rettv));
@@ -788,6 +829,7 @@ eval_init()
/* add to compat scope dict */
hash_add(&compat_hashtab, p->vv_di.di_key);
}
+ set_vim_var_nr(VV_SEARCHFORWARD, 1L);
}
#if defined(EXITFREE) || defined(PROTO)
@@ -818,15 +860,15 @@ eval_clear()
/* global variables */
vars_clear(&globvarht);
- /* functions */
- free_all_functions();
- hash_clear(&func_hashtab);
-
/* autoloaded script names */
ga_clear_strings(&ga_loaded);
/* unreferenced lists and dicts */
(void)garbage_collect();
+
+ /* functions */
+ free_all_functions();
+ hash_clear(&func_hashtab);
}
#endif
@@ -1422,7 +1464,8 @@ eval_expr(arg, nextcmd)
|| defined(FEAT_COMPL_FUNC) || defined(PROTO)
/*
* Call some vimL function and return the result in "*rettv".
- * Uses argv[argc] for the function arguments.
+ * Uses argv[argc] for the function arguments. Only Number and String
+ * arguments are currently supported.
* Returns OK or FAIL.
*/
static int
@@ -2849,16 +2892,36 @@ tv_op(tv1, tv2, op)
{
/* nr += nr or nr -= nr*/
n = get_tv_number(tv1);
- if (*op == '+')
- n += get_tv_number(tv2);
+#ifdef FEAT_FLOAT
+ if (tv2->v_type == VAR_FLOAT)
+ {
+ float_T f = n;
+
+ if (*op == '+')
+ f += tv2->vval.v_float;
+ else
+ f -= tv2->vval.v_float;
+ clear_tv(tv1);
+ tv1->v_type = VAR_FLOAT;
+ tv1->vval.v_float = f;
+ }
else
- n -= get_tv_number(tv2);
- clear_tv(tv1);
- tv1->v_type = VAR_NUMBER;
- tv1->vval.v_number = n;
+#endif
+ {
+ if (*op == '+')
+ n += get_tv_number(tv2);
+ else
+ n -= get_tv_number(tv2);
+ clear_tv(tv1);
+ tv1->v_type = VAR_NUMBER;
+ tv1->vval.v_number = n;
+ }
}
else
{
+ if (tv2->v_type == VAR_FLOAT)
+ break;
+
/* str .= str */
s = get_tv_string(tv1);
s = concat_str(s, get_tv_string_buf(tv2, numbuf));
@@ -2867,6 +2930,27 @@ tv_op(tv1, tv2, op)
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
}
}
@@ -4115,7 +4199,7 @@ eval4(arg, rettv, evaluate)
}
/*
- * If there is a comparitive operator, use it.
+ * If there is a comparative operator, use it.
*/
if (type != TYPE_UNKNOWN)
{
@@ -4131,7 +4215,7 @@ eval4(arg, rettv, evaluate)
ic = FALSE;
++len;
}
- /* nothing appened: use 'ignorecase' */
+ /* nothing appended: use 'ignorecase' */
else
ic = p_ic;
@@ -4238,6 +4322,40 @@ eval4(arg, rettv, evaluate)
}
}
+#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.
@@ -4330,6 +4448,9 @@ eval5(arg, rettv, evaluate)
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;
@@ -4349,7 +4470,11 @@ eval5(arg, rettv, evaluate)
if (op != '+' && op != '-' && op != '.')
break;
- if (op != '+' || rettv->v_type != VAR_LIST)
+ if ((op != '+' || rettv->v_type != VAR_LIST)
+#ifdef FEAT_FLOAT
+ && (op == '.' || rettv->v_type != VAR_FLOAT)
+#endif
+ )
{
/* For "list + ...", an illegal use of the first operand as
* a number cannot be determined before evaluating the 2nd
@@ -4413,29 +4538,73 @@ eval5(arg, rettv, evaluate)
{
int error = FALSE;
- n1 = get_tv_number_chk(rettv, &error);
- if (error)
+#ifdef FEAT_FLOAT
+ if (rettv->v_type == VAR_FLOAT)
{
- /* This can only happen for "list + non-list".
- * For "non-list + ..." or "something - ...", we returned
- * before evaluating the 2nd operand. */
- clear_tv(rettv);
- return FAIL;
+ f1 = rettv->vval.v_float;
+ n1 = 0;
}
- n2 = get_tv_number_chk(&var2, &error);
- if (error)
+ else
+#endif
{
- clear_tv(rettv);
- clear_tv(&var2);
- return FAIL;
+ n1 = get_tv_number_chk(rettv, &error);
+ if (error)
+ {
+ /* This can only happen for "list + non-list". For
+ * "non-list + ..." or "something - ...", we returned
+ * before evaluating the 2nd operand. */
+ clear_tv(rettv);
+ return FAIL;
+ }
+#ifdef FEAT_FLOAT
+ if (var2.v_type == VAR_FLOAT)
+ f1 = n1;
+#endif
+ }
+#ifdef FEAT_FLOAT
+ if (var2.v_type == VAR_FLOAT)
+ {
+ f2 = var2.vval.v_float;
+ n2 = 0;
+ }
+ else
+#endif
+ {
+ n2 = get_tv_number_chk(&var2, &error);
+ if (error)
+ {
+ clear_tv(rettv);
+ clear_tv(&var2);
+ return FAIL;
+ }
+#ifdef FEAT_FLOAT
+ if (rettv->v_type == VAR_FLOAT)
+ f2 = n2;
+#endif
}
clear_tv(rettv);
- if (op == '+')
- n1 = n1 + n2;
+
+#ifdef FEAT_FLOAT
+ /* If there is a float on either side the result is a float. */
+ if (rettv->v_type == VAR_FLOAT || var2.v_type == VAR_FLOAT)
+ {
+ if (op == '+')
+ f1 = f1 + f2;
+ else
+ f1 = f1 - f2;
+ rettv->v_type = VAR_FLOAT;
+ rettv->vval.v_float = f1;
+ }
else
- n1 = n1 - n2;
- rettv->v_type = VAR_NUMBER;
- rettv->vval.v_number = n1;
+#endif
+ {
+ if (op == '+')
+ n1 = n1 + n2;
+ else
+ n1 = n1 - n2;
+ rettv->v_type = VAR_NUMBER;
+ rettv->vval.v_number = n1;
+ }
}
clear_tv(&var2);
}
@@ -4463,6 +4632,10 @@ eval6(arg, rettv, evaluate)
typval_T var2;
int op;
long n1, n2;
+#ifdef FEAT_FLOAT
+ int use_float = FALSE;
+ float_T f1 = 0, f2;
+#endif
int error = FALSE;
/*
@@ -4482,7 +4655,16 @@ eval6(arg, rettv, evaluate)
if (evaluate)
{
- n1 = get_tv_number_chk(rettv, &error);
+#ifdef FEAT_FLOAT
+ if (rettv->v_type == VAR_FLOAT)
+ {
+ f1 = rettv->vval.v_float;
+ use_float = TRUE;
+ n1 = 0;
+ }
+ else
+#endif
+ n1 = get_tv_number_chk(rettv, &error);
clear_tv(rettv);
if (error)
return FAIL;
@@ -4499,32 +4681,82 @@ eval6(arg, rettv, evaluate)
if (evaluate)
{
- n2 = get_tv_number_chk(&var2, &error);
- clear_tv(&var2);
- if (error)
- return FAIL;
+#ifdef FEAT_FLOAT
+ if (var2.v_type == VAR_FLOAT)
+ {
+ if (!use_float)
+ {
+ f1 = n1;
+ use_float = TRUE;
+ }
+ f2 = var2.vval.v_float;
+ n2 = 0;
+ }
+ else
+#endif
+ {
+ n2 = get_tv_number_chk(&var2, &error);
+ clear_tv(&var2);
+ if (error)
+ return FAIL;
+#ifdef FEAT_FLOAT
+ if (use_float)
+ f2 = n2;
+#endif
+ }
/*
* Compute the result.
+ * When either side is a float the result is a float.
*/
- if (op == '*')
- n1 = n1 * n2;
- else if (op == '/')
+#ifdef FEAT_FLOAT
+ if (use_float)
{
- if (n2 == 0) /* give an error message? */
- n1 = 0x7fffffffL;
+ if (op == '*')
+ f1 = f1 * f2;
+ else if (op == '/')
+ {
+ /* We rely on the floating point library to handle divide
+ * by zero to result in "inf" and not a crash. */
+ f1 = f1 / f2;
+ }
else
- n1 = n1 / n2;
+ {
+ EMSG(_("E804: Cannot use % with float"));
+ return FAIL;
+ }
+ rettv->v_type = VAR_FLOAT;
+ rettv->vval.v_float = f1;
}
else
+#endif
{
- if (n2 == 0) /* give an error message? */
- n1 = 0;
+ if (op == '*')
+ n1 = n1 * n2;
+ else if (op == '/')
+ {
+ if (n2 == 0) /* give an error message? */
+ {
+ if (n1 == 0)
+ n1 = -0x7fffffffL - 1L; /* similar to NaN */
+ else if (n1 < 0)
+ n1 = -0x7fffffffL;
+ else
+ n1 = 0x7fffffffL;
+ }
+ else
+ n1 = n1 / n2;
+ }
else
- n1 = n1 % n2;
+ {
+ if (n2 == 0) /* give an error message? */
+ n1 = 0;
+ else
+ n1 = n1 % n2;
+ }
+ rettv->v_type = VAR_NUMBER;
+ rettv->vval.v_number = n1;
}
- rettv->v_type = VAR_NUMBER;
- rettv->vval.v_number = n1;
}
}
@@ -4566,7 +4798,6 @@ eval7(arg, rettv, evaluate)
long n;
int len;
char_u *s;
- int val;
char_u *start_leader, *end_leader;
int ret = OK;
char_u *alias;
@@ -4600,14 +4831,55 @@ eval7(arg, rettv, evaluate)
case '7':
case '8':
case '9':
- vim_str2nr(*arg, NULL, &len, TRUE, TRUE, &n, NULL);
- *arg += len;
- if (evaluate)
+ {
+#ifdef FEAT_FLOAT
+ char_u *p = skipdigits(*arg + 1);
+ int get_float = FALSE;
+
+ /* We accept a float when the format matches
+ * "[0-9]\+\.[0-9]\+\([eE][+-]\?[0-9]\+\)\?". This is very
+ * strict to avoid backwards compatibility problems. */
+ if (p[0] == '.' && vim_isdigit(p[1]))
{
- rettv->v_type = VAR_NUMBER;
- rettv->vval.v_number = n;
+ get_float = TRUE;
+ p = skipdigits(p + 2);
+ if (*p == 'e' || *p == 'E')
+ {
+ ++p;
+ if (*p == '-' || *p == '+')
+ ++p;
+ if (!vim_isdigit(*p))
+ get_float = FALSE;
+ else
+ p = skipdigits(p + 1);
+ }
+ if (ASCII_ISALPHA(*p) || *p == '.')
+ get_float = FALSE;
+ }
+ if (get_float)
+ {
+ float_T f;
+
+ *arg += string2float(*arg, &f);
+ if (evaluate)
+ {
+ rettv->v_type = VAR_FLOAT;
+ rettv->vval.v_float = f;
+ }
+ }
+ else
+#endif
+ {
+ vim_str2nr(*arg, NULL, &len, TRUE, TRUE, &n, NULL);
+ *arg += len;
+ if (evaluate)
+ {
+ rettv->v_type = VAR_NUMBER;
+ rettv->vval.v_number = n;
+ }
}
break;
+ }
/*
* String constant: "string".
@@ -4735,8 +5007,15 @@ eval7(arg, rettv, evaluate)
if (ret == OK && evaluate && end_leader > start_leader)
{
int error = FALSE;
+ int val = 0;
+#ifdef FEAT_FLOAT
+ float_T f = 0.0;
- val = get_tv_number_chk(rettv, &error);
+ if (rettv->v_type == VAR_FLOAT)
+ f = rettv->vval.v_float;
+ else
+#endif
+ val = get_tv_number_chk(rettv, &error);
if (error)
{
clear_tv(rettv);
@@ -4748,13 +5027,37 @@ eval7(arg, rettv, evaluate)
{
--end_leader;
if (*end_leader == '!')
- val = !val;
+ {
+#ifdef FEAT_FLOAT
+ if (rettv->v_type == VAR_FLOAT)
+ f = !f;
+ else
+#endif
+ val = !val;
+ }
else if (*end_leader == '-')
- val = -val;
+ {
+#ifdef FEAT_FLOAT
+ if (rettv->v_type == VAR_FLOAT)
+ f = -f;
+ else
+#endif
+ val = -val;
+ }
+ }
+#ifdef FEAT_FLOAT
+ if (rettv->v_type == VAR_FLOAT)
+ {
+ clear_tv(rettv);
+ rettv->vval.v_float = f;
+ }
+ else
+#endif
+ {
+ clear_tv(rettv);
+ rettv->v_type = VAR_NUMBER;
+ rettv->vval.v_number = val;
}
- clear_tv(rettv);
- rettv->v_type = VAR_NUMBER;
- rettv->vval.v_number = val;
}
}
@@ -4781,7 +5084,11 @@ eval_index(arg, rettv, evaluate, verbose)
char_u *s;
char_u *key = NULL;
- if (rettv->v_type == VAR_FUNC)
+ if (rettv->v_type == VAR_FUNC
+#ifdef FEAT_FLOAT
+ || rettv->v_type == VAR_FLOAT
+#endif
+ )
{
if (verbose)
EMSG(_("E695: Cannot index a Funcref"));
@@ -5567,7 +5874,7 @@ dict_equal(d1, d2, ic)
/*
* Return TRUE if "tv1" and "tv2" have the same value.
* Compares the items just like "==" would compare them, but strings and
- * numbers are different.
+ * numbers are different. Floats and numbers are also different.
*/
static int
tv_equal(tv1, tv2, ic)
@@ -5609,6 +5916,11 @@ tv_equal(tv1, tv2, ic)
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);
@@ -6898,6 +7210,14 @@ echo_string(tv, tofree, numbuf, copyID)
r = get_tv_string_buf(tv, numbuf);
break;
+#ifdef FEAT_FLOAT
+ case VAR_FLOAT:
+ *tofree = NULL;
+ vim_snprintf((char *)numbuf, NUMBUFLEN, "%g", tv->vval.v_float);
+ r = numbuf;
+ break;
+#endif
+
default:
EMSG2(_(e_intern2), "echo_string()");
*tofree = NULL;
@@ -6929,6 +7249,12 @@ tv2string(tv, tofree, numbuf, copyID)
case VAR_STRING:
*tofree = string_quote(tv->vval.v_string, FALSE);
return *tofree;
+#ifdef FEAT_FLOAT
+ case VAR_FLOAT:
+ *tofree = NULL;
+ vim_snprintf((char *)numbuf, NUMBUFLEN - 1, "%g", tv->vval.v_float);
+ return numbuf;
+#endif
case VAR_NUMBER:
case VAR_LIST:
case VAR_DICT:
@@ -6985,6 +7311,27 @@ string_quote(str, function)
return s;
}
+#ifdef FEAT_FLOAT
+/*
+ * Convert the string "text" to a floating point number.
+ * This uses strtod(). setlocale(LC_NUMERIC, "C") has been used to make sure
+ * this always uses a decimal point.
+ * Returns the length of the text that was consumed.
+ */
+ static int
+string2float(text, value)
+ char_u *text;
+ float_T *value; /* result stored here */
+{
+ char *s = (char *)text;
+ float_T f;
+
+ f = strtod(s, &s);
+ *value = f;
+ return (int)((char_u *)s - text);
+}
+#endif
+
/*
* Get the value of an environment variable.