aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/eval.c')
-rw-r--r--src/nvim/eval.c216
1 files changed, 58 insertions, 158 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index ed0b6290dc..48f9faa777 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -300,7 +300,6 @@ static ufunc_T dumuf;
#define FUNCARG(fp, j) ((char_u **)(fp->uf_args.ga_data))[j]
#define FUNCLINE(fp, j) ((char_u **)(fp->uf_lines.ga_data))[j]
-#define MAX_FUNC_ARGS 20 /* maximum number of function arguments */
#define VAR_SHORT_LEN 20 /* short variable name length */
#define FIXVAR_CNT 12 /* number of fixed variables */
@@ -6973,7 +6972,7 @@ get_func_tv (
* Return FAIL when the function can't be called, OK otherwise.
* Also returns OK when an error was encountered while executing the function.
*/
-static int
+int
call_func (
char_u *funcname, /* name of the function */
int len, /* length of "name" */
@@ -7194,7 +7193,7 @@ static int non_zero_arg(typval_T *argvars)
* 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(typval_T *argvars, float_T *f)
+static inline int get_float_arg(typval_T *argvars, float_T *f)
{
if (argvars[0].v_type == VAR_FLOAT) {
*f = argvars[0].vval.v_float;
@@ -7208,14 +7207,34 @@ static int get_float_arg(typval_T *argvars, float_T *f)
return FAIL;
}
+// Apply a floating point C function on a typval with one float_T.
+//
+// Some versions of glibc on i386 have an optimization that makes it harder to
+// call math functions indirectly from inside an inlined function, causing
+// compile-time errors. Avoid `inline` in that case. #3072
+#ifndef ARCH_32
+inline
+#endif
+static void float_op_wrapper(typval_T *argvars, typval_T *rettv,
+ float_T (*function)(float_T))
+{
+ float_T f;
+
+ rettv->v_type = VAR_FLOAT;
+ if (get_float_arg(argvars, &f) == OK) {
+ rettv->vval.v_float = function(f);
+ } else {
+ rettv->vval.v_float = 0.0;
+ }
+}
+
/*
* "abs(expr)" function
*/
static void f_abs(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);
+ float_op_wrapper(argvars, rettv, &fabs);
} else {
varnumber_T n;
int error = FALSE;
@@ -7235,13 +7254,7 @@ static void f_abs(typval_T *argvars, typval_T *rettv)
*/
static void f_acos(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 = acos(f);
- else
- rettv->vval.v_float = 0.0;
+ float_op_wrapper(argvars, rettv, &acos);
}
/*
@@ -7395,13 +7408,7 @@ static void f_argv(typval_T *argvars, typval_T *rettv)
*/
static void f_asin(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 = asin(f);
- else
- rettv->vval.v_float = 0.0;
+ float_op_wrapper(argvars, rettv, &asin);
}
/*
@@ -7409,13 +7416,7 @@ static void f_asin(typval_T *argvars, typval_T *rettv)
*/
static void f_atan(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;
+ float_op_wrapper(argvars, rettv, &atan);
}
/*
@@ -7744,13 +7745,7 @@ static void f_call(typval_T *argvars, typval_T *rettv)
*/
static void f_ceil(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;
+ float_op_wrapper(argvars, rettv, &ceil);
}
/*
@@ -7954,13 +7949,7 @@ static void f_copy(typval_T *argvars, typval_T *rettv)
*/
static void f_cos(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;
+ float_op_wrapper(argvars, rettv, &cos);
}
/*
@@ -7968,13 +7957,7 @@ static void f_cos(typval_T *argvars, typval_T *rettv)
*/
static void f_cosh(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 = cosh(f);
- else
- rettv->vval.v_float = 0.0;
+ float_op_wrapper(argvars, rettv, &cosh);
}
/*
@@ -8373,13 +8356,7 @@ static void f_exists(typval_T *argvars, typval_T *rettv)
*/
static void f_exp(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 = exp(f);
- else
- rettv->vval.v_float = 0.0;
+ float_op_wrapper(argvars, rettv, &exp);
}
/*
@@ -8858,13 +8835,7 @@ static void f_float2nr(typval_T *argvars, typval_T *rettv)
*/
static void f_floor(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;
+ float_op_wrapper(argvars, rettv, &floor);
}
/*
@@ -10042,9 +10013,7 @@ static void f_has(typval_T *argvars, typval_T *rettv)
#endif
"arabic",
"autocmd",
-#if defined(FEAT_BROWSE) && (defined(USE_FILE_CHOOSER) \
- || defined(FEAT_GUI_W32) \
- || defined(FEAT_GUI_MOTIF))
+#ifdef FEAT_BROWSE
"browsefilter",
#endif
"byte_offset",
@@ -11421,13 +11390,7 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact)
*/
static void f_log(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 = log(f);
- else
- rettv->vval.v_float = 0.0;
+ float_op_wrapper(argvars, rettv, &log);
}
/*
@@ -11435,13 +11398,7 @@ static void f_log(typval_T *argvars, typval_T *rettv)
*/
static void f_log10(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 = log10(f);
- else
- rettv->vval.v_float = 0.0;
+ float_op_wrapper(argvars, rettv, &log10);
}
@@ -11833,33 +11790,6 @@ static void f_min(typval_T *argvars, typval_T *rettv)
max_min(argvars, rettv, FALSE);
}
-
-/*
- * Create the directory in which "dir" is located, and higher levels when
- * needed.
- */
-static int mkdir_recurse(char_u *dir, int prot)
-{
- char_u *p;
- char_u *updir;
- int r = FAIL;
-
- /* Get end of directory name in "dir".
- * We're done when it's "/" or "c:/". */
- p = path_tail_with_sep(dir);
- if (p <= get_past_head(dir))
- return OK;
-
- /* If the directory exists we're done. Otherwise: create it.*/
- updir = vim_strnsave(dir, (int)(p - dir));
- if (os_isdir(updir))
- r = OK;
- else if (mkdir_recurse(updir, prot) == OK)
- r = vim_mkdir_emsg(updir, prot);
- xfree(updir);
- return r;
-}
-
/*
* "mkdir()" function
*/
@@ -11884,8 +11814,19 @@ static void f_mkdir(typval_T *argvars, typval_T *rettv)
if (argvars[1].v_type != VAR_UNKNOWN) {
if (argvars[2].v_type != VAR_UNKNOWN)
prot = get_tv_number_chk(&argvars[2], NULL);
- if (prot != -1 && STRCMP(get_tv_string(&argvars[1]), "p") == 0)
- mkdir_recurse(dir, prot);
+ if (prot != -1 && STRCMP(get_tv_string(&argvars[1]), "p") == 0) {
+ char *failed_dir;
+ int ret = os_mkdir_recurse((char *) dir, prot, &failed_dir);
+ if (ret != 0) {
+ EMSG3(_(e_mkdir), failed_dir, os_strerror(ret));
+ xfree(failed_dir);
+ rettv->vval.v_number = FAIL;
+ return;
+ } else {
+ rettv->vval.v_number = OK;
+ return;
+ }
+ }
}
rettv->vval.v_number = prot == -1 ? FAIL : vim_mkdir_emsg(dir, prot);
}
@@ -13356,7 +13297,7 @@ static void f_resolve(typval_T *argvars, typval_T *rettv)
#endif
p = get_tv_string(&argvars[0]);
-#ifdef FEAT_SHORTCUT
+#ifdef WIN32
{
char_u *v = NULL;
@@ -13692,13 +13633,7 @@ theend:
*/
static void f_round(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 = round(f);
- else
- rettv->vval.v_float = 0.0;
+ float_op_wrapper(argvars, rettv, &round);
}
// "rpcnotify()" function
@@ -14829,13 +14764,7 @@ static void f_simplify(typval_T *argvars, typval_T *rettv)
*/
static void f_sin(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 = sin(f);
- else
- rettv->vval.v_float = 0.0;
+ float_op_wrapper(argvars, rettv, &sin);
}
/*
@@ -14843,13 +14772,7 @@ static void f_sin(typval_T *argvars, typval_T *rettv)
*/
static void f_sinh(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 = sinh(f);
- else
- rettv->vval.v_float = 0.0;
+ float_op_wrapper(argvars, rettv, &sinh);
}
/// struct used in the array that's given to qsort()
@@ -15320,13 +15243,7 @@ static void f_split(typval_T *argvars, typval_T *rettv)
*/
static void f_sqrt(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 = sqrt(f);
- else
- rettv->vval.v_float = 0.0;
+ float_op_wrapper(argvars, rettv, &sqrt);
}
/*
@@ -15699,6 +15616,8 @@ static void f_synIDattr(typval_T *argvars, typval_T *rettv)
modec = TOLOWER_ASC(mode[0]);
if (modec != 'c' && modec != 'g')
modec = 0; /* replace invalid with current */
+ } else if (ui_rgb_attached()) {
+ modec = 'g';
} else {
modec = 'c';
}
@@ -16210,13 +16129,7 @@ static void f_test(typval_T *argvars, typval_T *rettv)
*/
static void f_tan(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 = tan(f);
- else
- rettv->vval.v_float = 0.0;
+ float_op_wrapper(argvars, rettv, &tan);
}
/*
@@ -16224,13 +16137,7 @@ static void f_tan(typval_T *argvars, typval_T *rettv)
*/
static void f_tanh(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 = tanh(f);
- else
- rettv->vval.v_float = 0.0;
+ float_op_wrapper(argvars, rettv, &tanh);
}
/*
@@ -16378,14 +16285,7 @@ error:
*/
static void f_trunc(typval_T *argvars, typval_T *rettv)
{
- float_T f;
-
- rettv->v_type = VAR_FLOAT;
- if (get_float_arg(argvars, &f) == OK)
- /* trunc() is not in C90, use floor() or ceil() instead. */
- rettv->vval.v_float = f > 0 ? floor(f) : ceil(f);
- else
- rettv->vval.v_float = 0.0;
+ float_op_wrapper(argvars, rettv, &trunc);
}
/*