mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +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
	 zeertzjq
					zeertzjq