summaryrefslogtreecommitdiffstats
path: root/src/eval.c
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/eval.c
parent864207de089119377a1e1e5d411307d8eb57399e (diff)
updated for version 7.2av7.2a
Diffstat (limited to 'src/eval.c')
-rw-r--r--src/eval.c1005
1 files changed, 897 insertions, 108 deletions
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.
* "arg" is pointing to the '$'. It is advanced to after the name.
@@ -7054,11 +7401,17 @@ static struct fst
/* implementation of function */
} functions[] =
{
+#ifdef FEAT_FLOAT
+ {"abs", 1, 1, f_abs},
+#endif
{"add", 2, 2, f_add},
{"append", 2, 2, f_append},
{"argc", 0, 0, f_argc},
{"argidx", 0, 0, f_argidx},
{"argv", 0, 1, f_argv},
+#ifdef FEAT_FLOAT
+ {"atan", 1, 1, f_atan},
+#endif
{"browse", 4, 4, f_browse},
{"browsedir", 2, 2, f_browsedir},
{"bufexists", 1, 1, f_bufexists},
@@ -7073,6 +7426,9 @@ static struct fst
{"byte2line", 1, 1, f_byte2line},
{"byteidx", 2, 2, f_byteidx},
{"call", 2, 3, f_call},
+#ifdef FEAT_FLOAT
+ {"ceil", 1, 1, f_ceil},
+#endif
{"changenr", 0, 0, f_changenr},
{"char2nr", 1, 1, f_char2nr},
{"cindent", 1, 1, f_cindent},
@@ -7085,6 +7441,9 @@ static struct fst
#endif
{"confirm", 1, 4, f_confirm},
{"copy", 1, 1, f_copy},
+#ifdef FEAT_FLOAT
+ {"cos", 1, 1, f_cos},
+#endif
{"count", 2, 4, f_count},
{"cscope_connection",0,3, f_cscope_connection},
{"cursor", 1, 3, f_cursor},
@@ -7108,6 +7467,10 @@ static struct fst
{"filter", 2, 2, f_filter},
{"finddir", 1, 3, f_finddir},
{"findfile", 1, 3, f_findfile},
+#ifdef FEAT_FLOAT
+ {"float2nr", 1, 1, f_float2nr},
+ {"floor", 1, 1, f_floor},
+#endif
{"fnameescape", 1, 1, f_fnameescape},
{"fnamemodify", 2, 2, f_fnamemodify},
{"foldclosed", 1, 1, f_foldclosed},
@@ -7182,6 +7545,9 @@ static struct fst
{"line2byte", 1, 1, f_line2byte},
{"lispindent", 1, 1, f_lispindent},
{"localtime", 0, 0, f_localtime},
+#ifdef FEAT_FLOAT
+ {"log10", 1, 1, f_log10},
+#endif
{"map", 2, 2, f_map},
{"maparg", 1, 3, f_maparg},
{"mapcheck", 1, 3, f_mapcheck},
@@ -7197,10 +7563,13 @@ static struct fst
#ifdef vim_mkdir
{"mkdir", 1, 3, f_mkdir},
#endif
- {"mode", 0, 0, f_mode},
+ {"mode", 0, 1, f_mode},
{"nextnonblank", 1, 1, f_nextnonblank},
{"nr2char", 1, 1, f_nr2char},
{"pathshorten", 1, 1, f_pathshorten},
+#ifdef FEAT_FLOAT
+ {"pow", 2, 2, f_pow},
+#endif
{"prevnonblank", 1, 1, f_prevnonblank},
{"printf", 2, 19, f_printf},
{"pumvisible", 0, 0, f_pumvisible},
@@ -7218,6 +7587,9 @@ static struct fst
{"repeat", 2, 2, f_repeat},
{"resolve", 1, 1, f_resolve},
{"reverse", 1, 1, f_reverse},
+#ifdef FEAT_FLOAT
+ {"round", 1, 1, f_round},
+#endif
{"search", 1, 4, f_search},
{"searchdecl", 1, 3, f_searchdecl},
{"searchpair", 3, 7, f_searchpair},
@@ -7237,11 +7609,18 @@ static struct fst
{"setwinvar", 3, 3, f_setwinvar},
{"shellescape", 1, 1, f_shellescape},
{"simplify", 1, 1, f_simplify},
+#ifdef FEAT_FLOAT
+ {"sin", 1, 1, f_sin},
+#endif
{"sort", 1, 2, f_sort},
{"soundfold", 1, 1, f_soundfold},
{"spellbadword", 0, 1, f_spellbadword},
{"spellsuggest", 1, 3, f_spellsuggest},
{"split", 1, 3, f_split},
+#ifdef FEAT_FLOAT
+ {"sqrt", 1, 1, f_sqrt},
+ {"str2float", 1, 1, f_str2float},
+#endif
{"str2nr", 1, 2, f_str2nr},
#ifdef HAVE_STRFTIME
{"strftime", 1, 2, f_strftime},
@@ -7269,6 +7648,9 @@ static struct fst
{"tolower", 1, 1, f_tolower},
{"toupper", 1, 1, f_toupper},
{"tr", 3, 3, f_tr},
+#ifdef FEAT_FLOAT
+ {"trunc", 1, 1, f_trunc},
+#endif
{"type", 1, 1, f_type},
{"values", 1, 1, f_values},
{"virtcol", 1, 1, f_virtcol},
@@ -7712,6 +8094,36 @@ emsg_funcname(ermsg, name)
* Implementation of the built-in functions
*/
+#ifdef FEAT_FLOAT
+/*
+ * "abs(expr)" function
+ */
+ static void
+f_abs(argvars, rettv)
+ typval_T *argvars;
+ typval_T *rettv;
+{
+ if (argvars[0].v_type == VAR_FLOAT)
+ {
+ rettv->v_type = VAR_FLOAT;
+ rettv->vval.v_float = fabs(argvars[0].vval.v_float);
+ }
+ else
+ {
+ varnumber_T n;
+ int error = FALSE;
+
+ n = get_tv_number_chk(&argvars[0], &error);
+ if (error)
+ rettv->vval.v_number = -1;
+ else if (n > 0)
+ rettv->vval.v_number = n;
+ else
+ rettv->vval.v_number = -n;
+ }
+}
+#endif
+
/*
* "add(list, item)" function
*/
@@ -7840,6 +8252,50 @@ f_argv(argvars, rettv)
alist_name(&ARGLIST[idx]), -1);
}
+#ifdef FEAT_FLOAT
+static int get_float_arg __ARGS((typval_T *argvars, float_T *f));
+
+/*
+ * Get the float value of "argvars[0]" into "f".
+ * Returns FAIL when the argument is not a Number or Float.
+ */
+ static int
+get_float_arg(argvars, f)
+ typval_T *argvars;
+ float_T *f;
+{
+ if (argvars[0].v_type == VAR_FLOAT)
+ {
+ *f = argvars[0].vval.v_float;
+ return OK;
+ }
+ if (argvars[0].v_type == VAR_NUMBER)
+ {
+ *f = (float_T)argvars[0].vval.v_number;
+ return OK;
+ }
+ EMSG(_("E808: Number or Float required"));
+ return FAIL;
+}
+
+/*
+ * "atan()" function
+ */
+ static void
+f_atan(argvars, rettv)
+ typval_T *argvars;
+ typval_T *rettv;
+{
+ float_T f;
+
+ rettv->v_type = VAR_FLOAT;
+ if (get_float_arg(argvars, &f) == OK)
+ rettv->vval.v_float = atan(f);
+ else
+ rettv->vval.v_float = 0.0;
+}
+#endif
+
/*
* "browse(save, title, initdir, default)" function
*/
@@ -8157,7 +8613,7 @@ f_byteidx(argvars, rettv)
}
rettv->vval.v_number = (varnumber_T)(t - str);
#else
- if (idx <= STRLEN(str))
+ if ((size_t)idx <= STRLEN(str))
rettv->vval.v_number = idx;
#endif
}
@@ -8227,6 +8683,25 @@ f_call(argvars, rettv)
clear_tv(&argv[--argc]);
}
+#ifdef FEAT_FLOAT
+/*
+ * "ceil({float})" function
+ */
+ static void
+f_ceil(argvars, rettv)
+ typval_T *argvars;
+ typval_T *rettv;
+{
+ float_T f;
+
+ rettv->v_type = VAR_FLOAT;
+ if (get_float_arg(argvars, &f) == OK)
+ rettv->vval.v_float = ceil(f);
+ else
+ rettv->vval.v_float = 0.0;
+}
+#endif
+
/*
* "changenr()" function
*/
@@ -8487,6 +8962,25 @@ f_copy(argvars, rettv)
item_copy(&argvars[0], rettv, FALSE, 0);
}
+#ifdef FEAT_FLOAT
+/*
+ * "cos()" function
+ */
+ static void
+f_cos(argvars, rettv)
+ typval_T *argvars;
+ typval_T *rettv;
+{
+ float_T f;
+
+ rettv->v_type = VAR_FLOAT;
+ if (get_float_arg(argvars, &f) == OK)
+ rettv->vval.v_float = cos(f);
+ else
+ rettv->vval.v_float = 0.0;
+}
+#endif
+
/*
* "count()" function
*/
@@ -8802,6 +9296,11 @@ f_empty(argvars, rettv)
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;
@@ -9466,6 +9965,48 @@ f_findfile(argvars, rettv)
findfilendir(argvars, rettv, FINDFILE_FILE);
}
+#ifdef FEAT_FLOAT
+/*
+ * "float2nr({float})" function
+ */
+ static void
+f_float2nr(argvars, rettv)
+ typval_T *argvars;
+ typval_T *rettv;
+{
+ float_T f;
+
+ if (get_float_arg(argvars, &f) == OK)
+ {
+ if (f < -0x7fffffff)
+ rettv->vval.v_number = -0x7fffffff;
+ else if (f > 0x7fffffff)
+ rettv->vval.v_number = 0x7fffffff;
+ else
+ rettv->vval.v_number = (varnumber_T)f;
+ }
+ else
+ rettv->vval.v_number = 0;
+}
+
+/*
+ * "floor({float})" function
+ */
+ static void
+f_floor(argvars, rettv)
+ typval_T *argvars;
+ typval_T *rettv;
+{
+ float_T f;
+
+ rettv->v_type = VAR_FLOAT;
+ if (get_float_arg(argvars, &f) == OK)
+ rettv->vval.v_float = floor(f);
+ else
+ rettv->vval.v_float = 0.0;
+}
+#endif
+
/*
* "fnameescape({string})" function
*/
@@ -10600,7 +11141,7 @@ f_getwinposy(argvars, rettv)
}
/*
- * Find window specifed by "vp" in tabpage "tp".
+ * Find window specified by "vp" in tabpage "tp".
*/
static win_T *
find_win_by_nr(vp, tp)
@@ -10892,6 +11433,9 @@ f_has(argvars, rettv)
#ifdef FEAT_FIND_ID
"find_in_path",
#endif
+#ifdef FEAT_FLOAT
+ "float",
+#endif
#ifdef FEAT_FOLDING
"folding",
#endif
@@ -11002,6 +11546,9 @@ f_has(argvars, rettv)
# ifdef FEAT_MOUSE_PTERM
"mouse_pterm",
# endif
+# ifdef FEAT_SYSMOUSE
+ "mouse_sysmouse",
+# endif
# ifdef FEAT_MOUSE_XTERM
"mouse_xterm",
# endif
@@ -11813,7 +12360,7 @@ f_inputsave(argvars, rettv)
typval_T *argvars;
typval_T *rettv;
{
- /* Add an entry to the stack of typehead storage. */
+ /* Add an entry to the stack of typeahead storage. */
if (ga_grow(&ga_userinput, 1) == OK)
{
save_typeahead((tasave_T *)(ga_userinput.ga_data)
@@ -12345,6 +12892,25 @@ get_maparg(argvars, rettv, exact)