# HG changeset patch # User Christian Brabandt # Date 1503835205 -7200 # Node ID f9de19f981a4d77e3fe4c893a94c623a2c0936fa # Parent e7de239b1e9f2c6a88091c54ecf704c593f26358 patch 8.0.1004: matchstrpos() without a match returns too many items commit https://github.com/vim/vim/commit/8d9f0ef5c6a6f6d19c3d02690e1ee347a70b8452 Author: Bram Moolenaar Date: Sun Aug 27 13:51:01 2017 +0200 patch 8.0.1004: matchstrpos() without a match returns too many items Problem: Matchstrpos() without a match returns too many items. Solution: Also remove the second item when the position is beyond the end of the string. (Hirohito Higashi) Use an enum for the type. diff --git a/src/evalfunc.c b/src/evalfunc.c --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -7250,10 +7250,17 @@ f_mapcheck(typval_T *argvars, typval_T * get_maparg(argvars, rettv, FALSE); } -static void find_some_match(typval_T *argvars, typval_T *rettv, int start); - - static void -find_some_match(typval_T *argvars, typval_T *rettv, int type) +typedef enum +{ + MATCH_END, /* matchend() */ + MATCH_MATCH, /* match() */ + MATCH_STR, /* matchstr() */ + MATCH_LIST, /* matchlist() */ + MATCH_POS /* matchstrpos() */ +} matchtype_T; + + static void +find_some_match(typval_T *argvars, typval_T *rettv, matchtype_T type) { char_u *str = NULL; long len = 0; @@ -7277,13 +7284,13 @@ find_some_match(typval_T *argvars, typva p_cpo = (char_u *)""; rettv->vval.v_number = -1; - if (type == 3 || type == 4) - { - /* type 3: return empty list when there are no matches. - * type 4: return ["", -1, -1, -1] */ + if (type == MATCH_LIST || type == MATCH_POS) + { + /* type MATCH_LIST: return empty list when there are no matches. + * type MATCH_POS: return ["", -1, -1, -1] */ if (rettv_list_alloc(rettv) == FAIL) goto theend; - if (type == 4 + if (type == MATCH_POS && (list_append_string(rettv->vval.v_list, (char_u *)"", 0) == FAIL || list_append_number(rettv->vval.v_list, @@ -7298,7 +7305,7 @@ find_some_match(typval_T *argvars, typva goto theend; } } - else if (type == 2) + else if (type == MATCH_STR) { rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; @@ -7410,7 +7417,7 @@ find_some_match(typval_T *argvars, typva if (match) { - if (type == 4) + if (type == MATCH_POS) { listitem_T *li1 = rettv->vval.v_list->lv_first; listitem_T *li2 = li1->li_next; @@ -7427,7 +7434,7 @@ find_some_match(typval_T *argvars, typva if (l != NULL) li2->li_tv.vval.v_number = (varnumber_T)idx; } - else if (type == 3) + else if (type == MATCH_LIST) { int i; @@ -7447,7 +7454,7 @@ find_some_match(typval_T *argvars, typva break; } } - else if (type == 2) + else if (type == MATCH_STR) { /* return matched string */ if (l != NULL) @@ -7460,7 +7467,7 @@ find_some_match(typval_T *argvars, typva rettv->vval.v_number = idx; else { - if (type != 0) + if (type != MATCH_END) rettv->vval.v_number = (varnumber_T)(regmatch.startp[0] - str); else @@ -7472,12 +7479,11 @@ find_some_match(typval_T *argvars, typva vim_regfree(regmatch.regprog); } - if (type == 4 && l == NULL) +theend: + if (type == MATCH_POS && l == NULL && rettv->vval.v_list != NULL) /* matchstrpos() without a list: drop the second item. */ listitem_remove(rettv->vval.v_list, rettv->vval.v_list->lv_first->li_next); - -theend: vim_free(tofree); p_cpo = save_cpo; } @@ -7488,7 +7494,7 @@ theend: static void f_match(typval_T *argvars, typval_T *rettv) { - find_some_match(argvars, rettv, 1); + find_some_match(argvars, rettv, MATCH_MATCH); } /* @@ -7656,7 +7662,7 @@ f_matchdelete(typval_T *argvars UNUSED, static void f_matchend(typval_T *argvars, typval_T *rettv) { - find_some_match(argvars, rettv, 0); + find_some_match(argvars, rettv, MATCH_END); } /* @@ -7665,7 +7671,7 @@ f_matchend(typval_T *argvars, typval_T * static void f_matchlist(typval_T *argvars, typval_T *rettv) { - find_some_match(argvars, rettv, 3); + find_some_match(argvars, rettv, MATCH_LIST); } /* @@ -7674,7 +7680,7 @@ f_matchlist(typval_T *argvars, typval_T static void f_matchstr(typval_T *argvars, typval_T *rettv) { - find_some_match(argvars, rettv, 2); + find_some_match(argvars, rettv, MATCH_STR); } /* @@ -7683,7 +7689,7 @@ f_matchstr(typval_T *argvars, typval_T * static void f_matchstrpos(typval_T *argvars, typval_T *rettv) { - find_some_match(argvars, rettv, 4); + find_some_match(argvars, rettv, MATCH_POS); } static void max_min(typval_T *argvars, typval_T *rettv, int domax); diff --git a/src/testdir/test_match.vim b/src/testdir/test_match.vim --- a/src/testdir/test_match.vim +++ b/src/testdir/test_match.vim @@ -152,13 +152,10 @@ endfunc func Test_matchstrpos() call assert_equal(['ing', 4, 7], matchstrpos('testing', 'ing')) - call assert_equal(['ing', 4, 7], matchstrpos('testing', 'ing', 2)) - call assert_equal(['', -1, -1], matchstrpos('testing', 'ing', 5)) - + call assert_equal(['', -1, -1], matchstrpos('testing', 'ing', 8)) call assert_equal(['ing', 1, 4, 7], matchstrpos(['vim', 'testing', 'execute'], 'ing')) - call assert_equal(['', -1, -1, -1], matchstrpos(['vim', 'testing', 'execute'], 'img')) endfunc diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -770,6 +770,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1004, +/**/ 1003, /**/ 1002,