To: vim_dev@googlegroups.com Subject: Patch 8.2.0918 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.0918 Problem: Duplicate code for evaluating expression argument. Solution: Merge the code and make the use more flexible. Files: src/evalfunc.c, src/eval.c, src/proto/eval.pro, src/evalvars.c, src/proto/evalvars.pro, src/structs.h *** ../vim-8.2.0917/src/evalfunc.c 2020-06-06 18:37:47.860138513 +0200 --- src/evalfunc.c 2020-06-07 14:42:25.007166673 +0200 *************** *** 6399,6409 **** int options = SEARCH_KEEP; int subpatnum; searchit_arg_T sia; ! evalarg_T skip; pos_T firstpos; - CLEAR_FIELD(skip); - pat = tv_get_string(&argvars[0]); dir = get_search_arg(&argvars[1], flagsp); // may set p_ws if (dir == 0) --- 6399,6407 ---- int options = SEARCH_KEEP; int subpatnum; searchit_arg_T sia; ! int use_skip = FALSE; pos_T firstpos; pat = tv_get_string(&argvars[0]); dir = get_search_arg(&argvars[1], flagsp); // may set p_ws if (dir == 0) *************** *** 6429,6437 **** if (time_limit < 0) goto theend; #endif ! if (argvars[4].v_type != VAR_UNKNOWN ! && evalarg_get(&argvars[4], &skip) == FAIL) ! goto theend; } } --- 6427,6433 ---- if (time_limit < 0) goto theend; #endif ! use_skip = eval_expr_valid_arg(&argvars[4]); } } *************** *** 6471,6489 **** if (firstpos.lnum != 0 && EQUAL_POS(pos, firstpos)) subpatnum = FAIL; ! if (subpatnum == FAIL || !evalarg_valid(&skip)) // didn't find it or no skip argument break; firstpos = pos; ! // If the skip pattern matches, ignore this match. { int do_skip; int err; pos_T save_pos = curwin->w_cursor; curwin->w_cursor = pos; ! do_skip = evalarg_call_bool(&skip, &err); curwin->w_cursor = save_pos; if (err) { --- 6467,6486 ---- if (firstpos.lnum != 0 && EQUAL_POS(pos, firstpos)) subpatnum = FAIL; ! if (subpatnum == FAIL || !use_skip) // didn't find it or no skip argument break; firstpos = pos; ! // If the skip expression matches, ignore this match. { int do_skip; int err; pos_T save_pos = curwin->w_cursor; curwin->w_cursor = pos; ! err = FALSE; ! do_skip = eval_expr_to_bool(&argvars[4], &err); curwin->w_cursor = save_pos; if (err) { *************** *** 6523,6529 **** curwin->w_set_curswant = TRUE; theend: p_ws = save_p_ws; - evalarg_clean(&skip); return retval; } --- 6520,6525 ---- *************** *** 6791,6804 **** skip = NULL; else { skip = &argvars[4]; ! if (skip->v_type != VAR_FUNC && skip->v_type != VAR_PARTIAL ! && skip->v_type != VAR_STRING) ! { ! // Type error ! semsg(_(e_invarg2), tv_get_string(&argvars[4])); ! goto theend; ! } if (argvars[5].v_type != VAR_UNKNOWN) { lnum_stop = (long)tv_get_number_chk(&argvars[5], NULL); --- 6787,6795 ---- skip = NULL; else { + // Type is checked later. skip = &argvars[4]; ! if (argvars[5].v_type != VAR_UNKNOWN) { lnum_stop = (long)tv_get_number_chk(&argvars[5], NULL); *************** *** 6922,6933 **** options |= SEARCH_START; if (skip != NULL) ! { ! // Empty string means to not use the skip expression. ! 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; pos = curwin->w_cursor; --- 6913,6919 ---- options |= SEARCH_START; if (skip != NULL) ! use_skip = eval_expr_valid_arg(skip); save_cursor = curwin->w_cursor; pos = curwin->w_cursor; *** ../vim-8.2.0917/src/eval.c 2020-05-30 17:05:57.028692410 +0200 --- src/eval.c 2020-06-07 14:26:15.094077727 +0200 *************** *** 212,217 **** --- 212,229 ---- } /* + * Return whether a typval is a valid expression to pass to eval_expr_typval() + * or eval_expr_to_bool(). An empty string returns FALSE; + */ + int + eval_expr_valid_arg(typval_T *tv) + { + return tv->v_type != VAR_UNKNOWN + && (tv->v_type != VAR_STRING + || (tv->vval.v_string != NULL && *tv->vval.v_string != NUL)); + } + + /* * Evaluate an expression, which can be a function, partial or string. * Pass arguments "argv[argc]". * Return the result in "rettv" and OK or FAIL. *** ../vim-8.2.0917/src/proto/eval.pro 2020-05-30 17:05:57.032692393 +0200 --- src/proto/eval.pro 2020-06-07 14:30:53.985926195 +0200 *************** *** 4,9 **** --- 4,10 ---- void eval_init(void); void eval_clear(void); int eval_to_bool(char_u *arg, int *error, char_u **nextcmd, int skip); + int eval_expr_valid_arg(typval_T *tv); int eval_expr_typval(typval_T *expr, typval_T *argv, int argc, typval_T *rettv); int eval_expr_to_bool(typval_T *expr, int *error); char_u *eval_to_string_skip(char_u *arg, char_u **nextcmd, int skip); *************** *** 19,32 **** int eval_foldexpr(char_u *arg, int *cp); char_u *get_lval(char_u *name, typval_T *rettv, lval_T *lp, int unlet, int skip, int flags, int fne_flags); void clear_lval(lval_T *lp); ! void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, int is_const, char_u *op); void *eval_for_line(char_u *arg, int *errp, char_u **nextcmdp, int skip); int next_for_item(void *fi_void, char_u *arg); void free_for_info(void *fi_void); void set_context_for_expression(expand_T *xp, char_u *arg, cmdidx_T cmdidx); int pattern_match(char_u *pat, char_u *text, int ic); ! int eval0(char_u *arg, typval_T *rettv, char_u **nextcmd, int evaluate); ! int eval1(char_u **arg, typval_T *rettv, int evaluate); void eval_addblob(typval_T *tv1, typval_T *tv2); int eval_addlist(typval_T *tv1, typval_T *tv2); char_u *partial_name(partial_T *pt); --- 20,33 ---- int eval_foldexpr(char_u *arg, int *cp); char_u *get_lval(char_u *name, typval_T *rettv, lval_T *lp, int unlet, int skip, int flags, int fne_flags); void clear_lval(lval_T *lp); ! void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, int flags, char_u *op); void *eval_for_line(char_u *arg, int *errp, char_u **nextcmdp, int skip); int next_for_item(void *fi_void, char_u *arg); void free_for_info(void *fi_void); void set_context_for_expression(expand_T *xp, char_u *arg, cmdidx_T cmdidx); int pattern_match(char_u *pat, char_u *text, int ic); ! int eval0(char_u *arg, typval_T *rettv, char_u **nextcmd, int flags); ! int eval1(char_u **arg, typval_T *rettv, int flags); void eval_addblob(typval_T *tv1, typval_T *tv2); int eval_addlist(typval_T *tv1, typval_T *tv2); char_u *partial_name(partial_T *pt); *************** *** 50,56 **** char_u *find_name_end(char_u *arg, char_u **expr_start, char_u **expr_end, int flags); int eval_isnamec(int c); int eval_isnamec1(int c); ! int handle_subscript(char_u **arg, typval_T *rettv, int evaluate, int verbose, char_u *start_leader, char_u **end_leaderp); int item_copy(typval_T *from, typval_T *to, int deep, int copyID); void echo_one(typval_T *rettv, int with_space, int *atstart, int *needclr); void ex_echo(exarg_T *eap); --- 51,57 ---- char_u *find_name_end(char_u *arg, char_u **expr_start, char_u **expr_end, int flags); int eval_isnamec(int c); int eval_isnamec1(int c); ! int handle_subscript(char_u **arg, typval_T *rettv, int flags, int verbose, char_u *start_leader, char_u **end_leaderp); int item_copy(typval_T *from, typval_T *to, int deep, int copyID); void echo_one(typval_T *rettv, int with_space, int *atstart, int *needclr); void ex_echo(exarg_T *eap); *** ../vim-8.2.0917/src/evalvars.c 2020-06-06 18:37:47.864138502 +0200 --- src/evalvars.c 2020-06-07 14:29:32.642858246 +0200 *************** *** 3811,3889 **** callback->cb_name = NULL; } - /* - * Process a function argument that can be a string expression or a function - * reference. - * "tv" must remain valid until calling evalarg_clean()! - * Returns FAIL when the argument is invalid. - */ - int - evalarg_get(typval_T *tv, evalarg_T *eva) - { - if (tv->v_type == VAR_STRING - || tv->v_type == VAR_NUMBER - || tv->v_type == VAR_BOOL - || tv->v_type == VAR_SPECIAL) - { - eva->eva_string = tv_get_string_buf(tv, eva->eva_buf); - return OK; - } - - eva->eva_callback = get_callback(tv); - return eva->eva_callback.cb_name == NULL ? FAIL : OK; - } - - /* - * Return whether "eva" has a valid expression or callback. - */ - int - evalarg_valid(evalarg_T *eva) - { - return eva->eva_string != NULL || eva->eva_callback.cb_name != NULL; - } - - /* - * Invoke the expression or callback "eva" and return the result in "tv". - * Returns FAIL if something failed - */ - int - evalarg_call(evalarg_T *eva, typval_T *tv) - { - typval_T argv[1]; - - if (eva->eva_string != NULL) - return eval0(eva->eva_string, tv, NULL, EVAL_EVALUATE); - - argv[0].v_type = VAR_UNKNOWN; - return call_callback(&eva->eva_callback, -1, tv, 0, argv); - } - - /* - * Like evalarg_call(), but just return TRUE of FALSE. - * Sets "error" to TRUE if evaluation failed. - */ - int - evalarg_call_bool(evalarg_T *eva, int *error) - { - typval_T tv; - int r; - - if (evalarg_call(eva, &tv) == FAIL) - { - *error = TRUE; - return FALSE; - } - r = tv_get_number(&tv); - clear_tv(&tv); - *error = FALSE; - return r; - } - - void - evalarg_clean(evalarg_T *eva) - { - if (eva->eva_string == NULL) - free_callback(&eva->eva_callback); - } - #endif // FEAT_EVAL --- 3811,3814 ---- *** ../vim-8.2.0917/src/proto/evalvars.pro 2020-06-06 18:37:47.864138502 +0200 --- src/proto/evalvars.pro 2020-06-07 14:30:48.389984199 +0200 *************** *** 88,96 **** void put_callback(callback_T *cb, typval_T *tv); void set_callback(callback_T *dest, callback_T *src); void free_callback(callback_T *callback); - int evalarg_get(typval_T *tv, evalarg_T *eva); - int evalarg_valid(evalarg_T *eva); - int evalarg_call(evalarg_T *eva, typval_T *tv); - int evalarg_call_bool(evalarg_T *eva, int *error); - void evalarg_clean(evalarg_T *eva); /* vim: set ft=c : */ --- 88,91 ---- *** ../vim-8.2.0917/src/structs.h 2020-06-06 18:37:47.860138513 +0200 --- src/structs.h 2020-06-07 14:30:18.334310727 +0200 *************** *** 4130,4149 **** int sa_wrapped; // search wrapped around } searchit_arg_T; - /* - * Function argument that can be a string, funcref or partial. - * - declare: evalarg_T name; - * - init: CLEAR_FIELD(name); - * - set: evalarg_get(&argvars[3], &name); - * - use: if (evalarg_valid(&name)) res = evalarg_call(&name); - * - cleanup: evalarg_clean(&name); - */ - typedef struct - { - char_u eva_buf[NUMBUFLEN]; // buffer for get_tv_string_buf() - char_u *eva_string; - callback_T eva_callback; - } evalarg_T; #define WRITEBUFSIZE 8192 // size of normal write buffer --- 4130,4135 ---- *** ../vim-8.2.0917/src/version.c 2020-06-07 14:10:34.900126463 +0200 --- src/version.c 2020-06-07 14:30:31.586163598 +0200 *************** *** 756,757 **** --- 756,759 ---- { /* Add new patch number below this line */ + /**/ + 918, /**/ -- GALAHAD hurries to the door and pushes through it. As he leaves the room we CUT TO the reverse to show that he is now in a room full of bathing and romping GIRLIES, all innocent, wide-eyed and beautiful. They smile enchantingly at him as he tries to keep walking without being diverted by the lovely sights assaulting his eyeballs. "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///