mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	vim-patch:8.2.0918: duplicate code for evaluating expression argument
Problem:    Duplicate code for evaluating expression argument.
Solution:   Merge the code and make the use more flexible.
a9c0104947
			
			
This commit is contained in:
		| @@ -766,6 +766,15 @@ static int eval1_emsg(char_u **arg, typval_T *rettv, bool evaluate) | |||||||
|   return ret; |   return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /// @return whether a typval is a valid expression to pass to eval_expr_typval() | ||||||
|  | /// or eval_expr_to_bool().  An empty string returns false; | ||||||
|  | bool eval_expr_valid_arg(const typval_T *const tv) | ||||||
|  |   FUNC_ATTR_NONNULL_ALL FUNC_ATTR_CONST | ||||||
|  | { | ||||||
|  |   return tv->v_type != VAR_UNKNOWN | ||||||
|  |          && (tv->v_type != VAR_STRING || (tv->vval.v_string != NULL && *tv->vval.v_string != NUL)); | ||||||
|  | } | ||||||
|  |  | ||||||
| int eval_expr_typval(const typval_T *expr, typval_T *argv, int argc, typval_T *rettv) | int eval_expr_typval(const typval_T *expr, typval_T *argv, int argc, typval_T *rettv) | ||||||
|   FUNC_ATTR_NONNULL_ARG(1, 2, 4) |   FUNC_ATTR_NONNULL_ARG(1, 2, 4) | ||||||
| { | { | ||||||
| @@ -3381,67 +3390,6 @@ static int eval_func(char_u **const arg, char_u *const name, const int name_len, | |||||||
|   return ret; |   return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| /// Process a function argument that can be a string expression or a function |  | ||||||
| /// reference. |  | ||||||
| /// "tv" must remain valid until calling evalarg_clean()! |  | ||||||
| /// @return false when the argument is invalid. |  | ||||||
| bool evalarg_get(typval_T *const tv, evalarg_T *const eva) |  | ||||||
|   FUNC_ATTR_NONNULL_ALL |  | ||||||
| { |  | ||||||
|   if (tv->v_type == VAR_STRING || tv->v_type == VAR_NUMBER || tv->v_type == VAR_BOOL |  | ||||||
|       || tv->v_type == VAR_SPECIAL) { |  | ||||||
|     char numbuf[NUMBUFLEN]; |  | ||||||
|     eva->eva_string = tv_get_string_buf(tv, numbuf); |  | ||||||
|     return true; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   return callback_from_typval(&eva->eva_callback, tv); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /// @return whether "eva" has a valid expression or callback. |  | ||||||
| bool evalarg_valid(const evalarg_T *const eva) |  | ||||||
|   FUNC_ATTR_NONNULL_ALL FUNC_ATTR_CONST |  | ||||||
| { |  | ||||||
|   return eva->eva_string != NULL || eva->eva_callback.type != kCallbackNone; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /// Invoke the expression or callback "eva" and return the result in "tv". |  | ||||||
| /// @return false if something failed |  | ||||||
| bool evalarg_call(evalarg_T *const eva, typval_T *const tv) |  | ||||||
|   FUNC_ATTR_NONNULL_ALL |  | ||||||
| { |  | ||||||
|   if (eva->eva_string != NULL) { |  | ||||||
|     return eval0((char_u *)eva->eva_string, tv, NULL, true); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   typval_T argv[1]; |  | ||||||
|   argv[0].v_type = VAR_UNKNOWN; |  | ||||||
|   return callback_call(&eva->eva_callback, 0, argv, tv); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /// Like evalarg_call(), but just return true or false. |  | ||||||
| /// Sets "error" to true if evaluation failed. |  | ||||||
| bool evalarg_call_bool(evalarg_T *const eva, bool *const error) |  | ||||||
|   FUNC_ATTR_NONNULL_ALL |  | ||||||
| { |  | ||||||
|   typval_T tv; |  | ||||||
|   if (!evalarg_call(eva, &tv)) { |  | ||||||
|     *error = true; |  | ||||||
|     return false; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   const bool r = tv_get_number(&tv); |  | ||||||
|   tv_clear(&tv); |  | ||||||
|   *error = false; |  | ||||||
|   return r; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void evalarg_clean(evalarg_T *const eva) |  | ||||||
|   FUNC_ATTR_NONNULL_ALL |  | ||||||
| { |  | ||||||
|   callback_free(&eva->eva_callback); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // TODO(ZyX-I): move to eval/expressions | // TODO(ZyX-I): move to eval/expressions | ||||||
|  |  | ||||||
| /* | /* | ||||||
|   | |||||||
| @@ -272,22 +272,6 @@ typedef int (*ex_unletlock_callback)(lval_T *, char_u *, 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; | ||||||
|  |  | ||||||
| /// Function argument that can be a string, funcref or partial. |  | ||||||
| /// - declare:  evalarg_T name; |  | ||||||
| /// - init:     name = EVALARG_INIT; |  | ||||||
| /// - set:      evalarg_get(&argvars[3], &name); |  | ||||||
| /// - use:      if (evalarg_valid(&name)) res = evalarg_call(&name); |  | ||||||
| /// - cleanup:  evalarg_clean(&name); |  | ||||||
| typedef struct { |  | ||||||
|   const char *eva_string; |  | ||||||
|   Callback eva_callback; |  | ||||||
| } evalarg_T; |  | ||||||
|  |  | ||||||
| #define EVALARG_INIT (evalarg_T) { \ |  | ||||||
|   .eva_string = NULL, \ |  | ||||||
|   .eva_callback = CALLBACK_NONE, \ |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #ifdef INCLUDE_GENERATED_DECLARATIONS | #ifdef INCLUDE_GENERATED_DECLARATIONS | ||||||
| # include "eval.h.generated.h" | # include "eval.h.generated.h" | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -8237,7 +8237,7 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp) | |||||||
|   int options = SEARCH_KEEP; |   int options = SEARCH_KEEP; | ||||||
|   int subpatnum; |   int subpatnum; | ||||||
|   searchit_arg_T sia; |   searchit_arg_T sia; | ||||||
|   evalarg_T skip = EVALARG_INIT; |   bool use_skip = false; | ||||||
|  |  | ||||||
|   const char *const pat = tv_get_string(&argvars[0]); |   const char *const pat = tv_get_string(&argvars[0]); | ||||||
|   dir = get_search_arg(&argvars[1], flagsp);  // May set p_ws. |   dir = get_search_arg(&argvars[1], flagsp);  // May set p_ws. | ||||||
| @@ -8266,9 +8266,7 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp) | |||||||
|       if (time_limit < 0) { |       if (time_limit < 0) { | ||||||
|         goto theend; |         goto theend; | ||||||
|       } |       } | ||||||
|       if (argvars[4].v_type != VAR_UNKNOWN && !evalarg_get(&argvars[4], &skip)) { |       use_skip = eval_expr_valid_arg(&argvars[4]); | ||||||
|         goto theend; |  | ||||||
|       } |  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -8303,19 +8301,19 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp) | |||||||
|       subpatnum = FAIL; |       subpatnum = FAIL; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (subpatnum == FAIL || !evalarg_valid(&skip)) { |     if (subpatnum == FAIL || !use_skip) { | ||||||
|       // didn't find it or no skip argument |       // didn't find it or no skip argument | ||||||
|       break; |       break; | ||||||
|     } |     } | ||||||
|     firstpos = pos; |     firstpos = pos; | ||||||
|  |  | ||||||
|     // If the skip pattern matches, ignore this match. |     // If the skip expression matches, ignore this match. | ||||||
|     { |     { | ||||||
|       bool err; |  | ||||||
|       const pos_T save_pos = curwin->w_cursor; |       const pos_T save_pos = curwin->w_cursor; | ||||||
|  |  | ||||||
|       curwin->w_cursor = pos; |       curwin->w_cursor = pos; | ||||||
|       const bool do_skip = evalarg_call_bool(&skip, &err); |       bool err = false; | ||||||
|  |       const bool do_skip = eval_expr_to_bool(&argvars[4], &err); | ||||||
|       curwin->w_cursor = save_pos; |       curwin->w_cursor = save_pos; | ||||||
|       if (err) { |       if (err) { | ||||||
|         // Evaluating {skip} caused an error, break here. |         // Evaluating {skip} caused an error, break here. | ||||||
| @@ -8356,7 +8354,6 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp) | |||||||
|   } |   } | ||||||
| theend: | theend: | ||||||
|   p_ws = save_p_ws; |   p_ws = save_p_ws; | ||||||
|   evalarg_clean(&skip); |  | ||||||
|  |  | ||||||
|   return retval; |   return retval; | ||||||
| } | } | ||||||
| @@ -8788,13 +8785,9 @@ static int searchpair_cmn(typval_T *argvars, pos_T *match_pos) | |||||||
|       || argvars[4].v_type == VAR_UNKNOWN) { |       || argvars[4].v_type == VAR_UNKNOWN) { | ||||||
|     skip = NULL; |     skip = NULL; | ||||||
|   } else { |   } else { | ||||||
|  |     // Type is checked later. | ||||||
|     skip = &argvars[4]; |     skip = &argvars[4]; | ||||||
|     if (skip->v_type != VAR_FUNC |  | ||||||
|         && skip->v_type != VAR_PARTIAL |  | ||||||
|         && skip->v_type != VAR_STRING) { |  | ||||||
|       semsg(_(e_invarg2), tv_get_string(&argvars[4])); |  | ||||||
|       goto theend;  // Type error. |  | ||||||
|     } |  | ||||||
|     if (argvars[5].v_type != VAR_UNKNOWN) { |     if (argvars[5].v_type != VAR_UNKNOWN) { | ||||||
|       lnum_stop = tv_get_number_chk(&argvars[5], NULL); |       lnum_stop = tv_get_number_chk(&argvars[5], NULL); | ||||||
|       if (lnum_stop < 0) { |       if (lnum_stop < 0) { | ||||||
| @@ -8905,10 +8898,7 @@ long do_searchpair(const char *spat, const char *mpat, const char *epat, int dir | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   if (skip != NULL) { |   if (skip != NULL) { | ||||||
|     // Empty string means to not use the skip expression. |     use_skip = eval_expr_valid_arg(skip); | ||||||
|     if (skip->v_type == VAR_STRING || skip->v_type == VAR_FUNC) { |  | ||||||
|       use_skip = skip->vval.v_string != NULL && *skip->vval.v_string != NUL; |  | ||||||
|     } |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   save_cursor = curwin->w_cursor; |   save_cursor = curwin->w_cursor; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Sean Dewar
					Sean Dewar