Mercurial > vim
comparison src/evalfunc.c @ 12248:f9de19f981a4 v8.0.1004
patch 8.0.1004: matchstrpos() without a match returns too many items
commit https://github.com/vim/vim/commit/8d9f0ef5c6a6f6d19c3d02690e1ee347a70b8452
Author: Bram Moolenaar <Bram@vim.org>
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.
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Sun, 27 Aug 2017 14:00:05 +0200 |
parents | abd69cea3459 |
children | 3d0e042ec13c |
comparison
equal
deleted
inserted
replaced
12247:e7de239b1e9f | 12248:f9de19f981a4 |
---|---|
7248 f_mapcheck(typval_T *argvars, typval_T *rettv) | 7248 f_mapcheck(typval_T *argvars, typval_T *rettv) |
7249 { | 7249 { |
7250 get_maparg(argvars, rettv, FALSE); | 7250 get_maparg(argvars, rettv, FALSE); |
7251 } | 7251 } |
7252 | 7252 |
7253 static void find_some_match(typval_T *argvars, typval_T *rettv, int start); | 7253 typedef enum |
7254 | 7254 { |
7255 static void | 7255 MATCH_END, /* matchend() */ |
7256 find_some_match(typval_T *argvars, typval_T *rettv, int type) | 7256 MATCH_MATCH, /* match() */ |
7257 MATCH_STR, /* matchstr() */ | |
7258 MATCH_LIST, /* matchlist() */ | |
7259 MATCH_POS /* matchstrpos() */ | |
7260 } matchtype_T; | |
7261 | |
7262 static void | |
7263 find_some_match(typval_T *argvars, typval_T *rettv, matchtype_T type) | |
7257 { | 7264 { |
7258 char_u *str = NULL; | 7265 char_u *str = NULL; |
7259 long len = 0; | 7266 long len = 0; |
7260 char_u *expr = NULL; | 7267 char_u *expr = NULL; |
7261 char_u *pat; | 7268 char_u *pat; |
7275 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */ | 7282 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */ |
7276 save_cpo = p_cpo; | 7283 save_cpo = p_cpo; |
7277 p_cpo = (char_u *)""; | 7284 p_cpo = (char_u *)""; |
7278 | 7285 |
7279 rettv->vval.v_number = -1; | 7286 rettv->vval.v_number = -1; |
7280 if (type == 3 || type == 4) | 7287 if (type == MATCH_LIST || type == MATCH_POS) |
7281 { | 7288 { |
7282 /* type 3: return empty list when there are no matches. | 7289 /* type MATCH_LIST: return empty list when there are no matches. |
7283 * type 4: return ["", -1, -1, -1] */ | 7290 * type MATCH_POS: return ["", -1, -1, -1] */ |
7284 if (rettv_list_alloc(rettv) == FAIL) | 7291 if (rettv_list_alloc(rettv) == FAIL) |
7285 goto theend; | 7292 goto theend; |
7286 if (type == 4 | 7293 if (type == MATCH_POS |
7287 && (list_append_string(rettv->vval.v_list, | 7294 && (list_append_string(rettv->vval.v_list, |
7288 (char_u *)"", 0) == FAIL | 7295 (char_u *)"", 0) == FAIL |
7289 || list_append_number(rettv->vval.v_list, | 7296 || list_append_number(rettv->vval.v_list, |
7290 (varnumber_T)-1) == FAIL | 7297 (varnumber_T)-1) == FAIL |
7291 || list_append_number(rettv->vval.v_list, | 7298 || list_append_number(rettv->vval.v_list, |
7296 list_free(rettv->vval.v_list); | 7303 list_free(rettv->vval.v_list); |
7297 rettv->vval.v_list = NULL; | 7304 rettv->vval.v_list = NULL; |
7298 goto theend; | 7305 goto theend; |
7299 } | 7306 } |
7300 } | 7307 } |
7301 else if (type == 2) | 7308 else if (type == MATCH_STR) |
7302 { | 7309 { |
7303 rettv->v_type = VAR_STRING; | 7310 rettv->v_type = VAR_STRING; |
7304 rettv->vval.v_string = NULL; | 7311 rettv->vval.v_string = NULL; |
7305 } | 7312 } |
7306 | 7313 |
7408 } | 7415 } |
7409 } | 7416 } |
7410 | 7417 |
7411 if (match) | 7418 if (match) |
7412 { | 7419 { |
7413 if (type == 4) | 7420 if (type == MATCH_POS) |
7414 { | 7421 { |
7415 listitem_T *li1 = rettv->vval.v_list->lv_first; | 7422 listitem_T *li1 = rettv->vval.v_list->lv_first; |
7416 listitem_T *li2 = li1->li_next; | 7423 listitem_T *li2 = li1->li_next; |
7417 listitem_T *li3 = li2->li_next; | 7424 listitem_T *li3 = li2->li_next; |
7418 listitem_T *li4 = li3->li_next; | 7425 listitem_T *li4 = li3->li_next; |
7425 li4->li_tv.vval.v_number = | 7432 li4->li_tv.vval.v_number = |
7426 (varnumber_T)(regmatch.endp[0] - expr); | 7433 (varnumber_T)(regmatch.endp[0] - expr); |
7427 if (l != NULL) | 7434 if (l != NULL) |
7428 li2->li_tv.vval.v_number = (varnumber_T)idx; | 7435 li2->li_tv.vval.v_number = (varnumber_T)idx; |
7429 } | 7436 } |
7430 else if (type == 3) | 7437 else if (type == MATCH_LIST) |
7431 { | 7438 { |
7432 int i; | 7439 int i; |
7433 | 7440 |
7434 /* return list with matched string and submatches */ | 7441 /* return list with matched string and submatches */ |
7435 for (i = 0; i < NSUBEXP; ++i) | 7442 for (i = 0; i < NSUBEXP; ++i) |
7445 (int)(regmatch.endp[i] - regmatch.startp[i])) | 7452 (int)(regmatch.endp[i] - regmatch.startp[i])) |
7446 == FAIL) | 7453 == FAIL) |
7447 break; | 7454 break; |
7448 } | 7455 } |
7449 } | 7456 } |
7450 else if (type == 2) | 7457 else if (type == MATCH_STR) |
7451 { | 7458 { |
7452 /* return matched string */ | 7459 /* return matched string */ |
7453 if (l != NULL) | 7460 if (l != NULL) |
7454 copy_tv(&li->li_tv, rettv); | 7461 copy_tv(&li->li_tv, rettv); |
7455 else | 7462 else |
7458 } | 7465 } |
7459 else if (l != NULL) | 7466 else if (l != NULL) |
7460 rettv->vval.v_number = idx; | 7467 rettv->vval.v_number = idx; |
7461 else | 7468 else |
7462 { | 7469 { |
7463 if (type != 0) | 7470 if (type != MATCH_END) |
7464 rettv->vval.v_number = | 7471 rettv->vval.v_number = |
7465 (varnumber_T)(regmatch.startp[0] - str); | 7472 (varnumber_T)(regmatch.startp[0] - str); |
7466 else | 7473 else |
7467 rettv->vval.v_number = | 7474 rettv->vval.v_number = |
7468 (varnumber_T)(regmatch.endp[0] - str); | 7475 (varnumber_T)(regmatch.endp[0] - str); |
7470 } | 7477 } |
7471 } | 7478 } |
7472 vim_regfree(regmatch.regprog); | 7479 vim_regfree(regmatch.regprog); |
7473 } | 7480 } |
7474 | 7481 |
7475 if (type == 4 && l == NULL) | 7482 theend: |
7483 if (type == MATCH_POS && l == NULL && rettv->vval.v_list != NULL) | |
7476 /* matchstrpos() without a list: drop the second item. */ | 7484 /* matchstrpos() without a list: drop the second item. */ |
7477 listitem_remove(rettv->vval.v_list, | 7485 listitem_remove(rettv->vval.v_list, |
7478 rettv->vval.v_list->lv_first->li_next); | 7486 rettv->vval.v_list->lv_first->li_next); |
7479 | |
7480 theend: | |
7481 vim_free(tofree); | 7487 vim_free(tofree); |
7482 p_cpo = save_cpo; | 7488 p_cpo = save_cpo; |
7483 } | 7489 } |
7484 | 7490 |
7485 /* | 7491 /* |
7486 * "match()" function | 7492 * "match()" function |
7487 */ | 7493 */ |
7488 static void | 7494 static void |
7489 f_match(typval_T *argvars, typval_T *rettv) | 7495 f_match(typval_T *argvars, typval_T *rettv) |
7490 { | 7496 { |
7491 find_some_match(argvars, rettv, 1); | 7497 find_some_match(argvars, rettv, MATCH_MATCH); |
7492 } | 7498 } |
7493 | 7499 |
7494 /* | 7500 /* |
7495 * "matchadd()" function | 7501 * "matchadd()" function |
7496 */ | 7502 */ |
7654 * "matchend()" function | 7660 * "matchend()" function |
7655 */ | 7661 */ |
7656 static void | 7662 static void |
7657 f_matchend(typval_T *argvars, typval_T *rettv) | 7663 f_matchend(typval_T *argvars, typval_T *rettv) |
7658 { | 7664 { |
7659 find_some_match(argvars, rettv, 0); | 7665 find_some_match(argvars, rettv, MATCH_END); |
7660 } | 7666 } |
7661 | 7667 |
7662 /* | 7668 /* |
7663 * "matchlist()" function | 7669 * "matchlist()" function |
7664 */ | 7670 */ |
7665 static void | 7671 static void |
7666 f_matchlist(typval_T *argvars, typval_T *rettv) | 7672 f_matchlist(typval_T *argvars, typval_T *rettv) |
7667 { | 7673 { |
7668 find_some_match(argvars, rettv, 3); | 7674 find_some_match(argvars, rettv, MATCH_LIST); |
7669 } | 7675 } |
7670 | 7676 |
7671 /* | 7677 /* |
7672 * "matchstr()" function | 7678 * "matchstr()" function |
7673 */ | 7679 */ |
7674 static void | 7680 static void |
7675 f_matchstr(typval_T *argvars, typval_T *rettv) | 7681 f_matchstr(typval_T *argvars, typval_T *rettv) |
7676 { | 7682 { |
7677 find_some_match(argvars, rettv, 2); | 7683 find_some_match(argvars, rettv, MATCH_STR); |
7678 } | 7684 } |
7679 | 7685 |
7680 /* | 7686 /* |
7681 * "matchstrpos()" function | 7687 * "matchstrpos()" function |
7682 */ | 7688 */ |
7683 static void | 7689 static void |
7684 f_matchstrpos(typval_T *argvars, typval_T *rettv) | 7690 f_matchstrpos(typval_T *argvars, typval_T *rettv) |
7685 { | 7691 { |
7686 find_some_match(argvars, rettv, 4); | 7692 find_some_match(argvars, rettv, MATCH_POS); |
7687 } | 7693 } |
7688 | 7694 |
7689 static void max_min(typval_T *argvars, typval_T *rettv, int domax); | 7695 static void max_min(typval_T *argvars, typval_T *rettv, int domax); |
7690 | 7696 |
7691 static void | 7697 static void |