To: vim_dev@googlegroups.com Subject: Patch 8.0.0020 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.0.0020 Problem: The regexp engines are not reentrant. Solution: Add regexec_T and save/restore the state when needed. Files: src/regexp.c, src/regexp_nfa.c, src/testdir/test_expr.vim, runtime/doc/eval.txt, runtime/doc/change.txt *** ../vim-8.0.0019/src/regexp.c 2016-09-09 20:20:20.000000000 +0200 --- src/regexp.c 2016-10-02 16:21:22.709068952 +0200 *************** *** 3509,3535 **** #endif /* - * Internal copy of 'ignorecase'. It is set at each call to vim_regexec(). - * Normally it gets the value of "rm_ic" or "rmm_ic", but when the pattern - * contains '\c' or '\C' the value is overruled. - */ - static int ireg_ic; - - #ifdef FEAT_MBYTE - /* - * Similar to ireg_ic, but only for 'combining' characters. Set with \Z flag - * in the regexp. Defaults to false, always. - */ - static int ireg_icombine; - #endif - - /* - * Copy of "rmm_maxcol": maximum column to search for a match. Zero when - * there is no maximum. - */ - static colnr_T ireg_maxcol; - - /* * Sometimes need to save a copy of a line. Since alloc()/free() is very * slow, we keep one allocated piece of memory and only re-allocate it when * it's too small. It's freed in bt_regexec_both() when finished. --- 3509,3514 ---- *************** *** 3538,3544 **** static unsigned reg_tofreelen; /* ! * These variables are set when executing a regexp to speed up the execution. * Which ones are set depends on whether a single-line or multi-line match is * done: * single-line multi-line --- 3517,3523 ---- static unsigned reg_tofreelen; /* ! * Structure used to store the execution state of the regex engine. * Which ones are set depends on whether a single-line or multi-line match is * done: * single-line multi-line *************** *** 3554,3570 **** * reg_maxline 0 last line nr * reg_line_lbr FALSE or TRUE FALSE */ ! static regmatch_T *reg_match; ! static regmmatch_T *reg_mmatch; ! static char_u **reg_startp = NULL; ! static char_u **reg_endp = NULL; ! static lpos_T *reg_startpos = NULL; ! static lpos_T *reg_endpos = NULL; ! static win_T *reg_win; ! static buf_T *reg_buf; ! static linenr_T reg_firstlnum; ! static linenr_T reg_maxline; ! static int reg_line_lbr; /* "\n" in string is line break */ /* Values for rs_state in regitem_T. */ typedef enum regstate_E --- 3533,3570 ---- * reg_maxline 0 last line nr * reg_line_lbr FALSE or TRUE FALSE */ ! typedef struct { ! regmatch_T *reg_match; ! regmmatch_T *reg_mmatch; ! char_u **reg_startp; ! char_u **reg_endp; ! lpos_T *reg_startpos; ! lpos_T *reg_endpos; ! win_T *reg_win; ! buf_T *reg_buf; ! linenr_T reg_firstlnum; ! linenr_T reg_maxline; ! int reg_line_lbr; /* "\n" in string is line break */ ! ! /* Internal copy of 'ignorecase'. It is set at each call to vim_regexec(). ! * Normally it gets the value of "rm_ic" or "rmm_ic", but when the pattern ! * contains '\c' or '\C' the value is overruled. */ ! int reg_ic; ! ! #ifdef FEAT_MBYTE ! /* Similar to rex.reg_ic, but only for 'combining' characters. Set with \Z ! * flag in the regexp. Defaults to false, always. */ ! int reg_icombine; ! #endif ! ! /* Copy of "rmm_maxcol": maximum column to search for a match. Zero when ! * there is no maximum. */ ! colnr_T reg_maxcol; ! } regexec_T; ! ! static regexec_T rex; ! static int rex_in_use = FALSE; ! /* Values for rs_state in regitem_T. */ typedef enum regstate_E *************** *** 3669,3680 **** { /* when looking behind for a match/no-match lnum is negative. But we * can't go before line 1 */ ! if (reg_firstlnum + lnum < 1) return NULL; ! if (lnum > reg_maxline) /* Must have matched the "\n" in the last line. */ return (char_u *)""; ! return ml_get_buf(reg_buf, reg_firstlnum + lnum, FALSE); } static regsave_T behind_pos; --- 3669,3680 ---- { /* when looking behind for a match/no-match lnum is negative. But we * can't go before line 1 */ ! if (rex.reg_firstlnum + lnum < 1) return NULL; ! if (lnum > rex.reg_maxline) /* Must have matched the "\n" in the last line. */ return (char_u *)""; ! return ml_get_buf(rex.reg_buf, rex.reg_firstlnum + lnum, FALSE); } static regsave_T behind_pos; *************** *** 3687,3696 **** #endif /* TRUE if using multi-line regexp. */ ! #define REG_MULTI (reg_match == NULL) ! ! static int bt_regexec_nl(regmatch_T *rmp, char_u *line, colnr_T col, int line_lbr); ! /* * Match a regexp against a string. --- 3687,3693 ---- #endif /* TRUE if using multi-line regexp. */ ! #define REG_MULTI (rex.reg_match == NULL) /* * Match a regexp against a string. *************** *** 3707,3729 **** colnr_T col, /* column to start looking for match */ int line_lbr) { ! reg_match = rmp; ! reg_mmatch = NULL; ! reg_maxline = 0; ! reg_line_lbr = line_lbr; ! reg_buf = curbuf; ! reg_win = NULL; ! ireg_ic = rmp->rm_ic; #ifdef FEAT_MBYTE ! ireg_icombine = FALSE; #endif ! ireg_maxcol = 0; return bt_regexec_both(line, col, NULL); } - static long bt_regexec_multi(regmmatch_T *rmp, win_T *win, buf_T *buf, linenr_T lnum, colnr_T col, proftime_T *tm); - /* * Match a regexp against multiple lines. * "rmp->regprog" is a compiled regexp as returned by vim_regcomp(). --- 3704,3724 ---- colnr_T col, /* column to start looking for match */ int line_lbr) { ! rex.reg_match = rmp; ! rex.reg_mmatch = NULL; ! rex.reg_maxline = 0; ! rex.reg_line_lbr = line_lbr; ! rex.reg_buf = curbuf; ! rex.reg_win = NULL; ! rex.reg_ic = rmp->rm_ic; #ifdef FEAT_MBYTE ! rex.reg_icombine = FALSE; #endif ! rex.reg_maxcol = 0; return bt_regexec_both(line, col, NULL); } /* * Match a regexp against multiple lines. * "rmp->regprog" is a compiled regexp as returned by vim_regcomp(). *************** *** 3741,3758 **** colnr_T col, /* column to start looking for match */ proftime_T *tm) /* timeout limit or NULL */ { ! reg_match = NULL; ! reg_mmatch = rmp; ! reg_buf = buf; ! reg_win = win; ! reg_firstlnum = lnum; ! reg_maxline = reg_buf->b_ml.ml_line_count - lnum; ! reg_line_lbr = FALSE; ! ireg_ic = rmp->rmm_ic; #ifdef FEAT_MBYTE ! ireg_icombine = FALSE; #endif ! ireg_maxcol = rmp->rmm_maxcol; return bt_regexec_both(NULL, col, tm); } --- 3736,3753 ---- colnr_T col, /* column to start looking for match */ proftime_T *tm) /* timeout limit or NULL */ { ! rex.reg_match = NULL; ! rex.reg_mmatch = rmp; ! rex.reg_buf = buf; ! rex.reg_win = win; ! rex.reg_firstlnum = lnum; ! rex.reg_maxline = rex.reg_buf->b_ml.ml_line_count - lnum; ! rex.reg_line_lbr = FALSE; ! rex.reg_ic = rmp->rmm_ic; #ifdef FEAT_MBYTE ! rex.reg_icombine = FALSE; #endif ! rex.reg_maxcol = rmp->rmm_maxcol; return bt_regexec_both(NULL, col, tm); } *************** *** 3794,3809 **** if (REG_MULTI) { ! prog = (bt_regprog_T *)reg_mmatch->regprog; line = reg_getline((linenr_T)0); ! reg_startpos = reg_mmatch->startpos; ! reg_endpos = reg_mmatch->endpos; } else { ! prog = (bt_regprog_T *)reg_match->regprog; ! reg_startp = reg_match->startp; ! reg_endp = reg_match->endp; } /* Be paranoid... */ --- 3789,3804 ---- if (REG_MULTI) { ! prog = (bt_regprog_T *)rex.reg_mmatch->regprog; line = reg_getline((linenr_T)0); ! rex.reg_startpos = rex.reg_mmatch->startpos; ! rex.reg_endpos = rex.reg_mmatch->endpos; } else { ! prog = (bt_regprog_T *)rex.reg_match->regprog; ! rex.reg_startp = rex.reg_match->startp; ! rex.reg_endp = rex.reg_match->endp; } /* Be paranoid... */ *************** *** 3818,3836 **** goto theend; /* If the start column is past the maximum column: no need to try. */ ! if (ireg_maxcol > 0 && col >= ireg_maxcol) goto theend; ! /* If pattern contains "\c" or "\C": overrule value of ireg_ic */ if (prog->regflags & RF_ICASE) ! ireg_ic = TRUE; else if (prog->regflags & RF_NOICASE) ! ireg_ic = FALSE; #ifdef FEAT_MBYTE ! /* If pattern contains "\Z" overrule value of ireg_icombine */ if (prog->regflags & RF_ICOMBINE) ! ireg_icombine = TRUE; #endif /* If there is a "must appear" string, look for it. */ --- 3813,3831 ---- goto theend; /* If the start column is past the maximum column: no need to try. */ ! if (rex.reg_maxcol > 0 && col >= rex.reg_maxcol) goto theend; ! /* If pattern contains "\c" or "\C": overrule value of rex.reg_ic */ if (prog->regflags & RF_ICASE) ! rex.reg_ic = TRUE; else if (prog->regflags & RF_NOICASE) ! rex.reg_ic = FALSE; #ifdef FEAT_MBYTE ! /* If pattern contains "\Z" overrule value of rex.reg_icombine */ if (prog->regflags & RF_ICOMBINE) ! rex.reg_icombine = TRUE; #endif /* If there is a "must appear" string, look for it. */ *************** *** 3850,3856 **** * This is used very often, esp. for ":global". Use three versions of * the loop to avoid overhead of conditions. */ ! if (!ireg_ic #ifdef FEAT_MBYTE && !has_mbyte #endif --- 3845,3851 ---- * This is used very often, esp. for ":global". Use three versions of * the loop to avoid overhead of conditions. */ ! if (!rex.reg_ic #ifdef FEAT_MBYTE && !has_mbyte #endif *************** *** 3862,3868 **** ++s; } #ifdef FEAT_MBYTE ! else if (!ireg_ic || (!enc_utf8 && mb_char2len(c) > 1)) while ((s = vim_strchr(s, c)) != NULL) { if (cstrncmp(s, prog->regmust, &prog->regmlen) == 0) --- 3857,3863 ---- ++s; } #ifdef FEAT_MBYTE ! else if (!rex.reg_ic || (!enc_utf8 && mb_char2len(c) > 1)) while ((s = vim_strchr(s, c)) != NULL) { if (cstrncmp(s, prog->regmust, &prog->regmlen) == 0) *************** *** 3898,3904 **** c = regline[col]; if (prog->regstart == NUL || prog->regstart == c ! || (ireg_ic && (( #ifdef FEAT_MBYTE (enc_utf8 && utf_fold(prog->regstart) == utf_fold(c))) || (c < 255 && prog->regstart < 255 && --- 3893,3899 ---- c = regline[col]; if (prog->regstart == NUL || prog->regstart == c ! || (rex.reg_ic && (( #ifdef FEAT_MBYTE (enc_utf8 && utf_fold(prog->regstart) == utf_fold(c))) || (c < 255 && prog->regstart < 255 && *************** *** 3920,3926 **** { /* Skip until the char we know it must start with. * Used often, do some work to avoid call overhead. */ ! if (!ireg_ic #ifdef FEAT_MBYTE && !has_mbyte #endif --- 3915,3921 ---- { /* Skip until the char we know it must start with. * Used often, do some work to avoid call overhead. */ ! if (!rex.reg_ic #ifdef FEAT_MBYTE && !has_mbyte #endif *************** *** 3937,3943 **** } /* Check for maximum column to try. */ ! if (ireg_maxcol > 0 && col >= ireg_maxcol) { retval = 0; break; --- 3932,3938 ---- } /* Check for maximum column to try. */ ! if (rex.reg_maxcol > 0 && col >= rex.reg_maxcol) { retval = 0; break; *************** *** 4056,4081 **** cleanup_subexpr(); if (REG_MULTI) { ! if (reg_startpos[0].lnum < 0) { ! reg_startpos[0].lnum = 0; ! reg_startpos[0].col = col; } ! if (reg_endpos[0].lnum < 0) { ! reg_endpos[0].lnum = reglnum; ! reg_endpos[0].col = (int)(reginput - regline); } else /* Use line number of "\ze". */ ! reglnum = reg_endpos[0].lnum; } else { ! if (reg_startp[0] == NULL) ! reg_startp[0] = regline + col; ! if (reg_endp[0] == NULL) ! reg_endp[0] = reginput; } #ifdef FEAT_SYN_HL /* Package any found \z(...\) matches for export. Default is none. */ --- 4051,4076 ---- cleanup_subexpr(); if (REG_MULTI) { ! if (rex.reg_startpos[0].lnum < 0) { ! rex.reg_startpos[0].lnum = 0; ! rex.reg_startpos[0].col = col; } ! if (rex.reg_endpos[0].lnum < 0) { ! rex.reg_endpos[0].lnum = reglnum; ! rex.reg_endpos[0].col = (int)(reginput - regline); } else /* Use line number of "\ze". */ ! reglnum = rex.reg_endpos[0].lnum; } else { ! if (rex.reg_startp[0] == NULL) ! rex.reg_startp[0] = regline + col; ! if (rex.reg_endp[0] == NULL) ! rex.reg_endp[0] = reginput; } #ifdef FEAT_SYN_HL /* Package any found \z(...\) matches for export. Default is none. */ *************** *** 4125,4131 **** { if (reginput > regline) return mb_get_class_buf(reginput - 1 ! - (*mb_head_off)(regline, reginput - 1), reg_buf); return -1; } #endif --- 4120,4126 ---- { if (reginput > regline) return mb_get_class_buf(reginput - 1 ! - (*mb_head_off)(regline, reginput - 1), rex.reg_buf); return -1; } #endif *************** *** 4141,4154 **** pos_T top, bot; linenr_T lnum; colnr_T col; ! win_T *wp = reg_win == NULL ? curwin : reg_win; int mode; colnr_T start, end; colnr_T start2, end2; colnr_T cols; /* Check if the buffer is the current buffer. */ ! if (reg_buf != curbuf || VIsual.lnum == 0) return FALSE; if (VIsual_active) --- 4136,4149 ---- pos_T top, bot; linenr_T lnum; colnr_T col; ! win_T *wp = rex.reg_win == NULL ? curwin : rex.reg_win; int mode; colnr_T start, end; colnr_T start2, end2; colnr_T cols; /* Check if the buffer is the current buffer. */ ! if (rex.reg_buf != curbuf || VIsual.lnum == 0) return FALSE; if (VIsual_active) *************** *** 4179,4185 **** } mode = curbuf->b_visual.vi_mode; } ! lnum = reglnum + reg_firstlnum; if (lnum < top.lnum || lnum > bot.lnum) return FALSE; --- 4174,4180 ---- } mode = curbuf->b_visual.vi_mode; } ! lnum = reglnum + rex.reg_firstlnum; if (lnum < top.lnum || lnum > bot.lnum) return FALSE; *************** *** 4309,4320 **** op = OP(scan); /* Check for character class with NL added. */ ! if (!reg_line_lbr && WITH_NL(op) && REG_MULTI ! && *reginput == NUL && reglnum <= reg_maxline) { reg_nextline(); } ! else if (reg_line_lbr && WITH_NL(op) && *reginput == '\n') { ADVANCE_REGINPUT(); } --- 4304,4315 ---- op = OP(scan); /* Check for character class with NL added. */ ! if (!rex.reg_line_lbr && WITH_NL(op) && REG_MULTI ! && *reginput == NUL && reglnum <= rex.reg_maxline) { reg_nextline(); } ! else if (rex.reg_line_lbr && WITH_NL(op) && *reginput == '\n') { ADVANCE_REGINPUT(); } *************** *** 4345,4365 **** * line where we started, not at the start of the line or we * didn't start at the first line of the buffer. */ if (reglnum != 0 || reginput != regline ! || (REG_MULTI && reg_firstlnum > 1)) status = RA_NOMATCH; break; case RE_EOF: ! if (reglnum != reg_maxline || c != NUL) status = RA_NOMATCH; break; case CURSOR: /* Check if the buffer is in a window and compare the ! * reg_win->w_cursor position to the match position. */ ! if (reg_win == NULL ! || (reglnum + reg_firstlnum != reg_win->w_cursor.lnum) ! || ((colnr_T)(reginput - regline) != reg_win->w_cursor.col)) status = RA_NOMATCH; break; --- 4340,4362 ---- * line where we started, not at the start of the line or we * didn't start at the first line of the buffer. */ if (reglnum != 0 || reginput != regline ! || (REG_MULTI && rex.reg_firstlnum > 1)) status = RA_NOMATCH; break; case RE_EOF: ! if (reglnum != rex.reg_maxline || c != NUL) status = RA_NOMATCH; break; case CURSOR: /* Check if the buffer is in a window and compare the ! * rex.reg_win->w_cursor position to the match position. */ ! if (rex.reg_win == NULL ! || (reglnum + rex.reg_firstlnum ! != rex.reg_win->w_cursor.lnum) ! || ((colnr_T)(reginput - regline) ! != rex.reg_win->w_cursor.col)) status = RA_NOMATCH; break; *************** *** 4370,4385 **** int cmp = OPERAND(scan)[1]; pos_T *pos; ! pos = getmark_buf(reg_buf, mark, FALSE); if (pos == NULL /* mark doesn't exist */ || pos->lnum <= 0 /* mark isn't set in reg_buf */ ! || (pos->lnum == reglnum + reg_firstlnum ? (pos->col == (colnr_T)(reginput - regline) ? (cmp == '<' || cmp == '>') : (pos->col < (colnr_T)(reginput - regline) ? cmp != '>' : cmp != '<')) ! : (pos->lnum < reglnum + reg_firstlnum ? cmp != '>' : cmp != '<'))) status = RA_NOMATCH; --- 4367,4382 ---- int cmp = OPERAND(scan)[1]; pos_T *pos; ! pos = getmark_buf(rex.reg_buf, mark, FALSE); if (pos == NULL /* mark doesn't exist */ || pos->lnum <= 0 /* mark isn't set in reg_buf */ ! || (pos->lnum == reglnum + rex.reg_firstlnum ? (pos->col == (colnr_T)(reginput - regline) ? (cmp == '<' || cmp == '>') : (pos->col < (colnr_T)(reginput - regline) ? cmp != '>' : cmp != '<')) ! : (pos->lnum < reglnum + rex.reg_firstlnum ? cmp != '>' : cmp != '<'))) status = RA_NOMATCH; *************** *** 4392,4398 **** break; case RE_LNUM: ! if (!REG_MULTI || !re_num_cmp((long_u)(reglnum + reg_firstlnum), scan)) status = RA_NOMATCH; break; --- 4389,4395 ---- break; case RE_LNUM: ! if (!REG_MULTI || !re_num_cmp((long_u)(reglnum + rex.reg_firstlnum), scan)) status = RA_NOMATCH; break; *************** *** 4404,4410 **** case RE_VCOL: if (!re_num_cmp((long_u)win_linetabsize( ! reg_win == NULL ? curwin : reg_win, regline, (colnr_T)(reginput - regline)) + 1, scan)) status = RA_NOMATCH; break; --- 4401,4407 ---- case RE_VCOL: if (!re_num_cmp((long_u)win_linetabsize( ! rex.reg_win == NULL ? curwin : rex.reg_win, regline, (colnr_T)(reginput - regline)) + 1, scan)) status = RA_NOMATCH; break; *************** *** 4418,4424 **** int this_class; /* Get class of current and previous char (if it exists). */ ! this_class = mb_get_class_buf(reginput, reg_buf); if (this_class <= 1) status = RA_NOMATCH; /* not on a word at all */ else if (reg_prev_class() == this_class) --- 4415,4421 ---- int this_class; /* Get class of current and previous char (if it exists). */ ! this_class = mb_get_class_buf(reginput, rex.reg_buf); if (this_class <= 1) status = RA_NOMATCH; /* not on a word at all */ else if (reg_prev_class() == this_class) *************** *** 4427,4434 **** #endif else { ! if (!vim_iswordc_buf(c, reg_buf) || (reginput > regline ! && vim_iswordc_buf(reginput[-1], reg_buf))) status = RA_NOMATCH; } break; --- 4424,4431 ---- #endif else { ! if (!vim_iswordc_buf(c, rex.reg_buf) || (reginput > regline ! && vim_iswordc_buf(reginput[-1], rex.reg_buf))) status = RA_NOMATCH; } break; *************** *** 4442,4448 **** int this_class, prev_class; /* Get class of current and previous char (if it exists). */ ! this_class = mb_get_class_buf(reginput, reg_buf); prev_class = reg_prev_class(); if (this_class == prev_class || prev_class == 0 || prev_class == 1) --- 4439,4445 ---- int this_class, prev_class; /* Get class of current and previous char (if it exists). */ ! this_class = mb_get_class_buf(reginput, rex.reg_buf); prev_class = reg_prev_class(); if (this_class == prev_class || prev_class == 0 || prev_class == 1) *************** *** 4451,4458 **** #endif else { ! if (!vim_iswordc_buf(reginput[-1], reg_buf) ! || (reginput[0] != NUL && vim_iswordc_buf(c, reg_buf))) status = RA_NOMATCH; } break; /* Matched with EOW */ --- 4448,4456 ---- #endif else { ! if (!vim_iswordc_buf(reginput[-1], rex.reg_buf) ! || (reginput[0] != NUL ! && vim_iswordc_buf(c, rex.reg_buf))) status = RA_NOMATCH; } break; /* Matched with EOW */ *************** *** 4480,4493 **** break; case KWORD: ! if (!vim_iswordp_buf(reginput, reg_buf)) status = RA_NOMATCH; else ADVANCE_REGINPUT(); break; case SKWORD: ! if (VIM_ISDIGIT(*reginput) || !vim_iswordp_buf(reginput, reg_buf)) status = RA_NOMATCH; else ADVANCE_REGINPUT(); --- 4478,4492 ---- break; case KWORD: ! if (!vim_iswordp_buf(reginput, rex.reg_buf)) status = RA_NOMATCH; else ADVANCE_REGINPUT(); break; case SKWORD: ! if (VIM_ISDIGIT(*reginput) ! || !vim_iswordp_buf(reginput, rex.reg_buf)) status = RA_NOMATCH; else ADVANCE_REGINPUT(); *************** *** 4655,4661 **** opnd = OPERAND(scan); /* Inline the first byte, for speed. */ if (*opnd != *reginput ! && (!ireg_ic || ( #ifdef FEAT_MBYTE !enc_utf8 && #endif --- 4654,4660 ---- opnd = OPERAND(scan); /* Inline the first byte, for speed. */ if (*opnd != *reginput ! && (!rex.reg_ic || ( #ifdef FEAT_MBYTE !enc_utf8 && #endif *************** *** 4670,4676 **** { if (opnd[1] == NUL #ifdef FEAT_MBYTE ! && !(enc_utf8 && ireg_ic) #endif ) { --- 4669,4675 ---- { if (opnd[1] == NUL #ifdef FEAT_MBYTE ! && !(enc_utf8 && rex.reg_ic) #endif ) { *************** *** 4689,4695 **** if (status != RA_NOMATCH && enc_utf8 && UTF_COMPOSINGLIKE(reginput, reginput + len) ! && !ireg_icombine && OP(next) != RE_COMPOSING) { /* raaron: This code makes a composing character get --- 4688,4694 ---- if (status != RA_NOMATCH && enc_utf8 && UTF_COMPOSINGLIKE(reginput, reginput + len) ! && !rex.reg_icombine && OP(next) != RE_COMPOSING) { /* raaron: This code makes a composing character get *************** *** 4840,4847 **** else { rp->rs_no = no; ! save_se(&rp->rs_un.sesave, ®_startpos[no], ! ®_startp[no]); /* We simply continue and handle the result when done. */ } } --- 4839,4846 ---- else { rp->rs_no = no; ! save_se(&rp->rs_un.sesave, &rex.reg_startpos[no], ! &rex.reg_startp[no]); /* We simply continue and handle the result when done. */ } } *************** *** 4900,4906 **** else { rp->rs_no = no; ! save_se(&rp->rs_un.sesave, ®_endpos[no], ®_endp[no]); /* We simply continue and handle the result when done. */ } } --- 4899,4906 ---- else { rp->rs_no = no; ! save_se(&rp->rs_un.sesave, &rex.reg_endpos[no], ! &rex.reg_endp[no]); /* We simply continue and handle the result when done. */ } } *************** *** 4949,4955 **** cleanup_subexpr(); if (!REG_MULTI) /* Single-line regexp */ { ! if (reg_startp[no] == NULL || reg_endp[no] == NULL) { /* Backref was not set: Match an empty string. */ len = 0; --- 4949,4955 ---- cleanup_subexpr(); if (!REG_MULTI) /* Single-line regexp */ { ! if (rex.reg_startp[no] == NULL || rex.reg_endp[no] == NULL) { /* Backref was not set: Match an empty string. */ len = 0; *************** *** 4958,4983 **** { /* Compare current input with back-ref in the same * line. */ ! len = (int)(reg_endp[no] - reg_startp[no]); ! if (cstrncmp(reg_startp[no], reginput, &len) != 0) status = RA_NOMATCH; } } else /* Multi-line regexp */ { ! if (reg_startpos[no].lnum < 0 || reg_endpos[no].lnum < 0) { /* Backref was not set: Match an empty string. */ len = 0; } else { ! if (reg_startpos[no].lnum == reglnum ! && reg_endpos[no].lnum == reglnum) { /* Compare back-ref within the current line. */ ! len = reg_endpos[no].col - reg_startpos[no].col; ! if (cstrncmp(regline + reg_startpos[no].col, reginput, &len) != 0) status = RA_NOMATCH; } --- 4958,4985 ---- { /* Compare current input with back-ref in the same * line. */ ! len = (int)(rex.reg_endp[no] - rex.reg_startp[no]); ! if (cstrncmp(rex.reg_startp[no], reginput, &len) != 0) status = RA_NOMATCH; } } else /* Multi-line regexp */ { ! if (rex.reg_startpos[no].lnum < 0 ! || rex.reg_endpos[no].lnum < 0) { /* Backref was not set: Match an empty string. */ len = 0; } else { ! if (rex.reg_startpos[no].lnum == reglnum ! && rex.reg_endpos[no].lnum == reglnum) { /* Compare back-ref within the current line. */ ! len = rex.reg_endpos[no].col ! - rex.reg_startpos[no].col; ! if (cstrncmp(regline + rex.reg_startpos[no].col, reginput, &len) != 0) status = RA_NOMATCH; } *************** *** 4986,4995 **** /* Messy situation: Need to compare between two * lines. */ int r = match_with_backref( ! reg_startpos[no].lnum, ! reg_startpos[no].col, ! reg_endpos[no].lnum, ! reg_endpos[no].col, &len); if (r != RA_MATCH) --- 4988,4997 ---- /* Messy situation: Need to compare between two * lines. */ int r = match_with_backref( ! rex.reg_startpos[no].lnum, ! rex.reg_startpos[no].col, ! rex.reg_endpos[no].lnum, ! rex.reg_endpos[no].col, &len); if (r != RA_MATCH) *************** *** 5154,5160 **** if (OP(next) == EXACTLY) { rst.nextb = *OPERAND(next); ! if (ireg_ic) { if (MB_ISUPPER(rst.nextb)) rst.nextb_ic = MB_TOLOWER(rst.nextb); --- 5156,5162 ---- if (OP(next) == EXACTLY) { rst.nextb = *OPERAND(next); ! if (rex.reg_ic) { if (MB_ISUPPER(rst.nextb)) rst.nextb_ic = MB_TOLOWER(rst.nextb); *************** *** 5282,5291 **** break; case NEWL: ! if ((c != NUL || !REG_MULTI || reglnum > reg_maxline ! || reg_line_lbr) && (c != '\n' || !reg_line_lbr)) status = RA_NOMATCH; ! else if (reg_line_lbr) ADVANCE_REGINPUT(); else reg_nextline(); --- 5284,5294 ---- break; case NEWL: ! if ((c != NUL || !REG_MULTI || reglnum > rex.reg_maxline ! || rex.reg_line_lbr) ! && (c != '\n' || !rex.reg_line_lbr)) status = RA_NOMATCH; ! else if (rex.reg_line_lbr) ADVANCE_REGINPUT(); else reg_nextline(); *************** *** 5331,5338 **** case RS_MOPEN: /* Pop the state. Restore pointers when there is no match. */ if (status == RA_NOMATCH) ! restore_se(&rp->rs_un.sesave, ®_startpos[rp->rs_no], ! ®_startp[rp->rs_no]); regstack_pop(&scan); break; --- 5334,5341 ---- case RS_MOPEN: /* Pop the state. Restore pointers when there is no match. */ if (status == RA_NOMATCH) ! restore_se(&rp->rs_un.sesave, &rex.reg_startpos[rp->rs_no], ! &rex.reg_startp[rp->rs_no]); regstack_pop(&scan); break; *************** *** 5349,5356 **** case RS_MCLOSE: /* Pop the state. Restore pointers when there is no match. */ if (status == RA_NOMATCH) ! restore_se(&rp->rs_un.sesave, ®_endpos[rp->rs_no], ! ®_endp[rp->rs_no]); regstack_pop(&scan); break; --- 5352,5359 ---- case RS_MCLOSE: /* Pop the state. Restore pointers when there is no match. */ if (status == RA_NOMATCH) ! restore_se(&rp->rs_un.sesave, &rex.reg_endpos[rp->rs_no], ! &rex.reg_endp[rp->rs_no]); regstack_pop(&scan); break; *************** *** 5785,5792 **** ++count; mb_ptr_adv(scan); } ! if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > reg_maxline ! || reg_line_lbr || count == maxcount) break; ++count; /* count the line-break */ reg_nextline(); --- 5788,5795 ---- ++count; mb_ptr_adv(scan); } ! if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > rex.reg_maxline ! || rex.reg_line_lbr || count == maxcount) break; ++count; /* count the line-break */ reg_nextline(); *************** *** 5810,5824 **** } else if (*scan == NUL) { ! if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > reg_maxline ! || reg_line_lbr) break; reg_nextline(); scan = reginput; if (got_int) break; } ! else if (reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) ++scan; else break; --- 5813,5827 ---- } else if (*scan == NUL) { ! if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > rex.reg_maxline ! || rex.reg_line_lbr) break; reg_nextline(); scan = reginput; if (got_int) break; } ! else if (rex.reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) ++scan; else break; *************** *** 5834,5855 **** case SKWORD + ADD_NL: while (count < maxcount) { ! if (vim_iswordp_buf(scan, reg_buf) && (testval || !VIM_ISDIGIT(*scan))) { mb_ptr_adv(scan); } else if (*scan == NUL) { ! if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > reg_maxline ! || reg_line_lbr) break; reg_nextline(); scan = reginput; if (got_int) break; } ! else if (reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) ++scan; else break; --- 5837,5858 ---- case SKWORD + ADD_NL: while (count < maxcount) { ! if (vim_iswordp_buf(scan, rex.reg_buf) && (testval || !VIM_ISDIGIT(*scan))) { mb_ptr_adv(scan); } else if (*scan == NUL) { ! if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > rex.reg_maxline ! || rex.reg_line_lbr) break; reg_nextline(); scan = reginput; if (got_int) break; } ! else if (rex.reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) ++scan; else break; *************** *** 5871,5885 **** } else if (*scan == NUL) { ! if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > reg_maxline ! || reg_line_lbr) break; reg_nextline(); scan = reginput; if (got_int) break; } ! else if (reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) ++scan; else break; --- 5874,5888 ---- } else if (*scan == NUL) { ! if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > rex.reg_maxline ! || rex.reg_line_lbr) break; reg_nextline(); scan = reginput; if (got_int) break; } ! else if (rex.reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) ++scan; else break; *************** *** 5897,5904 **** { if (*scan == NUL) { ! if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > reg_maxline ! || reg_line_lbr) break; reg_nextline(); scan = reginput; --- 5900,5907 ---- { if (*scan == NUL) { ! if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > rex.reg_maxline ! || rex.reg_line_lbr) break; reg_nextline(); scan = reginput; *************** *** 5910,5916 **** { mb_ptr_adv(scan); } ! else if (reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) ++scan; else break; --- 5913,5919 ---- { mb_ptr_adv(scan); } ! else if (rex.reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) ++scan; else break; *************** *** 5929,5936 **** #endif if (*scan == NUL) { ! if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > reg_maxline ! || reg_line_lbr) break; reg_nextline(); scan = reginput; --- 5932,5939 ---- #endif if (*scan == NUL) { ! if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > rex.reg_maxline ! || rex.reg_line_lbr) break; reg_nextline(); scan = reginput; *************** *** 5947,5953 **** #endif else if ((class_tab[*scan] & mask) == testval) ++scan; ! else if (reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) ++scan; else break; --- 5950,5956 ---- #endif else if ((class_tab[*scan] & mask) == testval) ++scan; ! else if (rex.reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) ++scan; else break; *************** *** 6031,6037 **** /* This doesn't do a multi-byte character, because a MULTIBYTECODE * would have been used for it. It does handle single-byte * characters, such as latin1. */ ! if (ireg_ic) { cu = MB_TOUPPER(*opnd); cl = MB_TOLOWER(*opnd); --- 6034,6040 ---- /* This doesn't do a multi-byte character, because a MULTIBYTECODE * would have been used for it. It does handle single-byte * characters, such as latin1. */ ! if (rex.reg_ic) { cu = MB_TOUPPER(*opnd); cl = MB_TOLOWER(*opnd); *************** *** 6062,6075 **** * compiling the program). */ if ((len = (*mb_ptr2len)(opnd)) > 1) { ! if (ireg_ic && enc_utf8) cf = utf_fold(utf_ptr2char(opnd)); while (count < maxcount && (*mb_ptr2len)(scan) >= len) { for (i = 0; i < len; ++i) if (opnd[i] != scan[i]) break; ! if (i < len && (!ireg_ic || !enc_utf8 || utf_fold(utf_ptr2char(scan)) != cf)) break; scan += len; --- 6065,6078 ---- * compiling the program). */ if ((len = (*mb_ptr2len)(opnd)) > 1) { ! if (rex.reg_ic && enc_utf8) cf = utf_fold(utf_ptr2char(opnd)); while (count < maxcount && (*mb_ptr2len)(scan) >= len) { for (i = 0; i < len; ++i) if (opnd[i] != scan[i]) break; ! if (i < len && (!rex.reg_ic || !enc_utf8 || utf_fold(utf_ptr2char(scan)) != cf)) break; scan += len; *************** *** 6094,6108 **** #endif if (*scan == NUL) { ! if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > reg_maxline ! || reg_line_lbr) break; reg_nextline(); scan = reginput; if (got_int) break; } ! else if (reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) ++scan; #ifdef FEAT_MBYTE else if (has_mbyte && (len = (*mb_ptr2len)(scan)) > 1) --- 6097,6111 ---- #endif if (*scan == NUL) { ! if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > rex.reg_maxline ! || rex.reg_line_lbr) break; reg_nextline(); scan = reginput; if (got_int) break; } ! else if (rex.reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) ++scan; #ifdef FEAT_MBYTE else if (has_mbyte && (len = (*mb_ptr2len)(scan)) > 1) *************** *** 6124,6134 **** case NEWL: while (count < maxcount ! && ((*scan == NUL && reglnum <= reg_maxline && !reg_line_lbr ! && REG_MULTI) || (*scan == '\n' && reg_line_lbr))) { count++; ! if (reg_line_lbr) ADVANCE_REGINPUT(); else reg_nextline(); --- 6127,6138 ---- case NEWL: while (count < maxcount ! && ((*scan == NUL && reglnum <= rex.reg_maxline ! && !rex.reg_line_lbr && REG_MULTI) ! || (*scan == '\n' && rex.reg_line_lbr))) { count++; ! if (rex.reg_line_lbr) ADVANCE_REGINPUT(); else reg_nextline(); *************** *** 6183,6189 **** { regprog_T *prog; ! prog = REG_MULTI ? reg_mmatch->regprog : reg_match->regprog; if (prog->engine == &nfa_regengine) /* For NFA matcher we don't check the magic */ return FALSE; --- 6187,6193 ---- { regprog_T *prog; ! prog = REG_MULTI ? rex.reg_mmatch->regprog : rex.reg_match->regprog; if (prog->engine == &nfa_regengine) /* For NFA matcher we don't check the magic */ return FALSE; *************** *** 6209,6221 **** if (REG_MULTI) { /* Use 0xff to set lnum to -1 */ ! vim_memset(reg_startpos, 0xff, sizeof(lpos_T) * NSUBEXP); ! vim_memset(reg_endpos, 0xff, sizeof(lpos_T) * NSUBEXP); } else { ! vim_memset(reg_startp, 0, sizeof(char_u *) * NSUBEXP); ! vim_memset(reg_endp, 0, sizeof(char_u *) * NSUBEXP); } need_clear_subexpr = FALSE; } --- 6213,6225 ---- if (REG_MULTI) { /* Use 0xff to set lnum to -1 */ ! vim_memset(rex.reg_startpos, 0xff, sizeof(lpos_T) * NSUBEXP); ! vim_memset(rex.reg_endpos, 0xff, sizeof(lpos_T) * NSUBEXP); } else { ! vim_memset(rex.reg_startp, 0, sizeof(char_u *) * NSUBEXP); ! vim_memset(rex.reg_endp, 0, sizeof(char_u *) * NSUBEXP); } need_clear_subexpr = FALSE; } *************** *** 6261,6273 **** { if (REG_MULTI) { ! bp->save_start[i].se_u.pos = reg_startpos[i]; ! bp->save_end[i].se_u.pos = reg_endpos[i]; } else { ! bp->save_start[i].se_u.ptr = reg_startp[i]; ! bp->save_end[i].se_u.ptr = reg_endp[i]; } } } --- 6265,6277 ---- { if (REG_MULTI) { ! bp->save_start[i].se_u.pos = rex.reg_startpos[i]; ! bp->save_end[i].se_u.pos = rex.reg_endpos[i]; } else { ! bp->save_start[i].se_u.ptr = rex.reg_startp[i]; ! bp->save_end[i].se_u.ptr = rex.reg_endp[i]; } } } *************** *** 6289,6301 **** { if (REG_MULTI) { ! reg_startpos[i] = bp->save_start[i].se_u.pos; ! reg_endpos[i] = bp->save_end[i].se_u.pos; } else { ! reg_startp[i] = bp->save_start[i].se_u.ptr; ! reg_endp[i] = bp->save_end[i].se_u.ptr; } } } --- 6293,6305 ---- { if (REG_MULTI) { ! rex.reg_startpos[i] = bp->save_start[i].se_u.pos; ! rex.reg_endpos[i] = bp->save_end[i].se_u.pos; } else { ! rex.reg_startp[i] = bp->save_start[i].se_u.ptr; ! rex.reg_endp[i] = bp->save_end[i].se_u.ptr; } } } *************** *** 6454,6460 **** *bytelen += len; if (clnum == end_lnum) break; /* match and at end! */ ! if (reglnum >= reg_maxline) return RA_NOMATCH; /* text too short */ /* Advance to next line. */ --- 6458,6464 ---- *bytelen += len; if (clnum == end_lnum) break; /* match and at end! */ ! if (reglnum >= rex.reg_maxline) return RA_NOMATCH; /* text too short */ /* Advance to next line. */ *************** *** 7039,7045 **** #endif /* ! * Compare two strings, ignore case if ireg_ic set. * Return 0 if strings match, non-zero otherwise. * Correct the length "*n" when composing characters are ignored. */ --- 7043,7049 ---- #endif /* ! * Compare two strings, ignore case if rex.reg_ic set. * Return 0 if strings match, non-zero otherwise. * Correct the length "*n" when composing characters are ignored. */ *************** *** 7048,7061 **** { int result; ! if (!ireg_ic) result = STRNCMP(s1, s2, *n); else result = MB_STRNICMP(s1, s2, *n); #ifdef FEAT_MBYTE /* if it failed and it's utf8 and we want to combineignore: */ ! if (result != 0 && enc_utf8 && ireg_icombine) { char_u *str1, *str2; int c1, c2, c11, c12; --- 7052,7065 ---- { int result; ! if (!rex.reg_ic) result = STRNCMP(s1, s2, *n); else result = MB_STRNICMP(s1, s2, *n); #ifdef FEAT_MBYTE /* if it failed and it's utf8 and we want to combineignore: */ ! if (result != 0 && enc_utf8 && rex.reg_icombine) { char_u *str1, *str2; int c1, c2, c11, c12; *************** *** 7074,7087 **** /* decompose the character if necessary, into 'base' characters * because I don't care about Arabic, I will hard-code the Hebrew * which I *do* care about! So sue me... */ ! if (c1 != c2 && (!ireg_ic || utf_fold(c1) != utf_fold(c2))) { /* decomposition necessary? */ mb_decompose(c1, &c11, &junk, &junk); mb_decompose(c2, &c12, &junk, &junk); c1 = c11; c2 = c12; ! if (c11 != c12 && (!ireg_ic || utf_fold(c11) != utf_fold(c12))) break; } } --- 7078,7092 ---- /* decompose the character if necessary, into 'base' characters * because I don't care about Arabic, I will hard-code the Hebrew * which I *do* care about! So sue me... */ ! if (c1 != c2 && (!rex.reg_ic || utf_fold(c1) != utf_fold(c2))) { /* decomposition necessary? */ mb_decompose(c1, &c11, &junk, &junk); mb_decompose(c2, &c12, &junk, &junk); c1 = c11; c2 = c12; ! if (c11 != c12 ! && (!rex.reg_ic || utf_fold(c11) != utf_fold(c12))) break; } } *************** *** 7103,7109 **** char_u *p; int cc; ! if (!ireg_ic #ifdef FEAT_MBYTE || (!enc_utf8 && mb_char2len(c) > 1) #endif --- 7108,7114 ---- char_u *p; int cc; ! if (!rex.reg_ic #ifdef FEAT_MBYTE || (!enc_utf8 && mb_char2len(c) > 1) #endif *************** *** 7276,7289 **** #ifdef FEAT_EVAL static int can_f_submatch = FALSE; /* TRUE when submatch() can be used */ ! /* These pointers are used instead of reg_match and reg_mmatch for ! * reg_submatch(). Needed for when the substitution string is an expression ! * that contains a call to substitute() and submatch(). */ ! static regmatch_T *submatch_match; ! static regmmatch_T *submatch_mmatch; ! static linenr_T submatch_firstlnum; ! static linenr_T submatch_maxline; ! static int submatch_line_lbr; #endif #if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) || defined(PROTO) --- 7281,7298 ---- #ifdef FEAT_EVAL static int can_f_submatch = FALSE; /* TRUE when submatch() can be used */ ! /* These pointers are used for reg_submatch(). Needed for when the ! * substitution string is an expression that contains a call to substitute() ! * and submatch(). */ ! typedef struct { ! regmatch_T *sm_match; ! regmmatch_T *sm_mmatch; ! linenr_T sm_firstlnum; ! linenr_T sm_maxline; ! int sm_line_lbr; ! } regsubmatch_T; ! ! static regsubmatch_T rsm; /* can only be used when can_f_submatch is TRUE */ #endif #if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) || defined(PROTO) *************** *** 7310,7320 **** li = argv->vval.v_list->lv_first; for (i = 0; i < 10; ++i) { ! s = submatch_match->startp[i]; ! if (s == NULL || submatch_match->endp[i] == NULL) s = NULL; else ! s = vim_strnsave(s, (int)(submatch_match->endp[i] - s)); li->li_tv.v_type = VAR_STRING; li->li_tv.vval.v_string = s; li = li->li_next; --- 7319,7329 ---- li = argv->vval.v_list->lv_first; for (i = 0; i < 10; ++i) { ! s = rsm.sm_match->startp[i]; ! if (s == NULL || rsm.sm_match->endp[i] == NULL) s = NULL; else ! s = vim_strnsave(s, (int)(rsm.sm_match->endp[i] - s)); li->li_tv.v_type = VAR_STRING; li->li_tv.vval.v_string = s; li = li->li_next; *************** *** 7359,7370 **** int magic, int backslash) { ! reg_match = rmp; ! reg_mmatch = NULL; ! reg_maxline = 0; ! reg_buf = curbuf; ! reg_line_lbr = TRUE; ! return vim_regsub_both(source, expr, dest, copy, magic, backslash); } #endif --- 7368,7394 ---- int magic, int backslash) { ! int result; ! regexec_T rex_save; ! int rex_in_use_save = rex_in_use; ! ! if (rex_in_use) ! /* Being called recursively, save the state. */ ! rex_save = rex; ! rex_in_use = TRUE; ! ! rex.reg_match = rmp; ! rex.reg_mmatch = NULL; ! rex.reg_maxline = 0; ! rex.reg_buf = curbuf; ! rex.reg_line_lbr = TRUE; ! result = vim_regsub_both(source, expr, dest, copy, magic, backslash); ! ! rex_in_use = rex_in_use_save; ! if (rex_in_use) ! rex = rex_save; ! ! return result; } #endif *************** *** 7378,7390 **** int magic, int backslash) { ! reg_match = NULL; ! reg_mmatch = rmp; ! reg_buf = curbuf; /* always works on the current buffer! */ ! reg_firstlnum = lnum; ! reg_maxline = curbuf->b_ml.ml_line_count - lnum; ! reg_line_lbr = FALSE; ! return vim_regsub_both(source, NULL, dest, copy, magic, backslash); } static int --- 7402,7429 ---- int magic, int backslash) { ! int result; ! regexec_T rex_save; ! int rex_in_use_save = rex_in_use; ! ! if (rex_in_use) ! /* Being called recursively, save the state. */ ! rex_save = rex; ! rex_in_use = TRUE; ! ! rex.reg_match = NULL; ! rex.reg_mmatch = rmp; ! rex.reg_buf = curbuf; /* always works on the current buffer! */ ! rex.reg_firstlnum = lnum; ! rex.reg_maxline = curbuf->b_ml.ml_line_count - lnum; ! rex.reg_line_lbr = FALSE; ! result = vim_regsub_both(source, NULL, dest, copy, magic, backslash); ! ! rex_in_use = rex_in_use_save; ! if (rex_in_use) ! rex = rex_save; ! ! return result; } static int *************** *** 7424,7434 **** /* * When the substitute part starts with "\=" evaluate it as an expression. */ ! if (expr != NULL || (source[0] == '\\' && source[1] == '=' ! #ifdef FEAT_EVAL ! && !can_f_submatch /* can't do this recursively */ ! #endif ! )) { #ifdef FEAT_EVAL /* To make sure that the length doesn't change between checking the --- 7463,7469 ---- /* * When the substitute part starts with "\=" evaluate it as an expression. */ ! if (expr != NULL || (source[0] == '\\' && source[1] == '=')) { #ifdef FEAT_EVAL /* To make sure that the length doesn't change between checking the *************** *** 7447,7470 **** } else { ! win_T *save_reg_win; ! int save_ireg_ic; ! int prev_can_f_submatch = can_f_submatch; vim_free(eval_result); /* The expression may contain substitute(), which calls us * recursively. Make sure submatch() gets the text from the first ! * level. Don't need to save "reg_buf", because ! * vim_regexec_multi() can't be called recursively. */ ! submatch_match = reg_match; ! submatch_mmatch = reg_mmatch; ! submatch_firstlnum = reg_firstlnum; ! submatch_maxline = reg_maxline; ! submatch_line_lbr = reg_line_lbr; ! save_reg_win = reg_win; ! save_ireg_ic = ireg_ic; can_f_submatch = TRUE; if (expr != NULL) { --- 7482,7503 ---- } else { ! int prev_can_f_submatch = can_f_submatch; ! regsubmatch_T rsm_save; vim_free(eval_result); /* The expression may contain substitute(), which calls us * recursively. Make sure submatch() gets the text from the first ! * level. */ ! if (can_f_submatch) ! rsm_save = rsm; can_f_submatch = TRUE; + rsm.sm_match = rex.reg_match; + rsm.sm_mmatch = rex.reg_mmatch; + rsm.sm_firstlnum = rex.reg_firstlnum; + rsm.sm_maxline = rex.reg_maxline; + rsm.sm_line_lbr = rex.reg_line_lbr; if (expr != NULL) { *************** *** 7476,7510 **** rettv.v_type = VAR_STRING; rettv.vval.v_string = NULL; ! if (prev_can_f_submatch) ! { ! /* can't do this recursively */ ! } ! else ! { ! argv[0].v_type = VAR_LIST; ! argv[0].vval.v_list = &matchList.sl_list; ! matchList.sl_list.lv_len = 0; ! if (expr->v_type == VAR_FUNC) ! { ! s = expr->vval.v_string; ! call_func(s, (int)STRLEN(s), &rettv, ! 1, argv, fill_submatch_list, ! 0L, 0L, &dummy, TRUE, NULL, NULL); ! } ! else if (expr->v_type == VAR_PARTIAL) ! { ! partial_T *partial = expr->vval.v_partial; - s = partial_name(partial); - call_func(s, (int)STRLEN(s), &rettv, - 1, argv, fill_submatch_list, - 0L, 0L, &dummy, TRUE, partial, NULL); - } - if (matchList.sl_list.lv_len > 0) - /* fill_submatch_list() was called */ - clear_submatch_list(&matchList); - } eval_result = get_tv_string_buf_chk(&rettv, buf); if (eval_result != NULL) eval_result = vim_strsave(eval_result); --- 7509,7537 ---- rettv.v_type = VAR_STRING; rettv.vval.v_string = NULL; ! argv[0].v_type = VAR_LIST; ! argv[0].vval.v_list = &matchList.sl_list; ! matchList.sl_list.lv_len = 0; ! if (expr->v_type == VAR_FUNC) ! { ! s = expr->vval.v_string; ! call_func(s, (int)STRLEN(s), &rettv, ! 1, argv, fill_submatch_list, ! 0L, 0L, &dummy, TRUE, NULL, NULL); ! } ! else if (expr->v_type == VAR_PARTIAL) ! { ! partial_T *partial = expr->vval.v_partial; ! ! s = partial_name(partial); ! call_func(s, (int)STRLEN(s), &rettv, ! 1, argv, fill_submatch_list, ! 0L, 0L, &dummy, TRUE, partial, NULL); ! } ! if (matchList.sl_list.lv_len > 0) ! /* fill_submatch_list() was called */ ! clear_submatch_list(&matchList); eval_result = get_tv_string_buf_chk(&rettv, buf); if (eval_result != NULL) eval_result = vim_strsave(eval_result); *************** *** 7522,7528 **** /* Change NL to CR, so that it becomes a line break, * unless called from vim_regexec_nl(). * Skip over a backslashed character. */ ! if (*s == NL && !submatch_line_lbr) *s = CAR; else if (*s == '\\' && s[1] != NUL) { --- 7549,7555 ---- /* Change NL to CR, so that it becomes a line break, * unless called from vim_regexec_nl(). * Skip over a backslashed character. */ ! if (*s == NL && !rsm.sm_line_lbr) *s = CAR; else if (*s == '\\' && s[1] != NUL) { *************** *** 7533,7539 **** * def * Not when called from vim_regexec_nl(). */ ! if (*s == NL && !submatch_line_lbr) *s = CAR; had_backslash = TRUE; } --- 7560,7566 ---- * def * Not when called from vim_regexec_nl(). */ ! if (*s == NL && !rsm.sm_line_lbr) *s = CAR; had_backslash = TRUE; } *************** *** 7552,7565 **** dst += STRLEN(eval_result); } ! reg_match = submatch_match; ! reg_mmatch = submatch_mmatch; ! reg_firstlnum = submatch_firstlnum; ! reg_maxline = submatch_maxline; ! reg_line_lbr = submatch_line_lbr; ! reg_win = save_reg_win; ! ireg_ic = save_ireg_ic; ! can_f_submatch = FALSE; } #endif } --- 7579,7587 ---- dst += STRLEN(eval_result); } ! can_f_submatch = prev_can_f_submatch; ! if (can_f_submatch) ! rsm = rsm_save; } #endif } *************** *** 7688,7713 **** { if (REG_MULTI) { ! clnum = reg_mmatch->startpos[no].lnum; ! if (clnum < 0 || reg_mmatch->endpos[no].lnum < 0) s = NULL; else { ! s = reg_getline(clnum) + reg_mmatch->startpos[no].col; ! if (reg_mmatch->endpos[no].lnum == clnum) ! len = reg_mmatch->endpos[no].col ! - reg_mmatch->startpos[no].col; else len = (int)STRLEN(s); } } else { ! s = reg_match->startp[no]; ! if (reg_match->endp[no] == NULL) s = NULL; else ! len = (int)(reg_match->endp[no] - s); } if (s != NULL) { --- 7710,7735 ---- { if (REG_MULTI) { ! clnum = rex.reg_mmatch->startpos[no].lnum; ! if (clnum < 0 || rex.reg_mmatch->endpos[no].lnum < 0) s = NULL; else { ! s = reg_getline(clnum) + rex.reg_mmatch->startpos[no].col; ! if (rex.reg_mmatch->endpos[no].lnum == clnum) ! len = rex.reg_mmatch->endpos[no].col ! - rex.reg_mmatch->startpos[no].col; else len = (int)STRLEN(s); } } else { ! s = rex.reg_match->startp[no]; ! if (rex.reg_match->endp[no] == NULL) s = NULL; else ! len = (int)(rex.reg_match->endp[no] - s); } if (s != NULL) { *************** *** 7717,7730 **** { if (REG_MULTI) { ! if (reg_mmatch->endpos[no].lnum == clnum) break; if (copy) *dst = CAR; ++dst; s = reg_getline(++clnum); ! if (reg_mmatch->endpos[no].lnum == clnum) ! len = reg_mmatch->endpos[no].col; else len = (int)STRLEN(s); } --- 7739,7752 ---- { if (REG_MULTI) { ! if (rex.reg_mmatch->endpos[no].lnum == clnum) break; if (copy) *dst = CAR; ++dst; s = reg_getline(++clnum); ! if (rex.reg_mmatch->endpos[no].lnum == clnum) ! len = rex.reg_mmatch->endpos[no].col; else len = (int)STRLEN(s); } *************** *** 7824,7839 **** reg_getline_submatch(linenr_T lnum) { char_u *s; ! linenr_T save_first = reg_firstlnum; ! linenr_T save_max = reg_maxline; ! reg_firstlnum = submatch_firstlnum; ! reg_maxline = submatch_maxline; s = reg_getline(lnum); ! reg_firstlnum = save_first; ! reg_maxline = save_max; return s; } --- 7846,7861 ---- reg_getline_submatch(linenr_T lnum) { char_u *s; ! linenr_T save_first = rex.reg_firstlnum; ! linenr_T save_max = rex.reg_maxline; ! rex.reg_firstlnum = rsm.sm_firstlnum; ! rex.reg_maxline = rsm.sm_maxline; s = reg_getline(lnum); ! rex.reg_firstlnum = save_first; ! rex.reg_maxline = save_max; return s; } *************** *** 7854,7860 **** if (!can_f_submatch || no < 0) return NULL; ! if (submatch_match == NULL) { /* * First round: compute the length and allocate memory. --- 7876,7882 ---- if (!can_f_submatch || no < 0) return NULL; ! if (rsm.sm_match == NULL) { /* * First round: compute the length and allocate memory. *************** *** 7862,7879 **** */ for (round = 1; round <= 2; ++round) { ! lnum = submatch_mmatch->startpos[no].lnum; ! if (lnum < 0 || submatch_mmatch->endpos[no].lnum < 0) return NULL; ! s = reg_getline_submatch(lnum) + submatch_mmatch->startpos[no].col; if (s == NULL) /* anti-crash check, cannot happen? */ break; ! if (submatch_mmatch->endpos[no].lnum == lnum) { /* Within one line: take form start to end col. */ ! len = submatch_mmatch->endpos[no].col ! - submatch_mmatch->startpos[no].col; if (round == 2) vim_strncpy(retval, s, len); ++len; --- 7884,7901 ---- */ for (round = 1; round <= 2; ++round) { ! lnum = rsm.sm_mmatch->startpos[no].lnum; ! if (lnum < 0 || rsm.sm_mmatch->endpos[no].lnum < 0) return NULL; ! s = reg_getline_submatch(lnum) + rsm.sm_mmatch->startpos[no].col; if (s == NULL) /* anti-crash check, cannot happen? */ break; ! if (rsm.sm_mmatch->endpos[no].lnum == lnum) { /* Within one line: take form start to end col. */ ! len = rsm.sm_mmatch->endpos[no].col ! - rsm.sm_mmatch->startpos[no].col; if (round == 2) vim_strncpy(retval, s, len); ++len; *************** *** 7890,7896 **** } ++len; ++lnum; ! while (lnum < submatch_mmatch->endpos[no].lnum) { s = reg_getline_submatch(lnum++); if (round == 2) --- 7912,7918 ---- } ++len; ++lnum; ! while (lnum < rsm.sm_mmatch->endpos[no].lnum) { s = reg_getline_submatch(lnum++); if (round == 2) *************** *** 7902,7909 **** } if (round == 2) STRNCPY(retval + len, reg_getline_submatch(lnum), ! submatch_mmatch->endpos[no].col); ! len += submatch_mmatch->endpos[no].col; if (round == 2) retval[len] = NUL; ++len; --- 7924,7931 ---- } if (round == 2) STRNCPY(retval + len, reg_getline_submatch(lnum), ! rsm.sm_mmatch->endpos[no].col); ! len += rsm.sm_mmatch->endpos[no].col; if (round == 2) retval[len] = NUL; ++len; *************** *** 7919,7929 **** } else { ! s = submatch_match->startp[no]; ! if (s == NULL || submatch_match->endp[no] == NULL) retval = NULL; else ! retval = vim_strnsave(s, (int)(submatch_match->endp[no] - s)); } return retval; --- 7941,7951 ---- } else { ! s = rsm.sm_match->startp[no]; ! if (s == NULL || rsm.sm_match->endp[no] == NULL) retval = NULL; else ! retval = vim_strnsave(s, (int)(rsm.sm_match->endp[no] - s)); } return retval; *************** *** 7951,7965 **** if (!can_f_submatch || no < 0) return NULL; ! if (submatch_match == NULL) { ! slnum = submatch_mmatch->startpos[no].lnum; ! elnum = submatch_mmatch->endpos[no].lnum; if (slnum < 0 || elnum < 0) return NULL; ! scol = submatch_mmatch->startpos[no].col; ! ecol = submatch_mmatch->endpos[no].col; list = list_alloc(); if (list == NULL) --- 7973,7987 ---- if (!can_f_submatch || no < 0) return NULL; ! if (rsm.sm_match == NULL) { ! slnum = rsm.sm_mmatch->startpos[no].lnum; ! elnum = rsm.sm_mmatch->endpos[no].lnum; if (slnum < 0 || elnum < 0) return NULL; ! scol = rsm.sm_mmatch->startpos[no].col; ! ecol = rsm.sm_mmatch->endpos[no].col; list = list_alloc(); if (list == NULL) *************** *** 7988,8001 **** } else { ! s = submatch_match->startp[no]; ! if (s == NULL || submatch_match->endp[no] == NULL) return NULL; list = list_alloc(); if (list == NULL) return NULL; if (list_append_string(list, s, ! (int)(submatch_match->endp[no] - s)) == FAIL) error = TRUE; } --- 8010,8023 ---- } else { ! s = rsm.sm_match->startp[no]; ! if (s == NULL || rsm.sm_match->endp[no] == NULL) return NULL; list = list_alloc(); if (list == NULL) return NULL; if (list_append_string(list, s, ! (int)(rsm.sm_match->endp[no] - s)) == FAIL) error = TRUE; } *************** *** 8173,8179 **** colnr_T col, /* column to start looking for match */ int nl) { ! int result = rmp->regprog->engine->regexec_nl(rmp, line, col, nl); /* NFA engine aborted because it's very slow. */ if (rmp->regprog->re_engine == AUTOMATIC_ENGINE --- 8195,8214 ---- colnr_T col, /* column to start looking for match */ int nl) { ! int result; ! regexec_T rex_save; ! int rex_in_use_save = rex_in_use; ! ! if (rex_in_use) ! /* Being called recursively, save the state. */ ! rex_save = rex; ! rex_in_use = TRUE; ! rex.reg_startp = NULL; ! rex.reg_endp = NULL; ! rex.reg_startpos = NULL; ! rex.reg_endpos = NULL; ! ! result = rmp->regprog->engine->regexec_nl(rmp, line, col, nl); /* NFA engine aborted because it's very slow. */ if (rmp->regprog->re_engine == AUTOMATIC_ENGINE *************** *** 8198,8203 **** --- 8233,8243 ---- p_re = save_p_re; } + + rex_in_use = rex_in_use_save; + if (rex_in_use) + rex = rex_save; + return result > 0; } *************** *** 8264,8271 **** colnr_T col, /* column to start looking for match */ proftime_T *tm) /* timeout limit or NULL */ { ! int result = rmp->regprog->engine->regexec_multi( ! rmp, win, buf, lnum, col, tm); /* NFA engine aborted because it's very slow. */ if (rmp->regprog->re_engine == AUTOMATIC_ENGINE --- 8304,8319 ---- colnr_T col, /* column to start looking for match */ proftime_T *tm) /* timeout limit or NULL */ { ! int result; ! regexec_T rex_save; ! int rex_in_use_save = rex_in_use; ! ! if (rex_in_use) ! /* Being called recursively, save the state. */ ! rex_save = rex; ! rex_in_use = TRUE; ! ! result = rmp->regprog->engine->regexec_multi(rmp, win, buf, lnum, col, tm); /* NFA engine aborted because it's very slow. */ if (rmp->regprog->re_engine == AUTOMATIC_ENGINE *************** *** 8291,8295 **** --- 8339,8347 ---- p_re = save_p_re; } + rex_in_use = rex_in_use_save; + if (rex_in_use) + rex = rex_save; + return result <= 0 ? 0 : result; } *** ../vim-8.0.0019/src/regexp_nfa.c 2016-09-09 20:26:46.000000000 +0200 --- src/regexp_nfa.c 2016-10-02 15:51:12.173504331 +0200 *************** *** 5432,5438 **** char_u *s; /* Used often, do some work to avoid call overhead. */ ! if (!ireg_ic #ifdef FEAT_MBYTE && !has_mbyte #endif --- 5432,5438 ---- char_u *s; /* Used often, do some work to avoid call overhead. */ ! if (!rex.reg_ic #ifdef FEAT_MBYTE && !has_mbyte #endif *************** *** 5467,5473 **** { c1 = PTR2CHAR(match_text + len1); c2 = PTR2CHAR(regline + col + len2); ! if (c1 != c2 && (!ireg_ic || MB_TOLOWER(c1) != MB_TOLOWER(c2))) { match = FALSE; break; --- 5467,5473 ---- { c1 = PTR2CHAR(match_text + len1); c2 = PTR2CHAR(regline + col + len2); ! if (c1 != c2 && (!rex.reg_ic || MB_TOLOWER(c1) != MB_TOLOWER(c2))) { match = FALSE; break; *************** *** 5485,5499 **** cleanup_subexpr(); if (REG_MULTI) { ! reg_startpos[0].lnum = reglnum; ! reg_startpos[0].col = col; ! reg_endpos[0].lnum = reglnum; ! reg_endpos[0].col = col + len2; } else { ! reg_startp[0] = regline + col; ! reg_endp[0] = regline + col + len2; } return 1L; } --- 5485,5499 ---- cleanup_subexpr(); if (REG_MULTI) { ! rex.reg_startpos[0].lnum = reglnum; ! rex.reg_startpos[0].col = col; ! rex.reg_endpos[0].lnum = reglnum; ! rex.reg_endpos[0].col = col + len2; } else { ! rex.reg_startp[0] = regline + col; ! rex.reg_endp[0] = regline + col + len2; } return 1L; } *************** *** 5728,5735 **** { #ifdef FEAT_MBYTE /* If the match ends before a composing characters and ! * ireg_icombine is not set, that is not really a match. */ ! if (enc_utf8 && !ireg_icombine && utf_iscomposing(curc)) break; #endif nfa_match = TRUE; --- 5728,5735 ---- { #ifdef FEAT_MBYTE /* If the match ends before a composing characters and ! * rex.reg_icombine is not set, that is not really a match. */ ! if (enc_utf8 && !rex.reg_icombine && utf_iscomposing(curc)) break; #endif nfa_match = TRUE; *************** *** 6048,6063 **** int this_class; /* Get class of current and previous char (if it exists). */ ! this_class = mb_get_class_buf(reginput, reg_buf); if (this_class <= 1) result = FALSE; else if (reg_prev_class() == this_class) result = FALSE; } #endif ! else if (!vim_iswordc_buf(curc, reg_buf) || (reginput > regline ! && vim_iswordc_buf(reginput[-1], reg_buf))) result = FALSE; if (result) { --- 6048,6063 ---- int this_class; /* Get class of current and previous char (if it exists). */ ! this_class = mb_get_class_buf(reginput, rex.reg_buf); if (this_class <= 1) result = FALSE; else if (reg_prev_class() == this_class) result = FALSE; } #endif ! else if (!vim_iswordc_buf(curc, rex.reg_buf) || (reginput > regline ! && vim_iswordc_buf(reginput[-1], rex.reg_buf))) result = FALSE; if (result) { *************** *** 6076,6091 **** int this_class, prev_class; /* Get class of current and previous char (if it exists). */ ! this_class = mb_get_class_buf(reginput, reg_buf); prev_class = reg_prev_class(); if (this_class == prev_class || prev_class == 0 || prev_class == 1) result = FALSE; } #endif ! else if (!vim_iswordc_buf(reginput[-1], reg_buf) || (reginput[0] != NUL ! && vim_iswordc_buf(curc, reg_buf))) result = FALSE; if (result) { --- 6076,6091 ---- int this_class, prev_class; /* Get class of current and previous char (if it exists). */ ! this_class = mb_get_class_buf(reginput, rex.reg_buf); prev_class = reg_prev_class(); if (this_class == prev_class || prev_class == 0 || prev_class == 1) result = FALSE; } #endif ! else if (!vim_iswordc_buf(reginput[-1], rex.reg_buf) || (reginput[0] != NUL ! && vim_iswordc_buf(curc, rex.reg_buf))) result = FALSE; if (result) { *************** *** 6096,6102 **** case NFA_BOF: if (reglnum == 0 && reginput == regline ! && (!REG_MULTI || reg_firstlnum == 1)) { add_here = TRUE; add_state = t->state->out; --- 6096,6102 ---- case NFA_BOF: if (reglnum == 0 && reginput == regline ! && (!REG_MULTI || rex.reg_firstlnum == 1)) { add_here = TRUE; add_state = t->state->out; *************** *** 6104,6110 **** break; case NFA_EOF: ! if (reglnum == reg_maxline && curc == NUL) { add_here = TRUE; add_state = t->state->out; --- 6104,6110 ---- break; case NFA_EOF: ! if (reglnum == rex.reg_maxline && curc == NUL) { add_here = TRUE; add_state = t->state->out; *************** *** 6131,6137 **** * (no preceding character). */ len += mb_char2len(mc); } ! if (ireg_icombine && len == 0) { /* If \Z was present, then ignore composing characters. * When ignoring the base character this always matches. */ --- 6131,6137 ---- * (no preceding character). */ len += mb_char2len(mc); } ! if (rex.reg_icombine && len == 0) { /* If \Z was present, then ignore composing characters. * When ignoring the base character this always matches. */ *************** *** 6190,6197 **** #endif case NFA_NEWL: ! if (curc == NUL && !reg_line_lbr && REG_MULTI ! && reglnum <= reg_maxline) { go_to_nextline = TRUE; /* Pass -1 for the offset, which means taking the position --- 6190,6197 ---- #endif case NFA_NEWL: ! if (curc == NUL && !rex.reg_line_lbr && REG_MULTI ! && reglnum <= rex.reg_maxline) { go_to_nextline = TRUE; /* Pass -1 for the offset, which means taking the position *************** *** 6199,6205 **** add_state = t->state->out; add_off = -1; } ! else if (curc == '\n' && reg_line_lbr) { /* match \n as if it is an ordinary character */ add_state = t->state->out; --- 6199,6205 ---- add_state = t->state->out; add_off = -1; } ! else if (curc == '\n' && rex.reg_line_lbr) { /* match \n as if it is an ordinary character */ add_state = t->state->out; *************** *** 6244,6250 **** result = result_if_matched; break; } ! if (ireg_ic) { int curc_low = MB_TOLOWER(curc); int done = FALSE; --- 6244,6250 ---- result = result_if_matched; break; } ! if (rex.reg_ic) { int curc_low = MB_TOLOWER(curc); int done = FALSE; *************** *** 6262,6268 **** } else if (state->c < 0 ? check_char_class(state->c, curc) : (curc == state->c ! || (ireg_ic && MB_TOLOWER(curc) == MB_TOLOWER(state->c)))) { result = result_if_matched; --- 6262,6268 ---- } else if (state->c < 0 ? check_char_class(state->c, curc) : (curc == state->c ! || (rex.reg_ic && MB_TOLOWER(curc) == MB_TOLOWER(state->c)))) { result = result_if_matched; *************** *** 6320,6332 **** break; case NFA_KWORD: /* \k */ ! result = vim_iswordp_buf(reginput, reg_buf); ADD_STATE_IF_MATCH(t->state); break; case NFA_SKWORD: /* \K */ result = !VIM_ISDIGIT(curc) ! && vim_iswordp_buf(reginput, reg_buf); ADD_STATE_IF_MATCH(t->state); break; --- 6320,6332 ---- break; case NFA_KWORD: /* \k */ ! result = vim_iswordp_buf(reginput, rex.reg_buf); ADD_STATE_IF_MATCH(t->state); break; case NFA_SKWORD: /* \K */ result = !VIM_ISDIGIT(curc) ! && vim_iswordp_buf(reginput, rex.reg_buf); ADD_STATE_IF_MATCH(t->state); break; *************** *** 6441,6464 **** break; case NFA_LOWER_IC: /* [a-z] */ ! result = ri_lower(curc) || (ireg_ic && ri_upper(curc)); ADD_STATE_IF_MATCH(t->state); break; case NFA_NLOWER_IC: /* [^a-z] */ result = curc != NUL ! && !(ri_lower(curc) || (ireg_ic && ri_upper(curc))); ADD_STATE_IF_MATCH(t->state); break; case NFA_UPPER_IC: /* [A-Z] */ ! result = ri_upper(curc) || (ireg_ic && ri_lower(curc)); ADD_STATE_IF_MATCH(t->state); break; case NFA_NUPPER_IC: /* ^[A-Z] */ result = curc != NUL ! && !(ri_upper(curc) || (ireg_ic && ri_lower(curc))); ADD_STATE_IF_MATCH(t->state); break; --- 6441,6464 ---- break; case NFA_LOWER_IC: /* [a-z] */ ! result = ri_lower(curc) || (rex.reg_ic && ri_upper(curc)); ADD_STATE_IF_MATCH(t->state); break; case NFA_NLOWER_IC: /* [^a-z] */ result = curc != NUL ! && !(ri_lower(curc) || (rex.reg_ic && ri_upper(curc))); ADD_STATE_IF_MATCH(t->state); break; case NFA_UPPER_IC: /* [A-Z] */ ! result = ri_upper(curc) || (rex.reg_ic && ri_lower(curc)); ADD_STATE_IF_MATCH(t->state); break; case NFA_NUPPER_IC: /* ^[A-Z] */ result = curc != NUL ! && !(ri_upper(curc) || (rex.reg_ic && ri_lower(curc))); ADD_STATE_IF_MATCH(t->state); break; *************** *** 6549,6555 **** case NFA_LNUM_LT: result = (REG_MULTI && nfa_re_num_cmp(t->state->val, t->state->c - NFA_LNUM, ! (long_u)(reglnum + reg_firstlnum))); if (result) { add_here = TRUE; --- 6549,6555 ---- case NFA_LNUM_LT: result = (REG_MULTI && nfa_re_num_cmp(t->state->val, t->state->c - NFA_LNUM, ! (long_u)(reglnum + rex.reg_firstlnum))); if (result) { add_here = TRUE; *************** *** 6575,6581 **** { int op = t->state->c - NFA_VCOL; colnr_T col = (colnr_T)(reginput - regline); ! win_T *wp = reg_win == NULL ? curwin : reg_win; /* Bail out quickly when there can't be a match, avoid the * overhead of win_linetabsize() on long lines. */ --- 6575,6581 ---- { int op = t->state->c - NFA_VCOL; colnr_T col = (colnr_T)(reginput - regline); ! win_T *wp = rex.reg_win == NULL ? curwin : rex.reg_win; /* Bail out quickly when there can't be a match, avoid the * overhead of win_linetabsize() on long lines. */ *************** *** 6611,6628 **** case NFA_MARK_GT: case NFA_MARK_LT: { ! pos_T *pos = getmark_buf(reg_buf, t->state->val, FALSE); /* Compare the mark position to the match position. */ result = (pos != NULL /* mark doesn't exist */ && pos->lnum > 0 /* mark isn't set in reg_buf */ ! && (pos->lnum == reglnum + reg_firstlnum ? (pos->col == (colnr_T)(reginput - regline) ? t->state->c == NFA_MARK : (pos->col < (colnr_T)(reginput - regline) ? t->state->c == NFA_MARK_GT : t->state->c == NFA_MARK_LT)) ! : (pos->lnum < reglnum + reg_firstlnum ? t->state->c == NFA_MARK_GT : t->state->c == NFA_MARK_LT))); if (result) --- 6611,6628 ---- case NFA_MARK_GT: case NFA_MARK_LT: { ! pos_T *pos = getmark_buf(rex.reg_buf, t->state->val, FALSE); /* Compare the mark position to the match position. */ result = (pos != NULL /* mark doesn't exist */ && pos->lnum > 0 /* mark isn't set in reg_buf */ ! && (pos->lnum == reglnum + rex.reg_firstlnum ? (pos->col == (colnr_T)(reginput - regline) ? t->state->c == NFA_MARK : (pos->col < (colnr_T)(reginput - regline) ? t->state->c == NFA_MARK_GT : t->state->c == NFA_MARK_LT)) ! : (pos->lnum < reglnum + rex.reg_firstlnum ? t->state->c == NFA_MARK_GT : t->state->c == NFA_MARK_LT))); if (result) *************** *** 6634,6643 **** } case NFA_CURSOR: ! result = (reg_win != NULL ! && (reglnum + reg_firstlnum == reg_win->w_cursor.lnum) && ((colnr_T)(reginput - regline) ! == reg_win->w_cursor.col)); if (result) { add_here = TRUE; --- 6634,6644 ---- } case NFA_CURSOR: ! result = (rex.reg_win != NULL ! && (reglnum + rex.reg_firstlnum ! == rex.reg_win->w_cursor.lnum) && ((colnr_T)(reginput - regline) ! == rex.reg_win->w_cursor.col)); if (result) { add_here = TRUE; *************** *** 6691,6702 **** #endif result = (c == curc); ! if (!result && ireg_ic) result = MB_TOLOWER(c) == MB_TOLOWER(curc); #ifdef FEAT_MBYTE ! /* If ireg_icombine is not set only skip over the character * itself. When it is set skip over composing characters. */ ! if (result && enc_utf8 && !ireg_icombine) clen = utf_ptr2len(reginput); #endif ADD_STATE_IF_MATCH(t->state); --- 6692,6703 ---- #endif result = (c == curc); ! if (!result && rex.reg_ic) result = MB_TOLOWER(c) == MB_TOLOWER(curc); #ifdef FEAT_MBYTE ! /* If rex.reg_icombine is not set only skip over the character * itself. When it is set skip over composing characters. */ ! if (result && enc_utf8 && !rex.reg_icombine) clen = utf_ptr2len(reginput); #endif ADD_STATE_IF_MATCH(t->state); *************** *** 6815,6822 **** && ((toplevel && reglnum == 0 && clen != 0 ! && (ireg_maxcol == 0 ! || (colnr_T)(reginput - regline) < ireg_maxcol)) || (nfa_endp != NULL && (REG_MULTI ? (reglnum < nfa_endp->se_u.pos.lnum --- 6816,6823 ---- && ((toplevel && reglnum == 0 && clen != 0 ! && (rex.reg_maxcol == 0 ! || (colnr_T)(reginput - regline) < rex.reg_maxcol)) || (nfa_endp != NULL && (REG_MULTI ? (reglnum < nfa_endp->se_u.pos.lnum *************** *** 6856,6863 **** /* Checking if the required start character matches is * cheaper than adding a state that won't match. */ c = PTR2CHAR(reginput + clen); ! if (c != prog->regstart && (!ireg_ic || MB_TOLOWER(c) ! != MB_TOLOWER(prog->regstart))) { #ifdef ENABLE_LOG fprintf(log_fd, " Skipping start state, regstart does not match\n"); --- 6857,6864 ---- /* Checking if the required start character matches is * cheaper than adding a state that won't match. */ c = PTR2CHAR(reginput + clen); ! if (c != prog->regstart && (!rex.reg_ic ! || MB_TOLOWER(c) != MB_TOLOWER(prog->regstart))) { #ifdef ENABLE_LOG fprintf(log_fd, " Skipping start state, regstart does not match\n"); *************** *** 6997,7036 **** { for (i = 0; i < subs.norm.in_use; i++) { ! reg_startpos[i].lnum = subs.norm.list.multi[i].start_lnum; ! reg_startpos[i].col = subs.norm.list.multi[i].start_col; ! reg_endpos[i].lnum = subs.norm.list.multi[i].end_lnum; ! reg_endpos[i].col = subs.norm.list.multi[i].end_col; } ! if (reg_startpos[0].lnum < 0) { ! reg_startpos[0].lnum = 0; ! reg_startpos[0].col = col; } ! if (reg_endpos[0].lnum < 0) { /* pattern has a \ze but it didn't match, use current end */ ! reg_endpos[0].lnum = reglnum; ! reg_endpos[0].col = (int)(reginput - regline); } else /* Use line number of "\ze". */ ! reglnum = reg_endpos[0].lnum; } else { for (i = 0; i < subs.norm.in_use; i++) { ! reg_startp[i] = subs.norm.list.line[i].start; ! reg_endp[i] = subs.norm.list.line[i].end; } ! if (reg_startp[0] == NULL) ! reg_startp[0] = regline + col; ! if (reg_endp[0] == NULL) ! reg_endp[0] = reginput; } #ifdef FEAT_SYN_HL --- 6998,7037 ---- { for (i = 0; i < subs.norm.in_use; i++) { ! rex.reg_startpos[i].lnum = subs.norm.list.multi[i].start_lnum; ! rex.reg_startpos[i].col = subs.norm.list.multi[i].start_col; ! rex.reg_endpos[i].lnum = subs.norm.list.multi[i].end_lnum; ! rex.reg_endpos[i].col = subs.norm.list.multi[i].end_col; } ! if (rex.reg_startpos[0].lnum < 0) { ! rex.reg_startpos[0].lnum = 0; ! rex.reg_startpos[0].col = col; } ! if (rex.reg_endpos[0].lnum < 0) { /* pattern has a \ze but it didn't match, use current end */ ! rex.reg_endpos[0].lnum = reglnum; ! rex.reg_endpos[0].col = (int)(reginput - regline); } else /* Use line number of "\ze". */ ! reglnum = rex.reg_endpos[0].lnum; } else { for (i = 0; i < subs.norm.in_use; i++) { ! rex.reg_startp[i] = subs.norm.list.line[i].start; ! rex.reg_endp[i] = subs.norm.list.line[i].end; } ! if (rex.reg_startp[0] == NULL) ! rex.reg_startp[0] = regline + col; ! if (rex.reg_endp[0] == NULL) ! rex.reg_endp[0] = reginput; } #ifdef FEAT_SYN_HL *************** *** 7093,7108 **** if (REG_MULTI) { ! prog = (nfa_regprog_T *)reg_mmatch->regprog; line = reg_getline((linenr_T)0); /* relative to the cursor */ ! reg_startpos = reg_mmatch->startpos; ! reg_endpos = reg_mmatch->endpos; } else { ! prog = (nfa_regprog_T *)reg_match->regprog; ! reg_startp = reg_match->startp; ! reg_endp = reg_match->endp; } /* Be paranoid... */ --- 7094,7109 ---- if (REG_MULTI) { ! prog = (nfa_regprog_T *)rex.reg_mmatch->regprog; line = reg_getline((linenr_T)0); /* relative to the cursor */ ! rex.reg_startpos = rex.reg_mmatch->startpos; ! rex.reg_endpos = rex.reg_mmatch->endpos; } else { ! prog = (nfa_regprog_T *)rex.reg_match->regprog; ! rex.reg_startp = rex.reg_match->startp; ! rex.reg_endp = rex.reg_match->endp; } /* Be paranoid... */ *************** *** 7112,7127 **** goto theend; } ! /* If pattern contains "\c" or "\C": overrule value of ireg_ic */ if (prog->regflags & RF_ICASE) ! ireg_ic = TRUE; else if (prog->regflags & RF_NOICASE) ! ireg_ic = FALSE; #ifdef FEAT_MBYTE ! /* If pattern contains "\Z" overrule value of ireg_icombine */ if (prog->regflags & RF_ICOMBINE) ! ireg_icombine = TRUE; #endif regline = line; --- 7113,7128 ---- goto theend; } ! /* If pattern contains "\c" or "\C": overrule value of rex.reg_ic */ if (prog->regflags & RF_ICASE) ! rex.reg_ic = TRUE; else if (prog->regflags & RF_NOICASE) ! rex.reg_ic = FALSE; #ifdef FEAT_MBYTE ! /* If pattern contains "\Z" overrule value of rex.reg_icombine */ if (prog->regflags & RF_ICOMBINE) ! rex.reg_icombine = TRUE; #endif regline = line; *************** *** 7160,7173 **** * Nothing else to try. Doesn't handle combining chars well. */ if (prog->match_text != NULL #ifdef FEAT_MBYTE ! && !ireg_icombine #endif ) return find_match_text(col, prog->regstart, prog->match_text); } /* If the start column is past the maximum column: no need to try. */ ! if (ireg_maxcol > 0 && col >= ireg_maxcol) goto theend; nstate = prog->nstate; --- 7161,7174 ---- * Nothing else to try. Doesn't handle combining chars well. */ if (prog->match_text != NULL #ifdef FEAT_MBYTE ! && !rex.reg_icombine #endif ) return find_match_text(col, prog->regstart, prog->match_text); } /* If the start column is past the maximum column: no need to try. */ ! if (rex.reg_maxcol > 0 && col >= rex.reg_maxcol) goto theend; nstate = prog->nstate; *************** *** 7326,7342 **** colnr_T col, /* column to start looking for match */ int line_lbr) { ! reg_match = rmp; ! reg_mmatch = NULL; ! reg_maxline = 0; ! reg_line_lbr = line_lbr; ! reg_buf = curbuf; ! reg_win = NULL; ! ireg_ic = rmp->rm_ic; #ifdef FEAT_MBYTE ! ireg_icombine = FALSE; #endif ! ireg_maxcol = 0; return nfa_regexec_both(line, col, NULL); } --- 7327,7343 ---- colnr_T col, /* column to start looking for match */ int line_lbr) { ! rex.reg_match = rmp; ! rex.reg_mmatch = NULL; ! rex.reg_maxline = 0; ! rex.reg_line_lbr = line_lbr; ! rex.reg_buf = curbuf; ! rex.reg_win = NULL; ! rex.reg_ic = rmp->rm_ic; #ifdef FEAT_MBYTE ! rex.reg_icombine = FALSE; #endif ! rex.reg_maxcol = 0; return nfa_regexec_both(line, col, NULL); } *************** *** 7375,7392 **** colnr_T col, /* column to start looking for match */ proftime_T *tm) /* timeout limit or NULL */ { ! reg_match = NULL; ! reg_mmatch = rmp; ! reg_buf = buf; ! reg_win = win; ! reg_firstlnum = lnum; ! reg_maxline = reg_buf->b_ml.ml_line_count - lnum; ! reg_line_lbr = FALSE; ! ireg_ic = rmp->rmm_ic; #ifdef FEAT_MBYTE ! ireg_icombine = FALSE; #endif ! ireg_maxcol = rmp->rmm_maxcol; return nfa_regexec_both(NULL, col, tm); } --- 7376,7393 ---- colnr_T col, /* column to start looking for match */ proftime_T *tm) /* timeout limit or NULL */ { ! rex.reg_match = NULL; ! rex.reg_mmatch = rmp; ! rex.reg_buf = buf; ! rex.reg_win = win; ! rex.reg_firstlnum = lnum; ! rex.reg_maxline = rex.reg_buf->b_ml.ml_line_count - lnum; ! rex.reg_line_lbr = FALSE; ! rex.reg_ic = rmp->rmm_ic; #ifdef FEAT_MBYTE ! rex.reg_icombine = FALSE; #endif ! rex.reg_maxcol = rmp->rmm_maxcol; return nfa_regexec_both(NULL, col, tm); } *** ../vim-8.0.0019/src/testdir/test_expr.vim 2016-09-14 22:16:09.863803610 +0200 --- src/testdir/test_expr.vim 2016-10-02 16:29:45.285611327 +0200 *************** *** 405,413 **** \ {-> submatch(2) . submatch(3) . submatch(1)}, '')) func Recurse() ! return substitute('yyy', 'y*', {-> g:val}, '') endfunc ! call assert_equal('--', substitute('xxx', 'x*', {-> '-' . Recurse() . '-'}, '')) endfunc func Test_invalid_submatch() --- 405,414 ---- \ {-> submatch(2) . submatch(3) . submatch(1)}, '')) func Recurse() ! return substitute('yyy', 'y\(.\)y', {-> submatch(1)}, '') endfunc ! " recursive call works ! call assert_equal('-y-x-', substitute('xxx', 'x\(.\)x', {-> '-' . Recurse() . '-' . submatch(1) . '-'}, '')) endfunc func Test_invalid_submatch() *** ../vim-8.0.0019/runtime/doc/eval.txt 2016-09-27 21:28:52.905342034 +0200 --- runtime/doc/eval.txt 2016-10-02 16:39:09.841721025 +0200 *************** *** 7379,7384 **** --- 7390,7398 ---- |substitute()| this list will always contain one or zero items, since there are no real line breaks. + When substitute() is used recursively only the submatches in + the current (deepest) call can be obtained. + Example: > :s/\d\+/\=submatch(0) + 1/ < This finds the first number in the line and adds one to it. *** ../vim-8.0.0019/runtime/doc/change.txt 2016-09-12 12:45:25.000000000 +0200 --- runtime/doc/change.txt 2016-10-02 16:37:35.170373987 +0200 *************** *** 1,4 **** ! *change.txt* For Vim version 8.0. Last change: 2016 Sep 11 VIM REFERENCE MANUAL by Bram Moolenaar --- 1,4 ---- ! *change.txt* For Vim version 8.0. Last change: 2016 Oct 02 VIM REFERENCE MANUAL by Bram Moolenaar *************** *** 913,920 **** Substitute with an expression *sub-replace-expression* *sub-replace-\=* *s/\=* When the substitute string starts with "\=" the remainder is interpreted as an ! expression. This does not work recursively: a |substitute()| function inside ! the expression cannot use "\=" for the substitute string. The special meaning for characters as mentioned at |sub-replace-special| does not apply except for "". A character is used as a line break, you --- 913,919 ---- Substitute with an expression *sub-replace-expression* *sub-replace-\=* *s/\=* When the substitute string starts with "\=" the remainder is interpreted as an ! expression. The special meaning for characters as mentioned at |sub-replace-special| does not apply except for "". A character is used as a line break, you *** ../vim-8.0.0019/src/version.c 2016-09-29 20:54:42.407110721 +0200 --- src/version.c 2016-10-02 15:27:58.639175908 +0200 *************** *** 766,767 **** --- 766,769 ---- { /* Add new patch number below this line */ + /**/ + 20, /**/ -- With sufficient thrust, pigs fly just fine. -- RFC 1925 /// 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 ///