mirror of
				https://github.com/neovim/neovim.git
				synced 2025-11-04 01:34:25 +00:00 
			
		
		
		
	vim-patch:8.2.1047: Vim9: script cannot use line continuation like :def function
Problem:    Vim9: script cannot use line continuation like in a :def function.
Solution:   Pass the getline function pointer to the eval() functions.  Use it
            for addition and multiplication operators.
5409f5d8c9
Omit source_nextline() and eval_next_non_blank(): Vim9 script only.
N/A patches for version.c:
vim-patch:8.2.1048: build failure without the eval feature
Problem:    Build failure without the eval feature.
Solution:   Add dummy typedef.
9d40c63c7d
vim-patch:8.2.1052: build failure with older compilers
Problem:    Build failure with older compilers.
Solution:   Move declaration to start of block.
7acde51832
Co-authored-by: Bram Moolenaar <Bram@vim.org>
			
			
This commit is contained in:
		@@ -172,7 +172,7 @@ Object nvim_eval(String expr, Error *err)
 | 
				
			|||||||
  int ok;
 | 
					  int ok;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  TRY_WRAP(err, {
 | 
					  TRY_WRAP(err, {
 | 
				
			||||||
    ok = eval0(expr.data, &rettv, NULL, EVAL_EVALUATE);
 | 
					    ok = eval0(expr.data, &rettv, NULL, &EVALARG_EVALUATE);
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (!ERROR_SET(err)) {
 | 
					  if (!ERROR_SET(err)) {
 | 
				
			||||||
@@ -290,7 +290,7 @@ Object nvim_call_dict_function(Object dict, String fn, Array args, Error *err)
 | 
				
			|||||||
  switch (dict.type) {
 | 
					  switch (dict.type) {
 | 
				
			||||||
  case kObjectTypeString:
 | 
					  case kObjectTypeString:
 | 
				
			||||||
    try_start();
 | 
					    try_start();
 | 
				
			||||||
    if (eval0(dict.data.string.data, &rettv, NULL, EVAL_EVALUATE) == FAIL) {
 | 
					    if (eval0(dict.data.string.data, &rettv, NULL, &EVALARG_EVALUATE) == FAIL) {
 | 
				
			||||||
      api_set_error(err, kErrorTypeException,
 | 
					      api_set_error(err, kErrorTypeException,
 | 
				
			||||||
                    "Failed to evaluate dict expression");
 | 
					                    "Failed to evaluate dict expression");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										148
									
								
								src/nvim/eval.c
									
									
									
									
									
								
							
							
						
						
									
										148
									
								
								src/nvim/eval.c
									
									
									
									
									
								
							@@ -706,7 +706,7 @@ int eval_to_bool(char *arg, bool *error, char **nextcmd, int skip)
 | 
				
			|||||||
  if (skip) {
 | 
					  if (skip) {
 | 
				
			||||||
    emsg_skip++;
 | 
					    emsg_skip++;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (eval0(arg, &tv, nextcmd, skip ? 0 : EVAL_EVALUATE) == FAIL) {
 | 
					  if (eval0(arg, &tv, nextcmd, skip ? NULL : &EVALARG_EVALUATE) == FAIL) {
 | 
				
			||||||
    *error = true;
 | 
					    *error = true;
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    *error = false;
 | 
					    *error = false;
 | 
				
			||||||
@@ -730,7 +730,7 @@ static int eval1_emsg(char **arg, typval_T *rettv, bool evaluate)
 | 
				
			|||||||
  const int did_emsg_before = did_emsg;
 | 
					  const int did_emsg_before = did_emsg;
 | 
				
			||||||
  const int called_emsg_before = called_emsg;
 | 
					  const int called_emsg_before = called_emsg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const int ret = eval1(arg, rettv, evaluate ? EVAL_EVALUATE : 0);
 | 
					  const int ret = eval1(arg, rettv, evaluate ? &EVALARG_EVALUATE : NULL);
 | 
				
			||||||
  if (ret == FAIL) {
 | 
					  if (ret == FAIL) {
 | 
				
			||||||
    // Report the invalid expression unless the expression evaluation has
 | 
					    // Report the invalid expression unless the expression evaluation has
 | 
				
			||||||
    // been cancelled due to an aborting error, an interrupt, or an
 | 
					    // been cancelled due to an aborting error, an interrupt, or an
 | 
				
			||||||
@@ -832,7 +832,8 @@ char *eval_to_string_skip(const char *arg, const char **nextcmd, const bool skip
 | 
				
			|||||||
  if (skip) {
 | 
					  if (skip) {
 | 
				
			||||||
    emsg_skip++;
 | 
					    emsg_skip++;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (eval0((char *)arg, &tv, (char **)nextcmd, skip ? 0 : EVAL_EVALUATE) == FAIL || skip) {
 | 
					  if (eval0((char *)arg, &tv, (char **)nextcmd, skip ? NULL : &EVALARG_EVALUATE)
 | 
				
			||||||
 | 
					      == FAIL || skip) {
 | 
				
			||||||
    retval = NULL;
 | 
					    retval = NULL;
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    retval = xstrdup(tv_get_string(&tv));
 | 
					    retval = xstrdup(tv_get_string(&tv));
 | 
				
			||||||
@@ -853,7 +854,7 @@ int skip_expr(char **pp)
 | 
				
			|||||||
  typval_T rettv;
 | 
					  typval_T rettv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  *pp = skipwhite(*pp);
 | 
					  *pp = skipwhite(*pp);
 | 
				
			||||||
  return eval1(pp, &rettv, 0);
 | 
					  return eval1(pp, &rettv, NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Top level evaluation function, returning a string.
 | 
					/// Top level evaluation function, returning a string.
 | 
				
			||||||
@@ -868,7 +869,7 @@ char *eval_to_string(char *arg, char **nextcmd, bool convert)
 | 
				
			|||||||
  char *retval;
 | 
					  char *retval;
 | 
				
			||||||
  garray_T ga;
 | 
					  garray_T ga;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (eval0(arg, &tv, nextcmd, EVAL_EVALUATE) == FAIL) {
 | 
					  if (eval0(arg, &tv, nextcmd, &EVALARG_EVALUATE) == FAIL) {
 | 
				
			||||||
    retval = NULL;
 | 
					    retval = NULL;
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    if (convert && tv.v_type == VAR_LIST) {
 | 
					    if (convert && tv.v_type == VAR_LIST) {
 | 
				
			||||||
@@ -929,7 +930,7 @@ varnumber_T eval_to_number(char *expr)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  emsg_off++;
 | 
					  emsg_off++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (eval1(&p, &rettv, EVAL_EVALUATE) == FAIL) {
 | 
					  if (eval1(&p, &rettv, &EVALARG_EVALUATE) == FAIL) {
 | 
				
			||||||
    retval = -1;
 | 
					    retval = -1;
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    retval = tv_get_number_chk(&rettv, NULL);
 | 
					    retval = tv_get_number_chk(&rettv, NULL);
 | 
				
			||||||
@@ -947,7 +948,7 @@ varnumber_T eval_to_number(char *expr)
 | 
				
			|||||||
typval_T *eval_expr(char *arg)
 | 
					typval_T *eval_expr(char *arg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  typval_T *tv = xmalloc(sizeof(*tv));
 | 
					  typval_T *tv = xmalloc(sizeof(*tv));
 | 
				
			||||||
  if (eval0(arg, tv, NULL, EVAL_EVALUATE) == FAIL) {
 | 
					  if (eval0(arg, tv, NULL, &EVALARG_EVALUATE) == FAIL) {
 | 
				
			||||||
    XFREE_CLEAR(tv);
 | 
					    XFREE_CLEAR(tv);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return tv;
 | 
					  return tv;
 | 
				
			||||||
@@ -1024,7 +1025,7 @@ list_T *eval_spell_expr(char *badword, char *expr)
 | 
				
			|||||||
    emsg_off++;
 | 
					    emsg_off++;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (eval1(&p, &rettv, EVAL_EVALUATE) == OK) {
 | 
					  if (eval1(&p, &rettv, &EVALARG_EVALUATE) == OK) {
 | 
				
			||||||
    if (rettv.v_type != VAR_LIST) {
 | 
					    if (rettv.v_type != VAR_LIST) {
 | 
				
			||||||
      tv_clear(&rettv);
 | 
					      tv_clear(&rettv);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
@@ -1171,7 +1172,7 @@ int eval_foldexpr(char *arg, int *cp)
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
  textlock++;
 | 
					  textlock++;
 | 
				
			||||||
  *cp = NUL;
 | 
					  *cp = NUL;
 | 
				
			||||||
  if (eval0(arg, &tv, NULL, EVAL_EVALUATE) == FAIL) {
 | 
					  if (eval0(arg, &tv, NULL, &EVALARG_EVALUATE) == FAIL) {
 | 
				
			||||||
    retval = 0;
 | 
					    retval = 0;
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    // If the result is a number, just return the number.
 | 
					    // If the result is a number, just return the number.
 | 
				
			||||||
@@ -1346,7 +1347,7 @@ char *get_lval(char *const name, typval_T *const rettv, lval_T *const lp, const
 | 
				
			|||||||
        empty1 = true;
 | 
					        empty1 = true;
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        empty1 = false;
 | 
					        empty1 = false;
 | 
				
			||||||
        if (eval1(&p, &var1, EVAL_EVALUATE) == FAIL) {  // Recursive!
 | 
					        if (eval1(&p, &var1, &EVALARG_EVALUATE) == FAIL) {  // Recursive!
 | 
				
			||||||
          return NULL;
 | 
					          return NULL;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (!tv_check_str(&var1)) {
 | 
					        if (!tv_check_str(&var1)) {
 | 
				
			||||||
@@ -1381,7 +1382,7 @@ char *get_lval(char *const name, typval_T *const rettv, lval_T *const lp, const
 | 
				
			|||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
          lp->ll_empty2 = false;
 | 
					          lp->ll_empty2 = false;
 | 
				
			||||||
          // Recursive!
 | 
					          // Recursive!
 | 
				
			||||||
          if (eval1(&p, &var2, EVAL_EVALUATE) == FAIL) {
 | 
					          if (eval1(&p, &var2, &EVALARG_EVALUATE) == FAIL) {
 | 
				
			||||||
            tv_clear(&var1);
 | 
					            tv_clear(&var1);
 | 
				
			||||||
            return NULL;
 | 
					            return NULL;
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
@@ -1784,6 +1785,7 @@ void *eval_for_line(const char *arg, bool *errp, char **nextcmdp, int skip)
 | 
				
			|||||||
  typval_T tv;
 | 
					  typval_T tv;
 | 
				
			||||||
  list_T *l;
 | 
					  list_T *l;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  evalarg_T evalarg = { .eval_flags = skip ? 0 : EVAL_EVALUATE };
 | 
				
			||||||
  *errp = true;  // Default: there is an error.
 | 
					  *errp = true;  // Default: there is an error.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  expr = skip_var_list(arg, &fi->fi_varcount, &fi->fi_semicolon);
 | 
					  expr = skip_var_list(arg, &fi->fi_varcount, &fi->fi_semicolon);
 | 
				
			||||||
@@ -1800,7 +1802,7 @@ void *eval_for_line(const char *arg, bool *errp, char **nextcmdp, int skip)
 | 
				
			|||||||
  if (skip) {
 | 
					  if (skip) {
 | 
				
			||||||
    emsg_skip++;
 | 
					    emsg_skip++;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (eval0(skipwhite(expr + 2), &tv, nextcmdp, skip ? 0 : EVAL_EVALUATE) == OK) {
 | 
					  if (eval0(skipwhite(expr + 2), &tv, nextcmdp, &evalarg) == OK) {
 | 
				
			||||||
    *errp = false;
 | 
					    *errp = false;
 | 
				
			||||||
    if (!skip) {
 | 
					    if (!skip) {
 | 
				
			||||||
      if (tv.v_type == VAR_LIST) {
 | 
					      if (tv.v_type == VAR_LIST) {
 | 
				
			||||||
@@ -2225,10 +2227,10 @@ static int eval_func(char **const arg, char *const name, const int name_len, typ
 | 
				
			|||||||
/// Put the result in "rettv" when returning OK and "evaluate" is true.
 | 
					/// Put the result in "rettv" when returning OK and "evaluate" is true.
 | 
				
			||||||
/// Note: "rettv.v_lock" is not set.
 | 
					/// Note: "rettv.v_lock" is not set.
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
/// @param flags  has EVAL_EVALUATE and similar flags.
 | 
					/// @param evalarg  can be NULL, &EVALARG_EVALUATE or a pointer.
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
/// @return OK or FAIL.
 | 
					/// @return OK or FAIL.
 | 
				
			||||||
int eval0(char *arg, typval_T *rettv, char **nextcmd, const int flags)
 | 
					int eval0(char *arg, typval_T *rettv, char **nextcmd, evalarg_T *const evalarg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  int ret;
 | 
					  int ret;
 | 
				
			||||||
  char *p;
 | 
					  char *p;
 | 
				
			||||||
@@ -2237,7 +2239,7 @@ int eval0(char *arg, typval_T *rettv, char **nextcmd, const int flags)
 | 
				
			|||||||
  bool end_error = false;
 | 
					  bool end_error = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  p = skipwhite(arg);
 | 
					  p = skipwhite(arg);
 | 
				
			||||||
  ret = eval1(&p, rettv, flags);
 | 
					  ret = eval1(&p, rettv, evalarg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (ret != FAIL) {
 | 
					  if (ret != FAIL) {
 | 
				
			||||||
    end_error = !ends_excmd(*p);
 | 
					    end_error = !ends_excmd(*p);
 | 
				
			||||||
@@ -2277,20 +2279,20 @@ int eval0(char *arg, typval_T *rettv, char **nextcmd, const int flags)
 | 
				
			|||||||
/// Note: "rettv.v_lock" is not set.
 | 
					/// Note: "rettv.v_lock" is not set.
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
/// @return  OK or FAIL.
 | 
					/// @return  OK or FAIL.
 | 
				
			||||||
int eval1(char **arg, typval_T *rettv, const int flags)
 | 
					int eval1(char **arg, typval_T *rettv, evalarg_T *const evalarg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  typval_T var2;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Get the first variable.
 | 
					  // Get the first variable.
 | 
				
			||||||
  if (eval2(arg, rettv, flags) == FAIL) {
 | 
					  if (eval2(arg, rettv, evalarg) == FAIL) {
 | 
				
			||||||
    return FAIL;
 | 
					    return FAIL;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if ((*arg)[0] == '?') {
 | 
					  if ((*arg)[0] == '?') {
 | 
				
			||||||
    const bool evaluate = flags & EVAL_EVALUATE;
 | 
					    evalarg_T nested_evalarg = evalarg == NULL ? (evalarg_T){ 0 } : *evalarg;
 | 
				
			||||||
 | 
					    const int orig_flags = evalarg == NULL ? 0 : evalarg->eval_flags;
 | 
				
			||||||
 | 
					    const bool evaluate = nested_evalarg.eval_flags & EVAL_EVALUATE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool result = false;
 | 
					    bool result = false;
 | 
				
			||||||
    if (flags & EVAL_EVALUATE) {
 | 
					    if (evaluate) {
 | 
				
			||||||
      bool error = false;
 | 
					      bool error = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (tv_get_number_chk(rettv, &error) != 0) {
 | 
					      if (tv_get_number_chk(rettv, &error) != 0) {
 | 
				
			||||||
@@ -2304,7 +2306,8 @@ int eval1(char **arg, typval_T *rettv, const int flags)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Get the second variable.  Recursive!
 | 
					    // Get the second variable.  Recursive!
 | 
				
			||||||
    *arg = skipwhite(*arg + 1);
 | 
					    *arg = skipwhite(*arg + 1);
 | 
				
			||||||
    if (eval1(arg, rettv, result ? flags : flags & ~EVAL_EVALUATE) == FAIL) {
 | 
					    nested_evalarg.eval_flags = result ? orig_flags : orig_flags & ~EVAL_EVALUATE;
 | 
				
			||||||
 | 
					    if (eval1(arg, rettv, &nested_evalarg) == FAIL) {
 | 
				
			||||||
      return FAIL;
 | 
					      return FAIL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2319,7 +2322,9 @@ int eval1(char **arg, typval_T *rettv, const int flags)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Get the third variable.  Recursive!
 | 
					    // Get the third variable.  Recursive!
 | 
				
			||||||
    *arg = skipwhite(*arg + 1);
 | 
					    *arg = skipwhite(*arg + 1);
 | 
				
			||||||
    if (eval1(arg, &var2, !result ? flags : flags & ~EVAL_EVALUATE) == FAIL) {
 | 
					    typval_T var2;
 | 
				
			||||||
 | 
					    nested_evalarg.eval_flags = !result ? orig_flags : orig_flags & ~EVAL_EVALUATE;
 | 
				
			||||||
 | 
					    if (eval1(arg, &var2, &nested_evalarg) == FAIL) {
 | 
				
			||||||
      if (evaluate && result) {
 | 
					      if (evaluate && result) {
 | 
				
			||||||
        tv_clear(rettv);
 | 
					        tv_clear(rettv);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@@ -2340,13 +2345,13 @@ int eval1(char **arg, typval_T *rettv, const int flags)
 | 
				
			|||||||
/// "arg" is advanced to the next non-white after the recognized expression.
 | 
					/// "arg" is advanced to the next non-white after the recognized expression.
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
/// @return  OK or FAIL.
 | 
					/// @return  OK or FAIL.
 | 
				
			||||||
static int eval2(char **arg, typval_T *rettv, const int flags)
 | 
					static int eval2(char **arg, typval_T *rettv, evalarg_T *const evalarg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  typval_T var2;
 | 
					  typval_T var2;
 | 
				
			||||||
  bool error = false;
 | 
					  bool error = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Get the first variable.
 | 
					  // Get the first variable.
 | 
				
			||||||
  if (eval3(arg, rettv, flags) == FAIL) {
 | 
					  if (eval3(arg, rettv, evalarg) == FAIL) {
 | 
				
			||||||
    return FAIL;
 | 
					    return FAIL;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2354,7 +2359,9 @@ static int eval2(char **arg, typval_T *rettv, const int flags)
 | 
				
			|||||||
  bool first = true;
 | 
					  bool first = true;
 | 
				
			||||||
  bool result = false;
 | 
					  bool result = false;
 | 
				
			||||||
  while ((*arg)[0] == '|' && (*arg)[1] == '|') {
 | 
					  while ((*arg)[0] == '|' && (*arg)[1] == '|') {
 | 
				
			||||||
    const bool evaluate = flags & EVAL_EVALUATE;
 | 
					    evalarg_T nested_evalarg = evalarg == NULL ? (evalarg_T){ 0 } : *evalarg;
 | 
				
			||||||
 | 
					    const int orig_flags = evalarg == NULL ? 0 : evalarg->eval_flags;
 | 
				
			||||||
 | 
					    const bool evaluate = orig_flags & EVAL_EVALUATE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (evaluate && first) {
 | 
					    if (evaluate && first) {
 | 
				
			||||||
      if (tv_get_number_chk(rettv, &error) != 0) {
 | 
					      if (tv_get_number_chk(rettv, &error) != 0) {
 | 
				
			||||||
@@ -2369,7 +2376,8 @@ static int eval2(char **arg, typval_T *rettv, const int flags)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Get the second variable.
 | 
					    // Get the second variable.
 | 
				
			||||||
    *arg = skipwhite(*arg + 2);
 | 
					    *arg = skipwhite(*arg + 2);
 | 
				
			||||||
    if (eval3(arg, &var2, !result ? flags : flags & ~EVAL_EVALUATE) == FAIL) {
 | 
					    nested_evalarg.eval_flags = !result ? orig_flags : orig_flags & ~EVAL_EVALUATE;
 | 
				
			||||||
 | 
					    if (eval3(arg, &var2, &nested_evalarg) == FAIL) {
 | 
				
			||||||
      return FAIL;
 | 
					      return FAIL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2399,13 +2407,13 @@ static int eval2(char **arg, typval_T *rettv, const int flags)
 | 
				
			|||||||
///             `arg` is advanced to the next non-white after the recognized expression.
 | 
					///             `arg` is advanced to the next non-white after the recognized expression.
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
/// @return  OK or FAIL.
 | 
					/// @return  OK or FAIL.
 | 
				
			||||||
static int eval3(char **arg, typval_T *rettv, const int flags)
 | 
					static int eval3(char **arg, typval_T *rettv, evalarg_T *const evalarg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  typval_T var2;
 | 
					  typval_T var2;
 | 
				
			||||||
  bool error = false;
 | 
					  bool error = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Get the first variable.
 | 
					  // Get the first variable.
 | 
				
			||||||
  if (eval4(arg, rettv, flags) == FAIL) {
 | 
					  if (eval4(arg, rettv, evalarg) == FAIL) {
 | 
				
			||||||
    return FAIL;
 | 
					    return FAIL;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2413,7 +2421,9 @@ static int eval3(char **arg, typval_T *rettv, const int flags)
 | 
				
			|||||||
  bool first = true;
 | 
					  bool first = true;
 | 
				
			||||||
  bool result = true;
 | 
					  bool result = true;
 | 
				
			||||||
  while ((*arg)[0] == '&' && (*arg)[1] == '&') {
 | 
					  while ((*arg)[0] == '&' && (*arg)[1] == '&') {
 | 
				
			||||||
    const bool evaluate = flags & EVAL_EVALUATE;
 | 
					    evalarg_T nested_evalarg = evalarg == NULL ? (evalarg_T){ 0 } : *evalarg;
 | 
				
			||||||
 | 
					    const int orig_flags = evalarg == NULL ? 0 : evalarg->eval_flags;
 | 
				
			||||||
 | 
					    const bool evaluate = orig_flags & EVAL_EVALUATE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (evaluate && first) {
 | 
					    if (evaluate && first) {
 | 
				
			||||||
      if (tv_get_number_chk(rettv, &error) == 0) {
 | 
					      if (tv_get_number_chk(rettv, &error) == 0) {
 | 
				
			||||||
@@ -2428,7 +2438,8 @@ static int eval3(char **arg, typval_T *rettv, const int flags)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Get the second variable.
 | 
					    // Get the second variable.
 | 
				
			||||||
    *arg = skipwhite(*arg + 2);
 | 
					    *arg = skipwhite(*arg + 2);
 | 
				
			||||||
    if (eval4(arg, &var2, result ? flags : flags & ~EVAL_EVALUATE) == FAIL) {
 | 
					    nested_evalarg.eval_flags = result ? orig_flags : orig_flags & ~EVAL_EVALUATE;
 | 
				
			||||||
 | 
					    if (eval4(arg, &var2, &nested_evalarg) == FAIL) {
 | 
				
			||||||
      return FAIL;
 | 
					      return FAIL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2467,7 +2478,7 @@ static int eval3(char **arg, typval_T *rettv, const int flags)
 | 
				
			|||||||
/// "arg" is advanced to the next non-white after the recognized expression.
 | 
					/// "arg" is advanced to the next non-white after the recognized expression.
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
/// @return  OK or FAIL.
 | 
					/// @return  OK or FAIL.
 | 
				
			||||||
static int eval4(char **arg, typval_T *rettv, const int flags)
 | 
					static int eval4(char **arg, typval_T *rettv, evalarg_T *const evalarg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  typval_T var2;
 | 
					  typval_T var2;
 | 
				
			||||||
  char *p;
 | 
					  char *p;
 | 
				
			||||||
@@ -2475,7 +2486,7 @@ static int eval4(char **arg, typval_T *rettv, const int flags)
 | 
				
			|||||||
  int len = 2;
 | 
					  int len = 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Get the first variable.
 | 
					  // Get the first variable.
 | 
				
			||||||
  if (eval5(arg, rettv, flags) == FAIL) {
 | 
					  if (eval5(arg, rettv, evalarg) == FAIL) {
 | 
				
			||||||
    return FAIL;
 | 
					    return FAIL;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2539,11 +2550,11 @@ static int eval4(char **arg, typval_T *rettv, const int flags)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Get the second variable.
 | 
					    // Get the second variable.
 | 
				
			||||||
    *arg = skipwhite(p + len);
 | 
					    *arg = skipwhite(p + len);
 | 
				
			||||||
    if (eval5(arg, &var2, flags) == FAIL) {
 | 
					    if (eval5(arg, &var2, evalarg) == FAIL) {
 | 
				
			||||||
      tv_clear(rettv);
 | 
					      tv_clear(rettv);
 | 
				
			||||||
      return FAIL;
 | 
					      return FAIL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (flags & EVAL_EVALUATE) {
 | 
					    if (evalarg != NULL && (evalarg->eval_flags & EVAL_EVALUATE)) {
 | 
				
			||||||
      const int ret = typval_compare(rettv, &var2, type, ic);
 | 
					      const int ret = typval_compare(rettv, &var2, type, ic);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      tv_clear(&var2);
 | 
					      tv_clear(&var2);
 | 
				
			||||||
@@ -2597,27 +2608,25 @@ static int eval_addlist(typval_T *tv1, typval_T *tv2)
 | 
				
			|||||||
///             `arg` is advanced to the next non-white after the recognized expression.
 | 
					///             `arg` is advanced to the next non-white after the recognized expression.
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
/// @return  OK or FAIL.
 | 
					/// @return  OK or FAIL.
 | 
				
			||||||
static int eval5(char **arg, typval_T *rettv, const int flags)
 | 
					static int eval5(char **arg, typval_T *rettv, evalarg_T *const evalarg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  typval_T var2;
 | 
					  const bool evaluate = evalarg == NULL ? 0 : (evalarg->eval_flags & EVAL_EVALUATE);
 | 
				
			||||||
  varnumber_T n1, n2;
 | 
					 | 
				
			||||||
  float_T f1 = 0, f2 = 0;
 | 
					 | 
				
			||||||
  char *p;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Get the first variable.
 | 
					  // Get the first variable.
 | 
				
			||||||
  if (eval6(arg, rettv, flags, false) == FAIL) {
 | 
					  if (eval6(arg, rettv, evalarg, false) == FAIL) {
 | 
				
			||||||
    return FAIL;
 | 
					    return FAIL;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Repeat computing, until no '+', '-' or '.' is following.
 | 
					  // Repeat computing, until no '+', '-' or '.' is following.
 | 
				
			||||||
  for (;;) {
 | 
					  for (;;) {
 | 
				
			||||||
    int op = (uint8_t)(**arg);
 | 
					    int op = (uint8_t)(**arg);
 | 
				
			||||||
    if (op != '+' && op != '-' && op != '.') {
 | 
					    bool concat = op == '.';
 | 
				
			||||||
 | 
					    if (op != '+' && op != '-' && !concat) {
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ((op != '+' || (rettv->v_type != VAR_LIST && rettv->v_type != VAR_BLOB))
 | 
					    if ((op != '+' || (rettv->v_type != VAR_LIST && rettv->v_type != VAR_BLOB))
 | 
				
			||||||
        && (op == '.' || rettv->v_type != VAR_FLOAT) && (flags & EVAL_EVALUATE)) {
 | 
					        && (op == '.' || rettv->v_type != VAR_FLOAT) && evaluate) {
 | 
				
			||||||
      // For "list + ...", an illegal use of the first operand as
 | 
					      // For "list + ...", an illegal use of the first operand as
 | 
				
			||||||
      // a number cannot be determined before evaluating the 2nd
 | 
					      // a number cannot be determined before evaluating the 2nd
 | 
				
			||||||
      // operand: if this is also a list, all is ok.
 | 
					      // operand: if this is also a list, all is ok.
 | 
				
			||||||
@@ -2636,12 +2645,13 @@ static int eval5(char **arg, typval_T *rettv, const int flags)
 | 
				
			|||||||
      (*arg)++;
 | 
					      (*arg)++;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    *arg = skipwhite(*arg + 1);
 | 
					    *arg = skipwhite(*arg + 1);
 | 
				
			||||||
    if (eval6(arg, &var2, flags, op == '.') == FAIL) {
 | 
					    typval_T var2;
 | 
				
			||||||
 | 
					    if (eval6(arg, &var2, evalarg, op == '.') == FAIL) {
 | 
				
			||||||
      tv_clear(rettv);
 | 
					      tv_clear(rettv);
 | 
				
			||||||
      return FAIL;
 | 
					      return FAIL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (flags & EVAL_EVALUATE) {
 | 
					    if (evaluate) {
 | 
				
			||||||
      // Compute the result.
 | 
					      // Compute the result.
 | 
				
			||||||
      if (op == '.') {
 | 
					      if (op == '.') {
 | 
				
			||||||
        char buf1[NUMBUFLEN];
 | 
					        char buf1[NUMBUFLEN];
 | 
				
			||||||
@@ -2654,7 +2664,7 @@ static int eval5(char **arg, typval_T *rettv, const int flags)
 | 
				
			|||||||
          tv_clear(&var2);
 | 
					          tv_clear(&var2);
 | 
				
			||||||
          return FAIL;
 | 
					          return FAIL;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        p = concat_str(s1, s2);
 | 
					        char *p = concat_str(s1, s2);
 | 
				
			||||||
        tv_clear(rettv);
 | 
					        tv_clear(rettv);
 | 
				
			||||||
        rettv->v_type = VAR_STRING;
 | 
					        rettv->v_type = VAR_STRING;
 | 
				
			||||||
        rettv->vval.v_string = p;
 | 
					        rettv->vval.v_string = p;
 | 
				
			||||||
@@ -2666,6 +2676,8 @@ static int eval5(char **arg, typval_T *rettv, const int flags)
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        bool error = false;
 | 
					        bool error = false;
 | 
				
			||||||
 | 
					        varnumber_T n1, n2;
 | 
				
			||||||
 | 
					        float_T f1 = 0, f2 = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (rettv->v_type == VAR_FLOAT) {
 | 
					        if (rettv->v_type == VAR_FLOAT) {
 | 
				
			||||||
          f1 = rettv->vval.v_float;
 | 
					          f1 = rettv->vval.v_float;
 | 
				
			||||||
@@ -2738,7 +2750,7 @@ static int eval5(char **arg, typval_T *rettv, const int flags)
 | 
				
			|||||||
/// @param[in]  want_string  True if "." is string_concatenation, otherwise
 | 
					/// @param[in]  want_string  True if "." is string_concatenation, otherwise
 | 
				
			||||||
///                          float
 | 
					///                          float
 | 
				
			||||||
/// @return  OK or FAIL.
 | 
					/// @return  OK or FAIL.
 | 
				
			||||||
static int eval6(char **arg, typval_T *rettv, const int flags, bool want_string)
 | 
					static int eval6(char **arg, typval_T *rettv, evalarg_T *const evalarg, bool want_string)
 | 
				
			||||||
  FUNC_ATTR_NO_SANITIZE_UNDEFINED
 | 
					  FUNC_ATTR_NO_SANITIZE_UNDEFINED
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  typval_T var2;
 | 
					  typval_T var2;
 | 
				
			||||||
@@ -2749,18 +2761,19 @@ static int eval6(char **arg, typval_T *rettv, const int flags, bool want_string)
 | 
				
			|||||||
  bool error = false;
 | 
					  bool error = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Get the first variable.
 | 
					  // Get the first variable.
 | 
				
			||||||
  if (eval7(arg, rettv, flags, want_string) == FAIL) {
 | 
					  if (eval7(arg, rettv, evalarg, want_string) == FAIL) {
 | 
				
			||||||
    return FAIL;
 | 
					    return FAIL;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Repeat computing, until no '*', '/' or '%' is following.
 | 
					  // Repeat computing, until no '*', '/' or '%' is following.
 | 
				
			||||||
  for (;;) {
 | 
					  for (;;) {
 | 
				
			||||||
 | 
					    const bool evaluate = evalarg == NULL ? 0 : (evalarg->eval_flags & EVAL_EVALUATE);
 | 
				
			||||||
    op = (uint8_t)(**arg);
 | 
					    op = (uint8_t)(**arg);
 | 
				
			||||||
    if (op != '*' && op != '/' && op != '%') {
 | 
					    if (op != '*' && op != '/' && op != '%') {
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (flags & EVAL_EVALUATE) {
 | 
					    if (evaluate) {
 | 
				
			||||||
      if (rettv->v_type == VAR_FLOAT) {
 | 
					      if (rettv->v_type == VAR_FLOAT) {
 | 
				
			||||||
        f1 = rettv->vval.v_float;
 | 
					        f1 = rettv->vval.v_float;
 | 
				
			||||||
        use_float = true;
 | 
					        use_float = true;
 | 
				
			||||||
@@ -2778,11 +2791,11 @@ static int eval6(char **arg, typval_T *rettv, const int flags, bool want_string)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Get the second variable.
 | 
					    // Get the second variable.
 | 
				
			||||||
    *arg = skipwhite(*arg + 1);
 | 
					    *arg = skipwhite(*arg + 1);
 | 
				
			||||||
    if (eval7(arg, &var2, flags, false) == FAIL) {
 | 
					    if (eval7(arg, &var2, evalarg, false) == FAIL) {
 | 
				
			||||||
      return FAIL;
 | 
					      return FAIL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (flags & EVAL_EVALUATE) {
 | 
					    if (evaluate) {
 | 
				
			||||||
      if (var2.v_type == VAR_FLOAT) {
 | 
					      if (var2.v_type == VAR_FLOAT) {
 | 
				
			||||||
        if (!use_float) {
 | 
					        if (!use_float) {
 | 
				
			||||||
          f1 = (float_T)n1;
 | 
					          f1 = (float_T)n1;
 | 
				
			||||||
@@ -2869,9 +2882,10 @@ static int eval6(char **arg, typval_T *rettv, const int flags, bool want_string)
 | 
				
			|||||||
/// @param want_string  after "." operator
 | 
					/// @param want_string  after "." operator
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
/// @return  OK or FAIL.
 | 
					/// @return  OK or FAIL.
 | 
				
			||||||
static int eval7(char **arg, typval_T *rettv, const int flags, bool want_string)
 | 
					static int eval7(char **arg, typval_T *rettv, evalarg_T *const evalarg, bool want_string)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  const bool evaluate = flags & EVAL_EVALUATE;
 | 
					  const int flags = evalarg == NULL ? 0 : evalarg->eval_flags;
 | 
				
			||||||
 | 
					  const bool evaluate = evalarg != NULL && (evalarg->eval_flags & EVAL_EVALUATE);
 | 
				
			||||||
  int ret = OK;
 | 
					  int ret = OK;
 | 
				
			||||||
  static int recurse = 0;
 | 
					  static int recurse = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2979,7 +2993,7 @@ static int eval7(char **arg, typval_T *rettv, const int flags, bool want_string)
 | 
				
			|||||||
  // nested expression: (expression).
 | 
					  // nested expression: (expression).
 | 
				
			||||||
  case '(':
 | 
					  case '(':
 | 
				
			||||||
    *arg = skipwhite(*arg + 1);
 | 
					    *arg = skipwhite(*arg + 1);
 | 
				
			||||||
    ret = eval1(arg, rettv, flags);  // recursive!
 | 
					    ret = eval1(arg, rettv, evalarg);  // recursive!
 | 
				
			||||||
    if (**arg == ')') {
 | 
					    if (**arg == ')') {
 | 
				
			||||||
      (*arg)++;
 | 
					      (*arg)++;
 | 
				
			||||||
    } else if (ret == OK) {
 | 
					    } else if (ret == OK) {
 | 
				
			||||||
@@ -3319,13 +3333,15 @@ static int eval_index(char **arg, typval_T *rettv, const int flags, bool verbose
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    *arg = skipwhite(key + len);
 | 
					    *arg = skipwhite(key + len);
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
 | 
					    evalarg_T evalarg = { .eval_flags = flags };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // something[idx]
 | 
					    // something[idx]
 | 
				
			||||||
    //
 | 
					    //
 | 
				
			||||||
    // Get the (first) variable from inside the [].
 | 
					    // Get the (first) variable from inside the [].
 | 
				
			||||||
    *arg = skipwhite(*arg + 1);
 | 
					    *arg = skipwhite(*arg + 1);
 | 
				
			||||||
    if (**arg == ':') {
 | 
					    if (**arg == ':') {
 | 
				
			||||||
      empty1 = true;
 | 
					      empty1 = true;
 | 
				
			||||||
    } else if (eval1(arg, &var1, flags) == FAIL) {  // Recursive!
 | 
					    } else if (eval1(arg, &var1, &evalarg) == FAIL) {  // Recursive!
 | 
				
			||||||
      return FAIL;
 | 
					      return FAIL;
 | 
				
			||||||
    } else if (evaluate && !tv_check_str(&var1)) {
 | 
					    } else if (evaluate && !tv_check_str(&var1)) {
 | 
				
			||||||
      // Not a number or string.
 | 
					      // Not a number or string.
 | 
				
			||||||
@@ -3339,7 +3355,7 @@ static int eval_index(char **arg, typval_T *rettv, const int flags, bool verbose
 | 
				
			|||||||
      *arg = skipwhite(*arg + 1);
 | 
					      *arg = skipwhite(*arg + 1);
 | 
				
			||||||
      if (**arg == ']') {
 | 
					      if (**arg == ']') {
 | 
				
			||||||
        empty2 = true;
 | 
					        empty2 = true;
 | 
				
			||||||
      } else if (eval1(arg, &var2, flags) == FAIL) {  // Recursive!
 | 
					      } else if (eval1(arg, &var2, &evalarg) == FAIL) {  // Recursive!
 | 
				
			||||||
        if (!empty1) {
 | 
					        if (!empty1) {
 | 
				
			||||||
          tv_clear(&var1);
 | 
					          tv_clear(&var1);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -3947,6 +3963,8 @@ static int get_list_tv(char **arg, typval_T *rettv, const int flags)
 | 
				
			|||||||
  const bool evaluate = flags & EVAL_EVALUATE;
 | 
					  const bool evaluate = flags & EVAL_EVALUATE;
 | 
				
			||||||
  list_T *l = NULL;
 | 
					  list_T *l = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  evalarg_T evalarg = { .eval_flags = flags };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (evaluate) {
 | 
					  if (evaluate) {
 | 
				
			||||||
    l = tv_list_alloc(kListLenShouldKnow);
 | 
					    l = tv_list_alloc(kListLenShouldKnow);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -3954,7 +3972,7 @@ static int get_list_tv(char **arg, typval_T *rettv, const int flags)
 | 
				
			|||||||
  *arg = skipwhite(*arg + 1);
 | 
					  *arg = skipwhite(*arg + 1);
 | 
				
			||||||
  while (**arg != ']' && **arg != NUL) {
 | 
					  while (**arg != ']' && **arg != NUL) {
 | 
				
			||||||
    typval_T tv;
 | 
					    typval_T tv;
 | 
				
			||||||
    if (eval1(arg, &tv, flags) == FAIL) {  // Recursive!
 | 
					    if (eval1(arg, &tv, &evalarg) == FAIL) {  // Recursive!
 | 
				
			||||||
      goto failret;
 | 
					      goto failret;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (evaluate) {
 | 
					    if (evaluate) {
 | 
				
			||||||
@@ -4586,7 +4604,9 @@ static int get_literal_key(char **arg, typval_T *tv)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Allocate a variable for a Dictionary and fill it from "*arg".
 | 
					/// Allocate a variable for a Dictionary and fill it from "*arg".
 | 
				
			||||||
/// "literal" is true for #{key: val}
 | 
					///
 | 
				
			||||||
 | 
					/// @param literal  true for #{key: val}
 | 
				
			||||||
 | 
					/// @param flags    can have EVAL_EVALUATE and other EVAL_ flags.
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
/// @return  OK or FAIL.  Returns NOTDONE for {expr}.
 | 
					/// @return  OK or FAIL.  Returns NOTDONE for {expr}.
 | 
				
			||||||
static int eval_dict(char **arg, typval_T *rettv, const int flags, bool literal)
 | 
					static int eval_dict(char **arg, typval_T *rettv, const int flags, bool literal)
 | 
				
			||||||
@@ -4597,6 +4617,8 @@ static int eval_dict(char **arg, typval_T *rettv, const int flags, bool literal)
 | 
				
			|||||||
  char *curly_expr = skipwhite(*arg + 1);
 | 
					  char *curly_expr = skipwhite(*arg + 1);
 | 
				
			||||||
  char buf[NUMBUFLEN];
 | 
					  char buf[NUMBUFLEN];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  evalarg_T evalarg = { .eval_flags = flags };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // First check if it's not a curly-braces expression: {expr}.
 | 
					  // First check if it's not a curly-braces expression: {expr}.
 | 
				
			||||||
  // Must do this without evaluating, otherwise a function may be called
 | 
					  // Must do this without evaluating, otherwise a function may be called
 | 
				
			||||||
  // twice.  Unfortunately this means we need to call eval1() twice for the
 | 
					  // twice.  Unfortunately this means we need to call eval1() twice for the
 | 
				
			||||||
@@ -4605,7 +4627,7 @@ static int eval_dict(char **arg, typval_T *rettv, const int flags, bool literal)
 | 
				
			|||||||
  // "#{abc}" is never a curly-braces expression.
 | 
					  // "#{abc}" is never a curly-braces expression.
 | 
				
			||||||
  if (*curly_expr != '}'
 | 
					  if (*curly_expr != '}'
 | 
				
			||||||
      && !literal
 | 
					      && !literal
 | 
				
			||||||
      && eval1(&curly_expr, &tv, 0) == OK
 | 
					      && eval1(&curly_expr, &tv, NULL) == OK
 | 
				
			||||||
      && *skipwhite(curly_expr) == '}') {
 | 
					      && *skipwhite(curly_expr) == '}') {
 | 
				
			||||||
    return NOTDONE;
 | 
					    return NOTDONE;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -4622,7 +4644,7 @@ static int eval_dict(char **arg, typval_T *rettv, const int flags, bool literal)
 | 
				
			|||||||
  while (**arg != '}' && **arg != NUL) {
 | 
					  while (**arg != '}' && **arg != NUL) {
 | 
				
			||||||
    if ((literal
 | 
					    if ((literal
 | 
				
			||||||
         ? get_literal_key(arg, &tvkey)
 | 
					         ? get_literal_key(arg, &tvkey)
 | 
				
			||||||
         : eval1(arg, &tvkey, flags)) == FAIL) {  // recursive!
 | 
					         : eval1(arg, &tvkey, &evalarg)) == FAIL) {  // recursive!
 | 
				
			||||||
      goto failret;
 | 
					      goto failret;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (**arg != ':') {
 | 
					    if (**arg != ':') {
 | 
				
			||||||
@@ -4640,7 +4662,7 @@ static int eval_dict(char **arg, typval_T *rettv, const int flags, bool literal)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    *arg = skipwhite(*arg + 1);
 | 
					    *arg = skipwhite(*arg + 1);
 | 
				
			||||||
    if (eval1(arg, &tv, flags) == FAIL) {  // Recursive!
 | 
					    if (eval1(arg, &tv, &evalarg) == FAIL) {  // Recursive!
 | 
				
			||||||
      if (evaluate) {
 | 
					      if (evaluate) {
 | 
				
			||||||
        tv_clear(&tvkey);
 | 
					        tv_clear(&tvkey);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@@ -7389,6 +7411,8 @@ void ex_echo(exarg_T *eap)
 | 
				
			|||||||
  const int did_emsg_before = did_emsg;
 | 
					  const int did_emsg_before = did_emsg;
 | 
				
			||||||
  const int called_emsg_before = called_emsg;
 | 
					  const int called_emsg_before = called_emsg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  evalarg_T evalarg = { .eval_flags = eap->skip ? 0 : EVAL_EVALUATE };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (eap->skip) {
 | 
					  if (eap->skip) {
 | 
				
			||||||
    emsg_skip++;
 | 
					    emsg_skip++;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -7399,7 +7423,7 @@ void ex_echo(exarg_T *eap)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      char *p = arg;
 | 
					      char *p = arg;
 | 
				
			||||||
      if (eval1(&arg, &rettv, eap->skip ? 0 : EVAL_EVALUATE) == FAIL) {
 | 
					      if (eval1(&arg, &rettv, &evalarg) == FAIL) {
 | 
				
			||||||
        // Report the invalid expression unless the expression evaluation
 | 
					        // Report the invalid expression unless the expression evaluation
 | 
				
			||||||
        // has been cancelled due to an aborting error, an interrupt, or an
 | 
					        // has been cancelled due to an aborting error, an interrupt, or an
 | 
				
			||||||
        // exception.
 | 
					        // exception.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -266,11 +266,23 @@ typedef int (*ex_unletlock_callback)(lval_T *, char *, exarg_T *, int);
 | 
				
			|||||||
// Used for checking if local variables or arguments used in a lambda.
 | 
					// Used for checking if local variables or arguments used in a lambda.
 | 
				
			||||||
extern bool *eval_lavars_used;
 | 
					extern bool *eval_lavars_used;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Struct passed through eval() functions.
 | 
				
			||||||
 | 
					/// See EVALARG_EVALUATE for a fixed value with eval_flags set to EVAL_EVALUATE.
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					  int eval_flags;     ///< EVAL_ flag values below
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// copied from exarg_T when "getline" is "getsourceline". Can be NULL.
 | 
				
			||||||
 | 
					  void *eval_cookie;   // argument for getline()
 | 
				
			||||||
 | 
					} evalarg_T;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Flag for expression evaluation.
 | 
					/// Flag for expression evaluation.
 | 
				
			||||||
enum {
 | 
					enum {
 | 
				
			||||||
  EVAL_EVALUATE = 1,  ///< when missing don't actually evaluate
 | 
					  EVAL_EVALUATE = 1,  ///< when missing don't actually evaluate
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Passed to an eval() function to enable evaluation.
 | 
				
			||||||
 | 
					EXTERN evalarg_T EVALARG_EVALUATE INIT(= { EVAL_EVALUATE, NULL });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
 | 
					#ifdef INCLUDE_GENERATED_DECLARATIONS
 | 
				
			||||||
# include "eval.h.generated.h"
 | 
					# include "eval.h.generated.h"
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1550,7 +1550,7 @@ static void f_eval(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const char *const expr_start = s;
 | 
					  const char *const expr_start = s;
 | 
				
			||||||
  if (s == NULL || eval1((char **)&s, rettv, EVAL_EVALUATE) == FAIL) {
 | 
					  if (s == NULL || eval1((char **)&s, rettv, &EVALARG_EVALUATE) == FAIL) {
 | 
				
			||||||
    if (expr_start != NULL && !aborting()) {
 | 
					    if (expr_start != NULL && !aborting()) {
 | 
				
			||||||
      semsg(_(e_invexpr2), expr_start);
 | 
					      semsg(_(e_invexpr2), expr_start);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -152,7 +152,7 @@ static int get_function_args(char **argp, char endchar, garray_T *newargs, int *
 | 
				
			|||||||
        p = skipwhite(p) + 1;
 | 
					        p = skipwhite(p) + 1;
 | 
				
			||||||
        p = skipwhite(p);
 | 
					        p = skipwhite(p);
 | 
				
			||||||
        char *expr = p;
 | 
					        char *expr = p;
 | 
				
			||||||
        if (eval1(&p, &rettv, 0) != FAIL) {
 | 
					        if (eval1(&p, &rettv, NULL) != FAIL) {
 | 
				
			||||||
          ga_grow(default_args, 1);
 | 
					          ga_grow(default_args, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          // trim trailing whitespace
 | 
					          // trim trailing whitespace
 | 
				
			||||||
@@ -455,6 +455,8 @@ int get_func_tv(const char *name, int len, typval_T *rettv, char **arg, funcexe_
 | 
				
			|||||||
  typval_T argvars[MAX_FUNC_ARGS + 1];          // vars for arguments
 | 
					  typval_T argvars[MAX_FUNC_ARGS + 1];          // vars for arguments
 | 
				
			||||||
  int argcount = 0;                     // number of arguments found
 | 
					  int argcount = 0;                     // number of arguments found
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  evalarg_T evalarg = { .eval_flags = funcexe->fe_evaluate ? EVAL_EVALUATE : 0 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Get the arguments.
 | 
					  // Get the arguments.
 | 
				
			||||||
  argp = *arg;
 | 
					  argp = *arg;
 | 
				
			||||||
  while (argcount < MAX_FUNC_ARGS
 | 
					  while (argcount < MAX_FUNC_ARGS
 | 
				
			||||||
@@ -463,8 +465,7 @@ int get_func_tv(const char *name, int len, typval_T *rettv, char **arg, funcexe_
 | 
				
			|||||||
    if (*argp == ')' || *argp == ',' || *argp == NUL) {
 | 
					    if (*argp == ')' || *argp == ',' || *argp == NUL) {
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (eval1(&argp, &argvars[argcount],
 | 
					    if (eval1(&argp, &argvars[argcount], &evalarg) == FAIL) {
 | 
				
			||||||
              funcexe->fe_evaluate ? EVAL_EVALUATE : 0) == FAIL) {
 | 
					 | 
				
			||||||
      ret = FAIL;
 | 
					      ret = FAIL;
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -973,7 +974,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        default_expr = ((char **)(fp->uf_def_args.ga_data))
 | 
					        default_expr = ((char **)(fp->uf_def_args.ga_data))
 | 
				
			||||||
                       [ai + fp->uf_def_args.ga_len];
 | 
					                       [ai + fp->uf_def_args.ga_len];
 | 
				
			||||||
        if (eval1(&default_expr, &def_rettv, EVAL_EVALUATE) == FAIL) {
 | 
					        if (eval1(&default_expr, &def_rettv, &EVALARG_EVALUATE) == FAIL) {
 | 
				
			||||||
          default_arg_err = true;
 | 
					          default_arg_err = true;
 | 
				
			||||||
          break;
 | 
					          break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -1110,7 +1111,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett
 | 
				
			|||||||
    // A Lambda always has the command "return {expr}".  It is much faster
 | 
					    // A Lambda always has the command "return {expr}".  It is much faster
 | 
				
			||||||
    // to evaluate {expr} directly.
 | 
					    // to evaluate {expr} directly.
 | 
				
			||||||
    ex_nesting_level++;
 | 
					    ex_nesting_level++;
 | 
				
			||||||
    (void)eval1(&p, rettv, EVAL_EVALUATE);
 | 
					    (void)eval1(&p, rettv, &EVALARG_EVALUATE);
 | 
				
			||||||
    ex_nesting_level--;
 | 
					    ex_nesting_level--;
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    // call do_cmdline() to execute the lines
 | 
					    // call do_cmdline() to execute the lines
 | 
				
			||||||
@@ -2948,13 +2949,15 @@ void ex_return(exarg_T *eap)
 | 
				
			|||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  evalarg_T evalarg = { .eval_flags = eap->skip ? 0 : EVAL_EVALUATE };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (eap->skip) {
 | 
					  if (eap->skip) {
 | 
				
			||||||
    emsg_skip++;
 | 
					    emsg_skip++;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  eap->nextcmd = NULL;
 | 
					  eap->nextcmd = NULL;
 | 
				
			||||||
  if ((*arg != NUL && *arg != '|' && *arg != '\n')
 | 
					  if ((*arg != NUL && *arg != '|' && *arg != '\n')
 | 
				
			||||||
      && eval0(arg, &rettv, &eap->nextcmd, eap->skip ? 0 : EVAL_EVALUATE) != FAIL) {
 | 
					      && eval0(arg, &rettv, &eap->nextcmd, &evalarg) != FAIL) {
 | 
				
			||||||
    if (!eap->skip) {
 | 
					    if (!eap->skip) {
 | 
				
			||||||
      returning = do_return(eap, false, true, &rettv);
 | 
					      returning = do_return(eap, false, true, &rettv);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
@@ -3005,7 +3008,7 @@ void ex_call(exarg_T *eap)
 | 
				
			|||||||
    // instead to skip to any following command, e.g. for:
 | 
					    // instead to skip to any following command, e.g. for:
 | 
				
			||||||
    //   :if 0 | call dict.foo().bar() | endif.
 | 
					    //   :if 0 | call dict.foo().bar() | endif.
 | 
				
			||||||
    emsg_skip++;
 | 
					    emsg_skip++;
 | 
				
			||||||
    if (eval0(eap->arg, &rettv, &eap->nextcmd, 0) != FAIL) {
 | 
					    if (eval0(eap->arg, &rettv, &eap->nextcmd, NULL) != FAIL) {
 | 
				
			||||||
      tv_clear(&rettv);
 | 
					      tv_clear(&rettv);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    emsg_skip--;
 | 
					    emsg_skip--;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -255,13 +255,18 @@ void ex_let(exarg_T *eap)
 | 
				
			|||||||
    if (eap->skip) {
 | 
					    if (eap->skip) {
 | 
				
			||||||
      emsg_skip++;
 | 
					      emsg_skip++;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    int eval_flags = eap->skip ? 0 : EVAL_EVALUATE;
 | 
					    evalarg_T evalarg = {
 | 
				
			||||||
    i = eval0(expr, &rettv, &eap->nextcmd, eval_flags);
 | 
					      .eval_flags = eap->skip ? 0 : EVAL_EVALUATE,
 | 
				
			||||||
 | 
					      .eval_cookie = eap->getline == getsourceline ? eap->cookie : NULL,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    i = eval0(expr, &rettv, &eap->nextcmd, &evalarg);
 | 
				
			||||||
 | 
					    if (eap->skip) {
 | 
				
			||||||
 | 
					      emsg_skip--;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    if (eap->skip) {
 | 
					    if (eap->skip) {
 | 
				
			||||||
      if (i != FAIL) {
 | 
					      if (i != FAIL) {
 | 
				
			||||||
        tv_clear(&rettv);
 | 
					        tv_clear(&rettv);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      emsg_skip--;
 | 
					 | 
				
			||||||
    } else if (i != FAIL) {
 | 
					    } else if (i != FAIL) {
 | 
				
			||||||
      (void)ex_let_vars(eap->arg, &rettv, false, semicolon, var_count, is_const, op);
 | 
					      (void)ex_let_vars(eap->arg, &rettv, false, semicolon, var_count, is_const, op);
 | 
				
			||||||
      tv_clear(&rettv);
 | 
					      tv_clear(&rettv);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -792,8 +792,11 @@ void report_discard_pending(int pending, void *value)
 | 
				
			|||||||
void ex_eval(exarg_T *eap)
 | 
					void ex_eval(exarg_T *eap)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  typval_T tv;
 | 
					  typval_T tv;
 | 
				
			||||||
 | 
					  evalarg_T evalarg = {
 | 
				
			||||||
  if (eval0(eap->arg, &tv, &eap->nextcmd, eap->skip ? 0 : EVAL_EVALUATE) == OK) {
 | 
					    .eval_flags = eap->skip ? 0 : EVAL_EVALUATE,
 | 
				
			||||||
 | 
					    .eval_cookie = eap->getline == getsourceline ? eap->cookie : NULL,
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  if (eval0(eap->arg, &tv, &eap->nextcmd, &evalarg) == OK) {
 | 
				
			||||||
    tv_clear(&tv);
 | 
					    tv_clear(&tv);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6958,7 +6958,7 @@ void ex_cexpr(exarg_T *eap)
 | 
				
			|||||||
  // Evaluate the expression.  When the result is a string or a list we can
 | 
					  // Evaluate the expression.  When the result is a string or a list we can
 | 
				
			||||||
  // use it to fill the errorlist.
 | 
					  // use it to fill the errorlist.
 | 
				
			||||||
  typval_T tv;
 | 
					  typval_T tv;
 | 
				
			||||||
  if (eval0(eap->arg, &tv, &eap->nextcmd, EVAL_EVALUATE) == FAIL) {
 | 
					  if (eval0(eap->arg, &tv, &eap->nextcmd, &EVALARG_EVALUATE) == FAIL) {
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -512,7 +512,8 @@ end
 | 
				
			|||||||
local function eval0(expr)
 | 
					local function eval0(expr)
 | 
				
			||||||
  local tv = ffi.gc(ffi.new('typval_T', {v_type=eval.VAR_UNKNOWN}),
 | 
					  local tv = ffi.gc(ffi.new('typval_T', {v_type=eval.VAR_UNKNOWN}),
 | 
				
			||||||
                    eval.tv_clear)
 | 
					                    eval.tv_clear)
 | 
				
			||||||
  if eval.eval0(to_cstr(expr), tv, nil, eval.EVAL_EVALUATE) == 0 then
 | 
					  local evalarg = ffi.new('evalarg_T', {eval_flags = eval.EVAL_EVALUATE})
 | 
				
			||||||
 | 
					  if eval.eval0(to_cstr(expr), tv, nil, evalarg) == 0 then
 | 
				
			||||||
    return nil
 | 
					    return nil
 | 
				
			||||||
  else
 | 
					  else
 | 
				
			||||||
    return tv
 | 
					    return tv
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user