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