To: vim_dev@googlegroups.com Subject: Patch 8.1.0192 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.1.0192 Problem: Executing regexp recursively fails with a crash. Solution: Move global variables into "rex". Files: src/regexp.c, src/regexp.h, src/regexp_nfa.c *** ../vim-8.1.0191/src/regexp.c 2018-06-23 15:09:02.351412460 +0200 --- src/regexp.c 2018-07-17 05:32:30.971441868 +0200 *************** *** 344,350 **** #define MAX_LIMIT (32767L << 16L) - static int re_multi_type(int); static int cstrncmp(char_u *s1, char_u *s2, int *n); static char_u *cstrchr(char_u *, int); --- 344,349 ---- *************** *** 371,376 **** --- 370,377 ---- #endif static char_u e_missing_sb[] = N_("E69: Missing ] after %s%%["); static char_u e_empty_sb[] = N_("E70: Empty %s%%[]"); + static char_u e_recursive[] = N_("E956: Cannot use pattern recursively"); + #define NOT_MULTI 0 #define MULTI_ONE 1 #define MULTI_MULT 2 *************** *** 426,439 **** static char_u REGEXP_INRANGE[] = "]^-n\\"; static char_u REGEXP_ABBR[] = "nrtebdoxuU"; - static int backslash_trans(int c); - static int get_char_class(char_u **pp); - static int get_equi_class(char_u **pp); - static void reg_equi_class(int c); - static int get_coll_element(char_u **pp); - static char_u *skip_anyof(char_u *p); - static void init_class_tab(void); - /* * Translate '\x' to its control character, except "\n", which is Magic. */ --- 427,432 ---- *************** *** 688,695 **** * Forward declarations for vim_regcomp()'s friends. */ static void initchr(char_u *); - static void save_parse_state(parse_state_T *ps); - static void restore_parse_state(parse_state_T *ps); static int getchr(void); static void skipchr_keepstart(void); static int peekchr(void); --- 681,686 ---- *************** *** 1171,1177 **** return 0; } - static void get_cpo_flags(void); static int reg_cpo_lit; /* 'cpoptions' contains 'l' flag */ static int reg_cpo_bsl; /* 'cpoptions' contains '\' flag */ --- 1162,1167 ---- *************** *** 1322,1330 **** return TRUE; } - static regprog_T *bt_regcomp(char_u *expr, int re_flags); - static void bt_regfree(regprog_T *prog); - /* * bt_regcomp() - compile a regular expression into internal code for the * traditional back track matcher. --- 1312,1317 ---- *************** *** 1373,1378 **** --- 1360,1366 ---- r = (bt_regprog_T *)lalloc(sizeof(bt_regprog_T) + regsize, TRUE); if (r == NULL) return NULL; + r->re_in_use = FALSE; /* * Second pass: emit code. *************** *** 1525,1533 **** } #endif ! /* variables for parsing reginput */ ! static int at_start; /* True when on the first character */ ! static int prev_at_start; /* True when on the second character */ /* * Parse regular expression, i.e. main body or parenthesized thing. --- 1513,1521 ---- } #endif ! // variables used for parsing ! static int at_start; // True when on the first character ! static int prev_at_start; // True when on the second character /* * Parse regular expression, i.e. main body or parenthesized thing. *************** *** 3443,3460 **** * Global work variables for vim_regexec(). */ - /* The current match-position is remembered with these variables: */ - static linenr_T reglnum; /* line number, relative to first line */ - static char_u *regline; /* start of current line */ - static char_u *reginput; /* current input, points into "regline" */ - - static int need_clear_subexpr; /* subexpressions still need to be - * cleared */ - #ifdef FEAT_SYN_HL - static int need_clear_zsubexpr = FALSE; /* extmatch subexpressions - * still need to be cleared */ - #endif - /* * Structure used to save the current input state, when it needs to be * restored after trying a match. Used by reg_save() and reg_restore(). --- 3431,3436 ---- *************** *** 3464,3471 **** { union { ! char_u *ptr; /* reginput pointer, for single-line regexp */ ! lpos_T pos; /* reginput pos, for multi-line regexp */ } rs_u; int rs_len; } regsave_T; --- 3440,3447 ---- { union { ! char_u *ptr; /* rex.input pointer, for single-line regexp */ ! lpos_T pos; /* rex.input pos, for multi-line regexp */ } rs_u; int rs_len; } regsave_T; *************** *** 3564,3576 **** 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 --- 3540,3563 ---- linenr_T reg_maxline; int reg_line_lbr; /* "\n" in string is line break */ + // The current match-position is stord in these variables: + linenr_T lnum; // line number, relative to first line + char_u *line; // start of current line + char_u *input; // current input, points into "regline" + + int need_clear_subexpr; // subexpressions still need to be cleared + #ifdef FEAT_SYN_HL + int need_clear_zsubexpr; // extmatch subexpressions still need to be + // cleared + #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. */ int reg_ic; #ifdef FEAT_MBYTE ! /* Similar to "reg_ic", but only for 'combining' characters. Set with \Z * flag in the regexp. Defaults to false, always. */ int reg_icombine; #endif *************** *** 3578,3583 **** --- 3565,3586 ---- /* Copy of "rmm_maxcol": maximum column to search for a match. Zero when * there is no maximum. */ colnr_T reg_maxcol; + + // State for the NFA engine regexec. + int nfa_has_zend; // NFA regexp \ze operator encountered. + int nfa_has_backref; // NFA regexp \1 .. \9 encountered. + int nfa_nsubexpr; // Number of sub expressions actually being used + // during execution. 1 if only the whole match + // (subexpr 0) is used. + // listid is global, so that it increases on recursive calls to + // nfa_regmatch(), which means we don't have to clear the lastlist field of + // all the states. + int nfa_listid; + int nfa_alt_listid; + + #ifdef FEAT_SYN_HL + int nfa_has_zsubexpr; // NFA regexp has \z( ), set zsubexpr. + #endif } regexec_T; static regexec_T rex; *************** *** 3619,3625 **** { save_se_T sesave; regsave_T regsave; ! } rs_un; /* room for saving reginput */ short rs_no; /* submatch nr or BEHIND/NOBEHIND */ } regitem_T; --- 3622,3628 ---- { save_se_T sesave; regsave_T regsave; ! } rs_un; /* room for saving rex.input */ short rs_no; /* submatch nr or BEHIND/NOBEHIND */ } regitem_T; *************** *** 3896,3903 **** goto theend; } ! regline = line; ! reglnum = 0; reg_toolong = FALSE; /* Simplest case: Anchored match need be tried only once. */ --- 3899,3906 ---- goto theend; } ! rex.line = line; ! rex.lnum = 0; reg_toolong = FALSE; /* Simplest case: Anchored match need be tried only once. */ *************** *** 3907,3916 **** #ifdef FEAT_MBYTE if (has_mbyte) ! c = (*mb_ptr2char)(regline + col); else #endif ! c = regline[col]; if (prog->regstart == NUL || prog->regstart == c || (rex.reg_ic && (( --- 3910,3919 ---- #ifdef FEAT_MBYTE if (has_mbyte) ! c = (*mb_ptr2char)(rex.line + col); else #endif ! c = rex.line[col]; if (prog->regstart == NUL || prog->regstart == c || (rex.reg_ic && (( *************** *** 3940,3954 **** && !has_mbyte #endif ) ! s = vim_strbyte(regline + col, prog->regstart); else ! s = cstrchr(regline + col, prog->regstart); if (s == NULL) { retval = 0; break; } ! col = (int)(s - regline); } /* Check for maximum column to try. */ --- 3943,3957 ---- && !has_mbyte #endif ) ! s = vim_strbyte(rex.line + col, prog->regstart); else ! s = cstrchr(rex.line + col, prog->regstart); if (s == NULL) { retval = 0; break; } ! col = (int)(s - rex.line); } /* Check for maximum column to try. */ *************** *** 3963,3978 **** break; /* if not currently on the first line, get it again */ ! if (reglnum != 0) { ! reglnum = 0; ! regline = reg_getline((linenr_T)0); } ! if (regline[col] == NUL) break; #ifdef FEAT_MBYTE if (has_mbyte) ! col += (*mb_ptr2len)(regline + col); else #endif ++col; --- 3966,3981 ---- break; /* if not currently on the first line, get it again */ ! if (rex.lnum != 0) { ! rex.lnum = 0; ! rex.line = reg_getline((linenr_T)0); } ! if (rex.line[col] == NUL) break; #ifdef FEAT_MBYTE if (has_mbyte) ! col += (*mb_ptr2len)(rex.line + col); else #endif ++col; *************** *** 4052,4058 **** #endif /* ! * regtry - try match of "prog" with at regline["col"]. * Returns 0 for failure, number of lines contained in the match otherwise. */ static long --- 4055,4061 ---- #endif /* ! * regtry - try match of "prog" with at rex.line["col"]. * Returns 0 for failure, number of lines contained in the match otherwise. */ static long *************** *** 4062,4073 **** proftime_T *tm, /* timeout limit or NULL */ int *timed_out) /* flag set on timeout or NULL */ { ! reginput = regline + col; ! need_clear_subexpr = TRUE; #ifdef FEAT_SYN_HL ! /* Clear the external match subpointers if necessary. */ ! if (prog->reghasz == REX_SET) ! need_clear_zsubexpr = TRUE; #endif if (regmatch(prog->program + 1, tm, timed_out) == 0) --- 4065,4075 ---- proftime_T *tm, /* timeout limit or NULL */ int *timed_out) /* flag set on timeout or NULL */ { ! rex.input = rex.line + col; ! rex.need_clear_subexpr = TRUE; #ifdef FEAT_SYN_HL ! // Clear the external match subpointers if necessary. ! rex.need_clear_zsubexpr = (prog->reghasz == REX_SET); #endif if (regmatch(prog->program + 1, tm, timed_out) == 0) *************** *** 4083,4101 **** } 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. */ --- 4085,4103 ---- } if (rex.reg_endpos[0].lnum < 0) { ! rex.reg_endpos[0].lnum = rex.lnum; ! rex.reg_endpos[0].col = (int)(rex.input - rex.line); } else /* Use line number of "\ze". */ ! rex.lnum = rex.reg_endpos[0].lnum; } else { if (rex.reg_startp[0] == NULL) ! rex.reg_startp[0] = rex.line + col; if (rex.reg_endp[0] == NULL) ! rex.reg_endp[0] = rex.input; } #ifdef FEAT_SYN_HL /* Package any found \z(...\) matches for export. Default is none. */ *************** *** 4131,4137 **** } } #endif ! return 1 + reglnum; } #ifdef FEAT_MBYTE --- 4133,4139 ---- } } #endif ! return 1 + rex.lnum; } #ifdef FEAT_MBYTE *************** *** 4143,4151 **** static int reg_prev_class(void) { ! if (reginput > regline) ! return mb_get_class_buf(reginput - 1 ! - (*mb_head_off)(regline, reginput - 1), rex.reg_buf); return -1; } #endif --- 4145,4153 ---- static int reg_prev_class(void) { ! if (rex.input > rex.line) ! return mb_get_class_buf(rex.input - 1 ! - (*mb_head_off)(rex.line, rex.input - 1), rex.reg_buf); return -1; } #endif *************** *** 4153,4159 **** static int reg_match_visual(void); /* ! * Return TRUE if the current reginput position matches the Visual area. */ static int reg_match_visual(void) --- 4155,4161 ---- static int reg_match_visual(void); /* ! * Return TRUE if the current rex.input position matches the Visual area. */ static int reg_match_visual(void) *************** *** 4199,4211 **** } mode = curbuf->b_visual.vi_mode; } ! lnum = reglnum + rex.reg_firstlnum; if (lnum < top.lnum || lnum > bot.lnum) return FALSE; if (mode == 'v') { ! col = (colnr_T)(reginput - regline); if ((lnum == top.lnum && col < top.col) || (lnum == bot.lnum && col >= bot.col + (*p_sel != 'e'))) return FALSE; --- 4201,4213 ---- } mode = curbuf->b_visual.vi_mode; } ! lnum = rex.lnum + rex.reg_firstlnum; if (lnum < top.lnum || lnum > bot.lnum) return FALSE; if (mode == 'v') { ! col = (colnr_T)(rex.input - rex.line); if ((lnum == top.lnum && col < top.col) || (lnum == bot.lnum && col >= bot.col + (*p_sel != 'e'))) return FALSE; *************** *** 4220,4233 **** end = end2; if (top.col == MAXCOL || bot.col == MAXCOL) end = MAXCOL; ! cols = win_linetabsize(wp, regline, (colnr_T)(reginput - regline)); if (cols < start || cols > end - (*p_sel == 'e')) return FALSE; } return TRUE; } ! #define ADVANCE_REGINPUT() MB_PTR_ADV(reginput) /* * The arguments from BRACE_LIMITS are stored here. They are actually local --- 4222,4235 ---- end = end2; if (top.col == MAXCOL || bot.col == MAXCOL) end = MAXCOL; ! cols = win_linetabsize(wp, rex.line, (colnr_T)(rex.input - rex.line)); if (cols < start || cols > end - (*p_sel == 'e')) return FALSE; } return TRUE; } ! #define ADVANCE_REGINPUT() MB_PTR_ADV(rex.input) /* * The arguments from BRACE_LIMITS are stored here. They are actually local *************** *** 4247,4255 **** * (that don't need to know whether the rest of the match failed) by a nested * loop. * ! * Returns TRUE when there is a match. Leaves reginput and reglnum just after * the last matched character. ! * Returns FALSE when there is no match. Leaves reginput and reglnum in an * undefined state! */ static int --- 4249,4257 ---- * (that don't need to know whether the rest of the match failed) by a nested * loop. * ! * Returns TRUE when there is a match. Leaves rex.input and rex.lnum just after * the last matched character. ! * Returns FALSE when there is no match. Leaves rex.input and rex.lnum in an * undefined state! */ static int *************** *** 4349,4359 **** 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(); } --- 4351,4361 ---- op = OP(scan); /* Check for character class with NL added. */ if (!rex.reg_line_lbr && WITH_NL(op) && REG_MULTI ! && *rex.input == NUL && rex.lnum <= rex.reg_maxline) { reg_nextline(); } ! else if (rex.reg_line_lbr && WITH_NL(op) && *rex.input == '\n') { ADVANCE_REGINPUT(); } *************** *** 4363,4376 **** op -= ADD_NL; #ifdef FEAT_MBYTE if (has_mbyte) ! c = (*mb_ptr2char)(reginput); else #endif ! c = *reginput; switch (op) { case BOL: ! if (reginput != regline) status = RA_NOMATCH; break; --- 4365,4378 ---- op -= ADD_NL; #ifdef FEAT_MBYTE if (has_mbyte) ! c = (*mb_ptr2char)(rex.input); else #endif ! c = *rex.input; switch (op) { case BOL: ! if (rex.input != rex.line) status = RA_NOMATCH; break; *************** *** 4383,4395 **** /* We're not at the beginning of the file when below the first * 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; --- 4385,4397 ---- /* We're not at the beginning of the file when below the first * line where we started, not at the start of the line or we * didn't start at the first line of the buffer. */ ! if (rex.lnum != 0 || rex.input != rex.line || (REG_MULTI && rex.reg_firstlnum > 1)) status = RA_NOMATCH; break; case RE_EOF: ! if (rex.lnum != rex.reg_maxline || c != NUL) status = RA_NOMATCH; break; *************** *** 4397,4405 **** /* 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; --- 4399,4407 ---- /* 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 ! || (rex.lnum + rex.reg_firstlnum != rex.reg_win->w_cursor.lnum) ! || ((colnr_T)(rex.input - rex.line) != rex.reg_win->w_cursor.col)) status = RA_NOMATCH; break; *************** *** 4414,4426 **** 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; --- 4416,4428 ---- 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 == rex.lnum + rex.reg_firstlnum ! ? (pos->col == (colnr_T)(rex.input - rex.line) ? (cmp == '<' || cmp == '>') ! : (pos->col < (colnr_T)(rex.input - rex.line) ? cmp != '>' : cmp != '<')) ! : (pos->lnum < rex.lnum + rex.reg_firstlnum ? cmp != '>' : cmp != '<'))) status = RA_NOMATCH; *************** *** 4433,4456 **** break; case RE_LNUM: ! if (!REG_MULTI || !re_num_cmp((long_u)(reglnum + rex.reg_firstlnum), scan)) status = RA_NOMATCH; break; case RE_COL: ! if (!re_num_cmp((long_u)(reginput - regline) + 1, scan)) status = RA_NOMATCH; break; 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; ! case BOW: /* \ regline ! && vim_iswordc_buf(reginput[-1], rex.reg_buf))) status = RA_NOMATCH; } break; ! case EOW: /* word\>; reginput points after d */ ! if (reginput == regline) /* Can't match at start of line */ status = RA_NOMATCH; #ifdef FEAT_MBYTE else if (has_mbyte) --- 4470,4483 ---- #endif else { ! if (!vim_iswordc_buf(c, rex.reg_buf) || (rex.input > rex.line ! && vim_iswordc_buf(rex.input[-1], rex.reg_buf))) status = RA_NOMATCH; } break; ! case EOW: /* word\>; rex.input points after d */ ! if (rex.input == rex.line) /* Can't match at start of line */ status = RA_NOMATCH; #ifdef FEAT_MBYTE else if (has_mbyte) *************** *** 4483,4489 **** 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) --- 4485,4491 ---- int this_class, prev_class; /* Get class of current and previous char (if it exists). */ ! this_class = mb_get_class_buf(rex.input, rex.reg_buf); prev_class = reg_prev_class(); if (this_class == prev_class || prev_class == 0 || prev_class == 1) *************** *** 4492,4499 **** #endif else { ! if (!vim_iswordc_buf(reginput[-1], rex.reg_buf) ! || (reginput[0] != NUL && vim_iswordc_buf(c, rex.reg_buf))) status = RA_NOMATCH; } --- 4494,4501 ---- #endif else { ! if (!vim_iswordc_buf(rex.input[-1], rex.reg_buf) ! || (rex.input[0] != NUL && vim_iswordc_buf(c, rex.reg_buf))) status = RA_NOMATCH; } *************** *** 4515,4536 **** break; case SIDENT: ! if (VIM_ISDIGIT(*reginput) || !vim_isIDc(c)) status = RA_NOMATCH; else ADVANCE_REGINPUT(); 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(); --- 4517,4538 ---- break; case SIDENT: ! if (VIM_ISDIGIT(*rex.input) || !vim_isIDc(c)) status = RA_NOMATCH; else ADVANCE_REGINPUT(); break; case KWORD: ! if (!vim_iswordp_buf(rex.input, rex.reg_buf)) status = RA_NOMATCH; else ADVANCE_REGINPUT(); break; case SKWORD: ! if (VIM_ISDIGIT(*rex.input) ! || !vim_iswordp_buf(rex.input, rex.reg_buf)) status = RA_NOMATCH; else ADVANCE_REGINPUT(); *************** *** 4544,4564 **** break; case SFNAME: ! if (VIM_ISDIGIT(*reginput) || !vim_isfilec(c)) status = RA_NOMATCH; else ADVANCE_REGINPUT(); break; case PRINT: ! if (!vim_isprintc(PTR2CHAR(reginput))) status = RA_NOMATCH; else ADVANCE_REGINPUT(); break; case SPRINT: ! if (VIM_ISDIGIT(*reginput) || !vim_isprintc(PTR2CHAR(reginput))) status = RA_NOMATCH; else ADVANCE_REGINPUT(); --- 4546,4566 ---- break; case SFNAME: ! if (VIM_ISDIGIT(*rex.input) || !vim_isfilec(c)) status = RA_NOMATCH; else ADVANCE_REGINPUT(); break; case PRINT: ! if (!vim_isprintc(PTR2CHAR(rex.input))) status = RA_NOMATCH; else ADVANCE_REGINPUT(); break; case SPRINT: ! if (VIM_ISDIGIT(*rex.input) || !vim_isprintc(PTR2CHAR(rex.input))) status = RA_NOMATCH; else ADVANCE_REGINPUT(); *************** *** 4697,4708 **** opnd = OPERAND(scan); /* Inline the first byte, for speed. */ ! if (*opnd != *reginput && (!rex.reg_ic || ( #ifdef FEAT_MBYTE !enc_utf8 && #endif ! MB_TOLOWER(*opnd) != MB_TOLOWER(*reginput)))) status = RA_NOMATCH; else if (*opnd == NUL) { --- 4699,4710 ---- opnd = OPERAND(scan); /* Inline the first byte, for speed. */ ! if (*opnd != *rex.input && (!rex.reg_ic || ( #ifdef FEAT_MBYTE !enc_utf8 && #endif ! MB_TOLOWER(*opnd) != MB_TOLOWER(*rex.input)))) status = RA_NOMATCH; else if (*opnd == NUL) { *************** *** 4723,4729 **** { /* Need to match first byte again for multi-byte. */ len = (int)STRLEN(opnd); ! if (cstrncmp(opnd, reginput, &len) != 0) status = RA_NOMATCH; } #ifdef FEAT_MBYTE --- 4725,4731 ---- { /* Need to match first byte again for multi-byte. */ len = (int)STRLEN(opnd); ! if (cstrncmp(opnd, rex.input, &len) != 0) status = RA_NOMATCH; } #ifdef FEAT_MBYTE *************** *** 4731,4737 **** * follows (skips over all composing chars). */ if (status != RA_NOMATCH && enc_utf8 ! && UTF_COMPOSINGLIKE(reginput, reginput + len) && !rex.reg_icombine && OP(next) != RE_COMPOSING) { --- 4733,4739 ---- * follows (skips over all composing chars). */ if (status != RA_NOMATCH && enc_utf8 ! && UTF_COMPOSINGLIKE(rex.input, rex.input + len) && !rex.reg_icombine && OP(next) != RE_COMPOSING) { *************** *** 4742,4748 **** } #endif if (status != RA_NOMATCH) ! reginput += len; } } break; --- 4744,4750 ---- } #endif if (status != RA_NOMATCH) ! rex.input += len; } } break; *************** *** 4780,4789 **** /* When only a composing char is given match at any * position where that composing char appears. */ status = RA_NOMATCH; ! for (i = 0; reginput[i] != NUL; ! i += utf_ptr2len(reginput + i)) { ! inpc = utf_ptr2char(reginput + i); if (!utf_iscomposing(inpc)) { if (i > 0) --- 4782,4791 ---- /* When only a composing char is given match at any * position where that composing char appears. */ status = RA_NOMATCH; ! for (i = 0; rex.input[i] != NUL; ! i += utf_ptr2len(rex.input + i)) { ! inpc = utf_ptr2char(rex.input + i); if (!utf_iscomposing(inpc)) { if (i > 0) *************** *** 4792,4798 **** else if (opndc == inpc) { /* Include all following composing chars. */ ! len = i + utfc_ptr2len(reginput + i); status = RA_MATCH; break; } --- 4794,4800 ---- else if (opndc == inpc) { /* Include all following composing chars. */ ! len = i + utfc_ptr2len(rex.input + i); status = RA_MATCH; break; } *************** *** 4800,4811 **** } else for (i = 0; i < len; ++i) ! if (opnd[i] != reginput[i]) { status = RA_NOMATCH; break; } ! reginput += len; } else status = RA_NOMATCH; --- 4802,4813 ---- } else for (i = 0; i < len; ++i) ! if (opnd[i] != rex.input[i]) { status = RA_NOMATCH; break; } ! rex.input += len; } else status = RA_NOMATCH; *************** *** 4816,4823 **** if (enc_utf8) { /* Skip composing characters. */ ! while (utf_iscomposing(utf_ptr2char(reginput))) ! MB_CPTR_ADV(reginput); } #endif break; --- 4818,4825 ---- if (enc_utf8) { /* Skip composing characters. */ ! while (utf_iscomposing(utf_ptr2char(rex.input))) ! MB_CPTR_ADV(rex.input); } #endif break; *************** *** 5003,5009 **** /* 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; } } --- 5005,5011 ---- /* 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], rex.input, &len) != 0) status = RA_NOMATCH; } } *************** *** 5017,5030 **** } 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; } else --- 5019,5032 ---- } else { ! if (rex.reg_startpos[no].lnum == rex.lnum ! && rex.reg_endpos[no].lnum == rex.lnum) { /* Compare back-ref within the current line. */ len = rex.reg_endpos[no].col - rex.reg_startpos[no].col; ! if (cstrncmp(rex.line + rex.reg_startpos[no].col, ! rex.input, &len) != 0) status = RA_NOMATCH; } else *************** *** 5045,5051 **** } /* Matched the backref, skip over it. */ ! reginput += len; } break; --- 5047,5053 ---- } /* Matched the backref, skip over it. */ ! rex.input += len; } break; *************** *** 5069,5078 **** { len = (int)STRLEN(re_extmatch_in->matches[no]); if (cstrncmp(re_extmatch_in->matches[no], ! reginput, &len) != 0) status = RA_NOMATCH; else ! reginput += len; } else { --- 5071,5080 ---- { len = (int)STRLEN(re_extmatch_in->matches[no]); if (cstrncmp(re_extmatch_in->matches[no], ! rex.input, &len) != 0) status = RA_NOMATCH; else ! rex.input += len; } else { *************** *** 5319,5334 **** case BHPOS: if (REG_MULTI) { ! if (behind_pos.rs_u.pos.col != (colnr_T)(reginput - regline) ! || behind_pos.rs_u.pos.lnum != reglnum) status = RA_NOMATCH; } ! else if (behind_pos.rs_u.ptr != reginput) status = RA_NOMATCH; 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; --- 5321,5336 ---- case BHPOS: if (REG_MULTI) { ! if (behind_pos.rs_u.pos.col != (colnr_T)(rex.input - rex.line) ! || behind_pos.rs_u.pos.lnum != rex.lnum) status = RA_NOMATCH; } ! else if (behind_pos.rs_u.ptr != rex.input) status = RA_NOMATCH; break; case NEWL: ! if ((c != NUL || !REG_MULTI || rex.lnum > rex.reg_maxline || rex.reg_line_lbr) && (c != '\n' || !rex.reg_line_lbr)) status = RA_NOMATCH; *************** *** 5562,5568 **** if (limit > 0 && ((rp->rs_un.regsave.rs_u.pos.lnum < behind_pos.rs_u.pos.lnum ! ? (colnr_T)STRLEN(regline) : behind_pos.rs_u.pos.col) - rp->rs_un.regsave.rs_u.pos.col >= limit)) no = FAIL; --- 5564,5570 ---- if (limit > 0 && ((rp->rs_un.regsave.rs_u.pos.lnum < behind_pos.rs_u.pos.lnum ! ? (colnr_T)STRLEN(rex.line) : behind_pos.rs_u.pos.col) - rp->rs_un.regsave.rs_u.pos.col >= limit)) no = FAIL; *************** *** 5578,5584 **** { reg_restore(&rp->rs_un.regsave, &backpos); rp->rs_un.regsave.rs_u.pos.col = ! (colnr_T)STRLEN(regline); } } else --- 5580,5586 ---- { reg_restore(&rp->rs_un.regsave, &backpos); rp->rs_un.regsave.rs_u.pos.col = ! (colnr_T)STRLEN(rex.line); } } else *************** *** 5600,5610 **** } else { ! if (rp->rs_un.regsave.rs_u.ptr == regline) no = FAIL; else { ! MB_PTR_BACK(regline, rp->rs_un.regsave.rs_u.ptr); if (limit > 0 && (long)(behind_pos.rs_u.ptr - rp->rs_un.regsave.rs_u.ptr) > limit) no = FAIL; --- 5602,5612 ---- } else { ! if (rp->rs_un.regsave.rs_u.ptr == rex.line) no = FAIL; else { ! MB_PTR_BACK(rex.line, rp->rs_un.regsave.rs_u.ptr); if (limit > 0 && (long)(behind_pos.rs_u.ptr - rp->rs_un.regsave.rs_u.ptr) > limit) no = FAIL; *************** *** 5678,5697 **** * didn't match -- back up one char. */ if (--rst->count < rst->minval) break; ! if (reginput == regline) { /* backup to last char of previous line */ ! --reglnum; ! regline = reg_getline(reglnum); /* Just in case regrepeat() didn't count * right. */ ! if (regline == NULL) break; ! reginput = regline + STRLEN(regline); fast_breakcheck(); } else ! MB_PTR_BACK(regline, reginput); } else { --- 5680,5699 ---- * didn't match -- back up one char. */ if (--rst->count < rst->minval) break; ! if (rex.input == rex.line) { /* backup to last char of previous line */ ! --rex.lnum; ! rex.line = reg_getline(rex.lnum); /* Just in case regrepeat() didn't count * right. */ ! if (rex.line == NULL) break; ! rex.input = rex.line + STRLEN(rex.line); fast_breakcheck(); } else ! MB_PTR_BACK(rex.line, rex.input); } else { *************** *** 5711,5718 **** status = RA_NOMATCH; /* If it could match, try it. */ ! if (rst->nextb == NUL || *reginput == rst->nextb ! || *reginput == rst->nextb_ic) { reg_save(&rp->rs_un.regsave, &backpos); scan = regnext(rp->rs_scan); --- 5713,5720 ---- status = RA_NOMATCH; /* If it could match, try it. */ ! if (rst->nextb == NUL || *rex.input == rst->nextb ! || *rex.input == rst->nextb_ic) { reg_save(&rp->rs_un.regsave, &backpos); scan = regnext(rp->rs_scan); *************** *** 5807,5813 **** /* * regrepeat - repeatedly match something simple, return how many. ! * Advances reginput (and reglnum) to just after the matched chars. */ static int regrepeat( --- 5809,5815 ---- /* * regrepeat - repeatedly match something simple, return how many. ! * Advances rex.input (and rex.lnum) to just after the matched chars. */ static int regrepeat( *************** *** 5820,5826 **** int mask; int testval = 0; ! scan = reginput; /* Make local copy of reginput for speed. */ opnd = OPERAND(p); switch (OP(p)) { --- 5822,5828 ---- int mask; int testval = 0; ! scan = rex.input; /* Make local copy of rex.input for speed. */ opnd = OPERAND(p); switch (OP(p)) { *************** *** 5835,5846 **** ++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(); ! scan = reginput; if (got_int) break; } --- 5837,5848 ---- ++count; MB_PTR_ADV(scan); } ! if (!REG_MULTI || !WITH_NL(OP(p)) || rex.lnum > rex.reg_maxline || rex.reg_line_lbr || count == maxcount) break; ++count; /* count the line-break */ reg_nextline(); ! scan = rex.input; if (got_int) break; } *************** *** 5860,5870 **** } 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; } --- 5862,5872 ---- } else if (*scan == NUL) { ! if (!REG_MULTI || !WITH_NL(OP(p)) || rex.lnum > rex.reg_maxline || rex.reg_line_lbr) break; reg_nextline(); ! scan = rex.input; if (got_int) break; } *************** *** 5891,5901 **** } 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; } --- 5893,5903 ---- } else if (*scan == NUL) { ! if (!REG_MULTI || !WITH_NL(OP(p)) || rex.lnum > rex.reg_maxline || rex.reg_line_lbr) break; reg_nextline(); ! scan = rex.input; if (got_int) break; } *************** *** 5921,5931 **** } 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; } --- 5923,5933 ---- } else if (*scan == NUL) { ! if (!REG_MULTI || !WITH_NL(OP(p)) || rex.lnum > rex.reg_maxline || rex.reg_line_lbr) break; reg_nextline(); ! scan = rex.input; if (got_int) break; } *************** *** 5947,5957 **** { 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; } --- 5949,5959 ---- { if (*scan == NUL) { ! if (!REG_MULTI || !WITH_NL(OP(p)) || rex.lnum > rex.reg_maxline || rex.reg_line_lbr) break; reg_nextline(); ! scan = rex.input; if (got_int) break; } *************** *** 5979,5989 **** #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; } --- 5981,5991 ---- #endif if (*scan == NUL) { ! if (!REG_MULTI || !WITH_NL(OP(p)) || rex.lnum > rex.reg_maxline || rex.reg_line_lbr) break; reg_nextline(); ! scan = rex.input; if (got_int) break; } *************** *** 6144,6154 **** #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; } --- 6146,6156 ---- #endif if (*scan == NUL) { ! if (!REG_MULTI || !WITH_NL(OP(p)) || rex.lnum > rex.reg_maxline || rex.reg_line_lbr) break; reg_nextline(); ! scan = rex.input; if (got_int) break; } *************** *** 6174,6180 **** case NEWL: while (count < maxcount ! && ((*scan == NUL && reglnum <= rex.reg_maxline && !rex.reg_line_lbr && REG_MULTI) || (*scan == '\n' && rex.reg_line_lbr))) { --- 6176,6182 ---- case NEWL: while (count < maxcount ! && ((*scan == NUL && rex.lnum <= rex.reg_maxline && !rex.reg_line_lbr && REG_MULTI) || (*scan == '\n' && rex.reg_line_lbr))) { *************** *** 6183,6189 **** ADVANCE_REGINPUT(); else reg_nextline(); ! scan = reginput; if (got_int) break; } --- 6185,6191 ---- ADVANCE_REGINPUT(); else reg_nextline(); ! scan = rex.input; if (got_int) break; } *************** *** 6197,6203 **** break; } ! reginput = scan; return (int)count; } --- 6199,6205 ---- break; } ! rex.input = scan; return (int)count; } *************** *** 6255,6261 **** static void cleanup_subexpr(void) { ! if (need_clear_subexpr) { if (REG_MULTI) { --- 6257,6263 ---- static void cleanup_subexpr(void) { ! if (rex.need_clear_subexpr) { if (REG_MULTI) { *************** *** 6268,6274 **** vim_memset(rex.reg_startp, 0, sizeof(char_u *) * NSUBEXP); vim_memset(rex.reg_endp, 0, sizeof(char_u *) * NSUBEXP); } ! need_clear_subexpr = FALSE; } } --- 6270,6276 ---- vim_memset(rex.reg_startp, 0, sizeof(char_u *) * NSUBEXP); vim_memset(rex.reg_endp, 0, sizeof(char_u *) * NSUBEXP); } ! rex.need_clear_subexpr = FALSE; } } *************** *** 6276,6282 **** static void cleanup_zsubexpr(void) { ! if (need_clear_zsubexpr) { if (REG_MULTI) { --- 6278,6284 ---- static void cleanup_zsubexpr(void) { ! if (rex.need_clear_zsubexpr) { if (REG_MULTI) { *************** *** 6289,6295 **** vim_memset(reg_startzp, 0, sizeof(char_u *) * NSUBEXP); vim_memset(reg_endzp, 0, sizeof(char_u *) * NSUBEXP); } ! need_clear_zsubexpr = FALSE; } } #endif --- 6291,6297 ---- vim_memset(reg_startzp, 0, sizeof(char_u *) * NSUBEXP); vim_memset(reg_endzp, 0, sizeof(char_u *) * NSUBEXP); } ! rex.need_clear_zsubexpr = FALSE; } } #endif *************** *** 6303,6312 **** { int i; ! /* When "need_clear_subexpr" is set we don't need to save the values, only * remember that this flag needs to be set again when restoring. */ ! bp->save_need_clear_subexpr = need_clear_subexpr; ! if (!need_clear_subexpr) { for (i = 0; i < NSUBEXP; ++i) { --- 6305,6314 ---- { int i; ! /* When "rex.need_clear_subexpr" is set we don't need to save the values, only * remember that this flag needs to be set again when restoring. */ ! bp->save_need_clear_subexpr = rex.need_clear_subexpr; ! if (!rex.need_clear_subexpr) { for (i = 0; i < NSUBEXP; ++i) { *************** *** 6333,6340 **** int i; /* Only need to restore saved values when they are not to be cleared. */ ! need_clear_subexpr = bp->save_need_clear_subexpr; ! if (!need_clear_subexpr) { for (i = 0; i < NSUBEXP; ++i) { --- 6335,6342 ---- int i; /* Only need to restore saved values when they are not to be cleared. */ ! rex.need_clear_subexpr = bp->save_need_clear_subexpr; ! if (!rex.need_clear_subexpr) { for (i = 0; i < NSUBEXP; ++i) { *************** *** 6353,6365 **** } /* ! * Advance reglnum, regline and reginput to the next line. */ static void reg_nextline(void) { ! regline = reg_getline(++reglnum); ! reginput = regline; fast_breakcheck(); } --- 6355,6367 ---- } /* ! * Advance rex.lnum, rex.line and rex.input to the next line. */ static void reg_nextline(void) { ! rex.line = reg_getline(++rex.lnum); ! rex.input = rex.line; fast_breakcheck(); } *************** *** 6371,6381 **** { if (REG_MULTI) { ! save->rs_u.pos.col = (colnr_T)(reginput - regline); ! save->rs_u.pos.lnum = reglnum; } else ! save->rs_u.ptr = reginput; save->rs_len = gap->ga_len; } --- 6373,6383 ---- { if (REG_MULTI) { ! save->rs_u.pos.col = (colnr_T)(rex.input - rex.line); ! save->rs_u.pos.lnum = rex.lnum; } else ! save->rs_u.ptr = rex.input; save->rs_len = gap->ga_len; } *************** *** 6387,6403 **** { if (REG_MULTI) { ! if (reglnum != save->rs_u.pos.lnum) { /* only call reg_getline() when the line number changed to save * a bit of time */ ! reglnum = save->rs_u.pos.lnum; ! regline = reg_getline(reglnum); } ! reginput = regline + save->rs_u.pos.col; } else ! reginput = save->rs_u.ptr; gap->ga_len = save->rs_len; } --- 6389,6405 ---- { if (REG_MULTI) { ! if (rex.lnum != save->rs_u.pos.lnum) { /* only call reg_getline() when the line number changed to save * a bit of time */ ! rex.lnum = save->rs_u.pos.lnum; ! rex.line = reg_getline(rex.lnum); } ! rex.input = rex.line + save->rs_u.pos.col; } else ! rex.input = save->rs_u.ptr; gap->ga_len = save->rs_len; } *************** *** 6408,6416 **** reg_save_equal(regsave_T *save) { if (REG_MULTI) ! return reglnum == save->rs_u.pos.lnum ! && reginput == regline + save->rs_u.pos.col; ! return reginput == save->rs_u.ptr; } /* --- 6410,6418 ---- reg_save_equal(regsave_T *save) { if (REG_MULTI) ! return rex.lnum == save->rs_u.pos.lnum ! && rex.input == rex.line + save->rs_u.pos.col; ! return rex.input == save->rs_u.ptr; } /* *************** *** 6424,6438 **** save_se_multi(save_se_T *savep, lpos_T *posp) { savep->se_u.pos = *posp; ! posp->lnum = reglnum; ! posp->col = (colnr_T)(reginput - regline); } static void save_se_one(save_se_T *savep, char_u **pp) { savep->se_u.ptr = *pp; ! *pp = reginput; } /* --- 6426,6440 ---- save_se_multi(save_se_T *savep, lpos_T *posp) { savep->se_u.pos = *posp; ! posp->lnum = rex.lnum; ! posp->col = (colnr_T)(rex.input - rex.line); } static void save_se_one(save_se_T *savep, char_u **pp) { savep->se_u.ptr = *pp; ! *pp = rex.input; } /* *************** *** 6475,6483 **** { /* Since getting one line may invalidate the other, need to make copy. * Slow! */ ! if (regline != reg_tofree) { ! len = (int)STRLEN(regline); if (reg_tofree == NULL || len >= (int)reg_tofreelen) { len += 50; /* get some extra */ --- 6477,6485 ---- { /* Since getting one line may invalidate the other, need to make copy. * Slow! */ ! if (rex.line != reg_tofree) { ! len = (int)STRLEN(rex.line); if (reg_tofree == NULL || len >= (int)reg_tofreelen) { len += 50; /* get some extra */ *************** *** 6487,6495 **** return RA_FAIL; /* out of memory!*/ reg_tofreelen = len; } ! STRCPY(reg_tofree, regline); ! reginput = reg_tofree + (reginput - regline); ! regline = reg_tofree; } /* Get the line to compare with. */ --- 6489,6497 ---- return RA_FAIL; /* out of memory!*/ reg_tofreelen = len; } ! STRCPY(reg_tofree, rex.line); ! rex.input = reg_tofree + (rex.input - rex.line); ! rex.line = reg_tofree; } /* Get the line to compare with. */ *************** *** 6499,6511 **** else len = (int)STRLEN(p + ccol); ! if (cstrncmp(p + ccol, reginput, &len) != 0) return RA_NOMATCH; /* doesn't match */ if (bytelen != NULL) *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. */ --- 6501,6513 ---- else len = (int)STRLEN(p + ccol); ! if (cstrncmp(p + ccol, rex.input, &len) != 0) return RA_NOMATCH; /* doesn't match */ if (bytelen != NULL) *bytelen += len; if (clnum == end_lnum) break; /* match and at end! */ ! if (rex.lnum >= rex.reg_maxline) return RA_NOMATCH; /* text too short */ /* Advance to next line. */ *************** *** 6518,6524 **** return RA_FAIL; } ! /* found a match! Note that regline may now point to a copy of the line, * that should not matter. */ return RA_MATCH; } --- 6520,6526 ---- return RA_FAIL; } ! /* found a match! Note that rex.line may now point to a copy of the line, * that should not matter. */ return RA_MATCH; } *************** *** 8144,8151 **** --- 8146,8155 ---- regexp_engine = AUTOMATIC_ENGINE; } } + #ifdef DEBUG bt_regengine.expr = expr; nfa_regengine.expr = expr; + #endif /* * First try the NFA engine, unless backtracking was requested. *************** *** 8243,8252 **** 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; --- 8247,8265 ---- regexec_T rex_save; int rex_in_use_save = rex_in_use; + // Cannot use the same prog recursively, it contains state. + if (rmp->regprog->re_in_use) + { + EMSG(_(e_recursive)); + return FALSE; + } + rmp->regprog->re_in_use = TRUE; + 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; *************** *** 8281,8286 **** --- 8294,8300 ---- rex_in_use = rex_in_use_save; if (rex_in_use) rex = rex_save; + rmp->regprog->re_in_use = FALSE; return result > 0; } *************** *** 8353,8358 **** --- 8367,8380 ---- regexec_T rex_save; int rex_in_use_save = rex_in_use; + // Cannot use the same prog recursively, it contains state. + if (rmp->regprog->re_in_use) + { + EMSG(_(e_recursive)); + return FALSE; + } + rmp->regprog->re_in_use = TRUE; + if (rex_in_use) /* Being called recursively, save the state. */ rex_save = rex; *************** *** 8397,8402 **** --- 8419,8425 ---- rex_in_use = rex_in_use_save; if (rex_in_use) rex = rex_save; + rmp->regprog->re_in_use = FALSE; return result <= 0 ? 0 : result; } *** ../vim-8.1.0191/src/regexp.h 2017-06-17 17:52:18.000000000 +0200 --- src/regexp.h 2018-07-17 05:08:49.564483204 +0200 *************** *** 50,57 **** { regengine_T *engine; unsigned regflags; ! unsigned re_engine; /* automatic, backtracking or nfa engine */ ! unsigned re_flags; /* second argument for vim_regcomp() */ } regprog_T; /* --- 50,58 ---- { regengine_T *engine; unsigned regflags; ! unsigned re_engine; // automatic, backtracking or nfa engine ! unsigned re_flags; // second argument for vim_regcomp() ! int re_in_use; // prog is being executed } regprog_T; /* *************** *** 65,71 **** regengine_T *engine; unsigned regflags; unsigned re_engine; ! unsigned re_flags; /* second argument for vim_regcomp() */ int regstart; char_u reganch; --- 66,73 ---- regengine_T *engine; unsigned regflags; unsigned re_engine; ! unsigned re_flags; ! int re_in_use; int regstart; char_u reganch; *************** *** 101,107 **** regengine_T *engine; unsigned regflags; unsigned re_engine; ! unsigned re_flags; /* second argument for vim_regcomp() */ nfa_state_T *start; /* points into state[] */ --- 103,110 ---- regengine_T *engine; unsigned regflags; unsigned re_engine; ! unsigned re_flags; ! int re_in_use; nfa_state_T *start; /* points into state[] */ *** ../vim-8.1.0191/src/regexp_nfa.c 2018-07-08 19:07:16.159415508 +0200 --- src/regexp_nfa.c 2018-07-17 05:08:49.568483181 +0200 *************** *** 244,284 **** static char_u e_misplaced[] = N_("E866: (NFA regexp) Misplaced %c"); static char_u e_ill_char_class[] = N_("E877: (NFA regexp) Invalid character class: %ld"); ! /* re_flags passed to nfa_regcomp() */ ! static int nfa_re_flags; ! ! /* NFA regexp \ze operator encountered. */ ! static int nfa_has_zend; ! ! /* NFA regexp \1 .. \9 encountered. */ ! static int nfa_has_backref; ! ! #ifdef FEAT_SYN_HL ! /* NFA regexp has \z( ), set zsubexpr. */ ! static int nfa_has_zsubexpr; ! #endif ! ! /* Number of sub expressions actually being used during execution. 1 if only ! * the whole match (subexpr 0) is used. */ ! static int nfa_nsubexpr; ! ! static int *post_start; /* holds the postfix form of r.e. */ static int *post_end; static int *post_ptr; ! ! static int nstate; /* Number of states in the NFA. Also used when ! * executing. */ ! static int istate; /* Index in the state vector, used in alloc_state() */ /* If not NULL match must end at this position */ static save_se_T *nfa_endp = NULL; - /* listid is global, so that it increases on recursive calls to - * nfa_regmatch(), which means we don't have to clear the lastlist field of - * all the states. */ - static int nfa_listid; - static int nfa_alt_listid; - /* 0 for first call to nfa_regmatch(), 1 for recursive call. */ static int nfa_ll_index = 0; --- 244,260 ---- static char_u e_misplaced[] = N_("E866: (NFA regexp) Misplaced %c"); static char_u e_ill_char_class[] = N_("E877: (NFA regexp) Invalid character class: %ld"); ! // Variables only used in nfa_regcomp() and descendants. ! static int nfa_re_flags; // re_flags passed to nfa_regcomp() ! static int *post_start; // holds the postfix form of r.e. static int *post_end; static int *post_ptr; ! static int nstate; // Number of states in the NFA. ! static int istate; // Index in the state vector, used in alloc_state() /* If not NULL match must end at this position */ static save_se_T *nfa_endp = NULL; /* 0 for first call to nfa_regmatch(), 1 for recursive call. */ static int nfa_ll_index = 0; *************** *** 326,333 **** return FAIL; post_ptr = post_start; post_end = post_start + nstate_max; ! nfa_has_zend = FALSE; ! nfa_has_backref = FALSE; /* shared with BT engine */ regcomp_start(expr, re_flags); --- 302,309 ---- return FAIL; post_ptr = post_start; post_end = post_start + nstate_max; ! rex.nfa_has_zend = FALSE; ! rex.nfa_has_backref = FALSE; /* shared with BT engine */ regcomp_start(expr, re_flags); *************** *** 1422,1428 **** if (!seen_endbrace(refnum + 1)) return FAIL; EMIT(NFA_BACKREF1 + refnum); ! nfa_has_backref = TRUE; } break; --- 1398,1404 ---- if (!seen_endbrace(refnum + 1)) return FAIL; EMIT(NFA_BACKREF1 + refnum); ! rex.nfa_has_backref = TRUE; } break; *************** *** 1437,1443 **** break; case 'e': EMIT(NFA_ZEND); ! nfa_has_zend = TRUE; if (re_mult_next("\\ze") == FAIL) return FAIL; break; --- 1413,1419 ---- break; case 'e': EMIT(NFA_ZEND); ! rex.nfa_has_zend = TRUE; if (re_mult_next("\\ze") == FAIL) return FAIL; break; *************** *** 1455,1461 **** if ((reg_do_extmatch & REX_USE) == 0) EMSG_RET_FAIL(_(e_z1_not_allowed)); EMIT(NFA_ZREF1 + (no_Magic(c) - '1')); ! /* No need to set nfa_has_backref, the sub-matches don't * change when \z1 .. \z9 matches or not. */ re_has_z = REX_USE; break; --- 1431,1437 ---- if ((reg_do_extmatch & REX_USE) == 0) EMSG_RET_FAIL(_(e_z1_not_allowed)); EMIT(NFA_ZREF1 + (no_Magic(c) - '1')); ! /* No need to set rex.nfa_has_backref, the sub-matches don't * change when \z1 .. \z9 matches or not. */ re_has_z = REX_USE; break; *************** *** 2920,2930 **** if (df) { fprintf(df, "Error popping the stack!\n"); ! #ifdef DEBUG fprintf(df, "Current regexp is \"%s\"\n", nfa_regengine.expr); ! #endif fprintf(df, "Postfix form is: "); ! #ifdef DEBUG for (p2 = postfix; p2 < end; p2++) { nfa_set_code(*p2); --- 2896,2906 ---- if (df) { fprintf(df, "Error popping the stack!\n"); ! # ifdef DEBUG fprintf(df, "Current regexp is \"%s\"\n", nfa_regengine.expr); ! # endif fprintf(df, "Postfix form is: "); ! # ifdef DEBUG for (p2 = postfix; p2 < end; p2++) { nfa_set_code(*p2); *************** *** 2937,2943 **** nfa_set_code(*p2); fprintf(df, "%s, ", code); } ! #else for (p2 = postfix; p2 < end; p2++) { fprintf(df, "%d, ", *p2); --- 2913,2919 ---- nfa_set_code(*p2); fprintf(df, "%s, ", code); } ! # else for (p2 = postfix; p2 < end; p2++) { fprintf(df, "%d, ", *p2); *************** *** 2947,2953 **** { fprintf(df, "%d, ", *p2); } ! #endif fprintf(df, "\n--------------------------\n"); fclose(df); } --- 2923,2929 ---- { fprintf(df, "%d, ", *p2); } ! # endif fprintf(df, "\n--------------------------\n"); fclose(df); } *************** *** 3887,3893 **** { log_subexpr(&subs->norm); # ifdef FEAT_SYN_HL ! if (nfa_has_zsubexpr) log_subexpr(&subs->synt); # endif } --- 3863,3869 ---- { log_subexpr(&subs->norm); # ifdef FEAT_SYN_HL ! if (rex.nfa_has_zsubexpr) log_subexpr(&subs->synt); # endif } *************** *** 3927,3933 **** else { sprintf(buf, " PIM col %d", REG_MULTI ? (int)pim->end.pos.col ! : (int)(pim->end.ptr - reginput)); } return buf; } --- 3903,3909 ---- else { sprintf(buf, " PIM col %d", REG_MULTI ? (int)pim->end.pos.col ! : (int)(pim->end.ptr - rex.input)); } return buf; } *************** *** 3955,3961 **** to->state = from->state; copy_sub(&to->subs.norm, &from->subs.norm); #ifdef FEAT_SYN_HL ! if (nfa_has_zsubexpr) copy_sub(&to->subs.synt, &from->subs.synt); #endif to->end = from->end; --- 3931,3937 ---- to->state = from->state; copy_sub(&to->subs.norm, &from->subs.norm); #ifdef FEAT_SYN_HL ! if (rex.nfa_has_zsubexpr) copy_sub(&to->subs.synt, &from->subs.synt); #endif to->end = from->end; *************** *** 3967,3975 **** if (REG_MULTI) /* Use 0xff to set lnum to -1 */ vim_memset(sub->list.multi, 0xff, ! sizeof(struct multipos) * nfa_nsubexpr); else ! vim_memset(sub->list.line, 0, sizeof(struct linepos) * nfa_nsubexpr); sub->in_use = 0; } --- 3943,3952 ---- if (REG_MULTI) /* Use 0xff to set lnum to -1 */ vim_memset(sub->list.multi, 0xff, ! sizeof(struct multipos) * rex.nfa_nsubexpr); else ! vim_memset(sub->list.line, 0, ! sizeof(struct linepos) * rex.nfa_nsubexpr); sub->in_use = 0; } *************** *** 4022,4028 **** static void copy_ze_off(regsub_T *to, regsub_T *from) { ! if (nfa_has_zend) { if (REG_MULTI) { --- 3999,4005 ---- static void copy_ze_off(regsub_T *to, regsub_T *from) { ! if (rex.nfa_has_zend) { if (REG_MULTI) { *************** *** 4073,4079 **** != sub2->list.multi[i].start_col) return FALSE; ! if (nfa_has_backref) { if (i < sub1->in_use) s1 = sub1->list.multi[i].end_lnum; --- 4050,4056 ---- != sub2->list.multi[i].start_col) return FALSE; ! if (rex.nfa_has_backref) { if (i < sub1->in_use) s1 = sub1->list.multi[i].end_lnum; *************** *** 4105,4111 **** sp2 = NULL; if (sp1 != sp2) return FALSE; ! if (nfa_has_backref) { if (i < sub1->in_use) sp1 = sub1->list.line[i].end; --- 4082,4088 ---- sp2 = NULL; if (sp1 != sp2) return FALSE; ! if (rex.nfa_has_backref) { if (i < sub1->in_use) sp1 = sub1->list.line[i].end; *************** *** 4139,4145 **** else if (REG_MULTI) col = sub->list.multi[0].start_col; else ! col = (int)(sub->list.line[0].start - regline); nfa_set_code(state->c); fprintf(log_fd, "> %s state %d to list %d. char %d: %s (start col %d)%s\n", action, abs(state->id), lid, state->c, code, col, --- 4116,4122 ---- else if (REG_MULTI) col = sub->list.multi[0].start_col; else ! col = (int)(sub->list.line[0].start - rex.line); nfa_set_code(state->c); fprintf(log_fd, "> %s state %d to list %d. char %d: %s (start col %d)%s\n", action, abs(state->id), lid, state->c, code, col, *************** *** 4167,4173 **** if (thread->state->id == state->id && sub_equal(&thread->subs.norm, &subs->norm) #ifdef FEAT_SYN_HL ! && (!nfa_has_zsubexpr || sub_equal(&thread->subs.synt, &subs->synt)) #endif && pim_equal(&thread->pim, pim)) --- 4144,4150 ---- if (thread->state->id == state->id && sub_equal(&thread->subs.norm, &subs->norm) #ifdef FEAT_SYN_HL ! && (!rex.nfa_has_zsubexpr || sub_equal(&thread->subs.synt, &subs->synt)) #endif && pim_equal(&thread->pim, pim)) *************** *** 4306,4312 **** { if (state->lastlist[nfa_ll_index] == l->id) { ! if (!nfa_has_backref || has_state_with_pos(l, state, subs, NULL)) return TRUE; } return FALSE; --- 4283,4289 ---- { if (state->lastlist[nfa_ll_index] == l->id) { ! if (!rex.nfa_has_backref || has_state_with_pos(l, state, subs, NULL)) return TRUE; } return FALSE; *************** *** 4390,4400 **** /* "^" won't match past end-of-line, don't bother trying. * Except when at the end of the line, or when we are going to the * next line for a look-behind match. */ ! if (reginput > regline ! && *reginput != NUL && (nfa_endp == NULL || !REG_MULTI ! || reglnum == nfa_endp->se_u.pos.lnum)) goto skip_add; /* FALLTHROUGH */ --- 4367,4377 ---- /* "^" won't match past end-of-line, don't bother trying. * Except when at the end of the line, or when we are going to the * next line for a look-behind match. */ ! if (rex.input > rex.line ! && *rex.input != NUL && (nfa_endp == NULL || !REG_MULTI ! || rex.lnum == nfa_endp->se_u.pos.lnum)) goto skip_add; /* FALLTHROUGH */ *************** *** 4432,4438 **** * unless it is an MOPEN that is used for a backreference or * when there is a PIM. For NFA_MATCH check the position, * lower position is preferred. */ ! if (!nfa_has_backref && pim == NULL && !l->has_pim && state->c != NFA_MATCH) { /* When called from addstate_here() do insert before --- 4409,4415 ---- * unless it is an MOPEN that is used for a backreference or * when there is a PIM. For NFA_MATCH check the position, * lower position is preferred. */ ! if (!rex.nfa_has_backref && pim == NULL && !l->has_pim && state->c != NFA_MATCH) { /* When called from addstate_here() do insert before *************** *** 4477,4483 **** * copy before it becomes invalid. */ copy_sub(&temp_subs.norm, &subs->norm); #ifdef FEAT_SYN_HL ! if (nfa_has_zsubexpr) copy_sub(&temp_subs.synt, &subs->synt); #endif subs = &temp_subs; --- 4454,4460 ---- * copy before it becomes invalid. */ copy_sub(&temp_subs.norm, &subs->norm); #ifdef FEAT_SYN_HL ! if (rex.nfa_has_zsubexpr) copy_sub(&temp_subs.synt, &subs->synt); #endif subs = &temp_subs; *************** *** 4501,4507 **** } copy_sub(&thread->subs.norm, &subs->norm); #ifdef FEAT_SYN_HL ! if (nfa_has_zsubexpr) copy_sub(&thread->subs.synt, &subs->synt); #endif #ifdef ENABLE_LOG --- 4478,4484 ---- } copy_sub(&thread->subs.norm, &subs->norm); #ifdef FEAT_SYN_HL ! if (rex.nfa_has_zsubexpr) copy_sub(&thread->subs.synt, &subs->synt); #endif #ifdef ENABLE_LOG *************** *** 4597,4610 **** } if (off == -1) { ! sub->list.multi[subidx].start_lnum = reglnum + 1; sub->list.multi[subidx].start_col = 0; } else { ! sub->list.multi[subidx].start_lnum = reglnum; sub->list.multi[subidx].start_col = ! (colnr_T)(reginput - regline + off); } sub->list.multi[subidx].end_lnum = -1; } --- 4574,4587 ---- } if (off == -1) { ! sub->list.multi[subidx].start_lnum = rex.lnum + 1; sub->list.multi[subidx].start_col = 0; } else { ! sub->list.multi[subidx].start_lnum = rex.lnum; sub->list.multi[subidx].start_col = ! (colnr_T)(rex.input - rex.line + off); } sub->list.multi[subidx].end_lnum = -1; } *************** *** 4625,4631 **** } sub->in_use = subidx + 1; } ! sub->list.line[subidx].start = reginput + off; } subs = addstate(l, state->out, subs, pim, off_arg); --- 4602,4608 ---- } sub->in_use = subidx + 1; } ! sub->list.line[subidx].start = rex.input + off; } subs = addstate(l, state->out, subs, pim, off_arg); *************** *** 4649,4655 **** break; case NFA_MCLOSE: ! if (nfa_has_zend && (REG_MULTI ? subs->norm.list.multi[0].end_lnum >= 0 : subs->norm.list.line[0].end != NULL)) { --- 4626,4632 ---- break; case NFA_MCLOSE: ! if (rex.nfa_has_zend && (REG_MULTI ? subs->norm.list.multi[0].end_lnum >= 0 : subs->norm.list.line[0].end != NULL)) { *************** *** 4708,4721 **** save_multipos = sub->list.multi[subidx]; if (off == -1) { ! sub->list.multi[subidx].end_lnum = reglnum + 1; sub->list.multi[subidx].end_col = 0; } else { ! sub->list.multi[subidx].end_lnum = reglnum; sub->list.multi[subidx].end_col = ! (colnr_T)(reginput - regline + off); } /* avoid compiler warnings */ save_ptr = NULL; --- 4685,4698 ---- save_multipos = sub->list.multi[subidx]; if (off == -1) { ! sub->list.multi[subidx].end_lnum = rex.lnum + 1; sub->list.multi[subidx].end_col = 0; } else { ! sub->list.multi[subidx].end_lnum = rex.lnum; sub->list.multi[subidx].end_col = ! (colnr_T)(rex.input - rex.line + off); } /* avoid compiler warnings */ save_ptr = NULL; *************** *** 4723,4729 **** else { save_ptr = sub->list.line[subidx].end; ! sub->list.line[subidx].end = reginput + off; /* avoid compiler warnings */ vim_memset(&save_multipos, 0, sizeof(save_multipos)); } --- 4700,4706 ---- else { save_ptr = sub->list.line[subidx].end; ! sub->list.line[subidx].end = rex.input + off; /* avoid compiler warnings */ vim_memset(&save_multipos, 0, sizeof(save_multipos)); } *************** *** 4929,4941 **** if (sub->list.multi[subidx].start_lnum < 0 || sub->list.multi[subidx].end_lnum < 0) goto retempty; ! if (sub->list.multi[subidx].start_lnum == reglnum ! && sub->list.multi[subidx].end_lnum == reglnum) { len = sub->list.multi[subidx].end_col - sub->list.multi[subidx].start_col; ! if (cstrncmp(regline + sub->list.multi[subidx].start_col, ! reginput, &len) == 0) { *bytelen = len; return TRUE; --- 4906,4918 ---- if (sub->list.multi[subidx].start_lnum < 0 || sub->list.multi[subidx].end_lnum < 0) goto retempty; ! if (sub->list.multi[subidx].start_lnum == rex.lnum ! && sub->list.multi[subidx].end_lnum == rex.lnum) { len = sub->list.multi[subidx].end_col - sub->list.multi[subidx].start_col; ! if (cstrncmp(rex.line + sub->list.multi[subidx].start_col, ! rex.input, &len) == 0) { *bytelen = len; return TRUE; *************** *** 4958,4964 **** || sub->list.line[subidx].end == NULL) goto retempty; len = (int)(sub->list.line[subidx].end - sub->list.line[subidx].start); ! if (cstrncmp(sub->list.line[subidx].start, reginput, &len) == 0) { *bytelen = len; return TRUE; --- 4935,4941 ---- || sub->list.line[subidx].end == NULL) goto retempty; len = (int)(sub->list.line[subidx].end - sub->list.line[subidx].start); ! if (cstrncmp(sub->list.line[subidx].start, rex.input, &len) == 0) { *bytelen = len; return TRUE; *************** *** 4989,4995 **** } len = (int)STRLEN(re_extmatch_in->matches[subidx]); ! if (cstrncmp(re_extmatch_in->matches[subidx], reginput, &len) == 0) { *bytelen = len; return TRUE; --- 4966,4972 ---- } len = (int)STRLEN(re_extmatch_in->matches[subidx]); ! if (cstrncmp(re_extmatch_in->matches[subidx], rex.input, &len) == 0) { *bytelen = len; return TRUE; *************** *** 5061,5070 **** int **listids, int *listids_len) { ! int save_reginput_col = (int)(reginput - regline); ! int save_reglnum = reglnum; int save_nfa_match = nfa_match; ! int save_nfa_listid = nfa_listid; save_se_T *save_nfa_endp = nfa_endp; save_se_T endpos; save_se_T *endposp = NULL; --- 5038,5047 ---- int **listids, int *listids_len) { ! int save_reginput_col = (int)(rex.input - rex.line); ! int save_reglnum = rex.lnum; int save_nfa_match = nfa_match; ! int save_nfa_listid = rex.nfa_listid; save_se_T *save_nfa_endp = nfa_endp; save_se_T endpos; save_se_T *endposp = NULL; *************** *** 5075,5083 **** { /* start at the position where the postponed match was */ if (REG_MULTI) ! reginput = regline + pim->end.pos.col; else ! reginput = pim->end.ptr; } if (state->c == NFA_START_INVISIBLE_BEFORE --- 5052,5060 ---- { /* start at the position where the postponed match was */ if (REG_MULTI) ! rex.input = rex.line + pim->end.pos.col; else ! rex.input = pim->end.ptr; } if (state->c == NFA_START_INVISIBLE_BEFORE *************** *** 5092,5099 **** { if (pim == NULL) { ! endpos.se_u.pos.col = (int)(reginput - regline); ! endpos.se_u.pos.lnum = reglnum; } else endpos.se_u.pos = pim->end.pos; --- 5069,5076 ---- { if (pim == NULL) { ! endpos.se_u.pos.col = (int)(rex.input - rex.line); ! endpos.se_u.pos.lnum = rex.lnum; } else endpos.se_u.pos = pim->end.pos; *************** *** 5101,5107 **** else { if (pim == NULL) ! endpos.se_u.ptr = reginput; else endpos.se_u.ptr = pim->end.ptr; } --- 5078,5084 ---- else { if (pim == NULL) ! endpos.se_u.ptr = rex.input; else endpos.se_u.ptr = pim->end.ptr; } *************** *** 5114,5152 **** { if (REG_MULTI) { ! regline = reg_getline(--reglnum); ! if (regline == NULL) /* can't go before the first line */ ! regline = reg_getline(++reglnum); } ! reginput = regline; } else { ! if (REG_MULTI && (int)(reginput - regline) < state->val) { /* Not enough bytes in this line, go to end of * previous line. */ ! regline = reg_getline(--reglnum); ! if (regline == NULL) { /* can't go before the first line */ ! regline = reg_getline(++reglnum); ! reginput = regline; } else ! reginput = regline + STRLEN(regline); } ! if ((int)(reginput - regline) >= state->val) { ! reginput -= state->val; #ifdef FEAT_MBYTE if (has_mbyte) ! reginput -= mb_head_off(regline, reginput); #endif } else ! reginput = regline; } } --- 5091,5129 ---- { if (REG_MULTI) { ! rex.line = reg_getline(--rex.lnum); ! if (rex.line == NULL) /* can't go before the first line */ ! rex.line = reg_getline(++rex.lnum); } ! rex.input = rex.line; } else { ! if (REG_MULTI && (int)(rex.input - rex.line) < state->val) { /* Not enough bytes in this line, go to end of * previous line. */ ! rex.line = reg_getline(--rex.lnum); ! if (rex.line == NULL) { /* can't go before the first line */ ! rex.line = reg_getline(++rex.lnum); ! rex.input = rex.line; } else ! rex.input = rex.line + STRLEN(rex.line); } ! if ((int)(rex.input - rex.line) >= state->val) { ! rex.input -= state->val; #ifdef FEAT_MBYTE if (has_mbyte) ! rex.input -= mb_head_off(rex.line, rex.input); #endif } else ! rex.input = rex.line; } } *************** *** 5161,5189 **** { /* Already calling nfa_regmatch() recursively. Save the lastlist[1] * values and clear them. */ ! if (*listids == NULL || *listids_len < nstate) { vim_free(*listids); ! *listids = (int *)lalloc(sizeof(int) * nstate, TRUE); if (*listids == NULL) { EMSG(_("E878: (NFA) Could not allocate memory for branch traversal!")); return 0; } ! *listids_len = nstate; } nfa_save_listids(prog, *listids); need_restore = TRUE; ! /* any value of nfa_listid will do */ } else { /* First recursive nfa_regmatch() call, switch to the second lastlist ! * entry. Make sure nfa_listid is different from a previous recursive ! * call, because some states may still have this ID. */ ++nfa_ll_index; ! if (nfa_listid <= nfa_alt_listid) ! nfa_listid = nfa_alt_listid; } /* Call nfa_regmatch() to check if the current concat matches at this --- 5138,5166 ---- { /* Already calling nfa_regmatch() recursively. Save the lastlist[1] * values and clear them. */ ! if (*listids == NULL || *listids_len < prog->nstate) { vim_free(*listids); ! *listids = (int *)lalloc(sizeof(int) * prog->nstate, TRUE); if (*listids == NULL) { EMSG(_("E878: (NFA) Could not allocate memory for branch traversal!")); return 0; } ! *listids_len = prog->nstate; } nfa_save_listids(prog, *listids); need_restore = TRUE; ! /* any value of rex.nfa_listid will do */ } else { /* First recursive nfa_regmatch() call, switch to the second lastlist ! * entry. Make sure rex.nfa_listid is different from a previous ! * recursive call, because some states may still have this ID. */ ++nfa_ll_index; ! if (rex.nfa_listid <= rex.nfa_alt_listid) ! rex.nfa_listid = rex.nfa_alt_listid; } /* Call nfa_regmatch() to check if the current concat matches at this *************** *** 5196,5213 **** else { --nfa_ll_index; ! nfa_alt_listid = nfa_listid; } /* restore position in input text */ ! reglnum = save_reglnum; if (REG_MULTI) ! regline = reg_getline(reglnum); ! reginput = regline + save_reginput_col; if (result != NFA_TOO_EXPENSIVE) { nfa_match = save_nfa_match; ! nfa_listid = save_nfa_listid; } nfa_endp = save_nfa_endp; --- 5173,5190 ---- else { --nfa_ll_index; ! rex.nfa_alt_listid = rex.nfa_listid; } /* restore position in input text */ ! rex.lnum = save_reglnum; if (REG_MULTI) ! rex.line = reg_getline(rex.lnum); ! rex.input = rex.line + save_reginput_col; if (result != NFA_TOO_EXPENSIVE) { nfa_match = save_nfa_match; ! rex.nfa_listid = save_nfa_listid; } nfa_endp = save_nfa_endp; *************** *** 5407,5418 **** && !has_mbyte #endif ) ! s = vim_strbyte(regline + *colp, c); else ! s = cstrchr(regline + *colp, c); if (s == NULL) return FAIL; ! *colp = (int)(s - regline); return OK; } --- 5384,5395 ---- && !has_mbyte #endif ) ! s = vim_strbyte(rex.line + *colp, c); else ! s = cstrchr(rex.line + *colp, c); if (s == NULL) return FAIL; ! *colp = (int)(s - rex.line); return OK; } *************** *** 5436,5442 **** for (len1 = 0; match_text[len1] != NUL; len1 += MB_CHAR2LEN(c1)) { c1 = PTR2CHAR(match_text + len1); ! c2 = PTR2CHAR(regline + col + len2); if (c1 != c2 && (!rex.reg_ic || MB_TOLOWER(c1) != MB_TOLOWER(c2))) { match = FALSE; --- 5413,5419 ---- for (len1 = 0; match_text[len1] != NUL; len1 += MB_CHAR2LEN(c1)) { c1 = PTR2CHAR(match_text + len1); ! c2 = PTR2CHAR(rex.line + col + len2); if (c1 != c2 && (!rex.reg_ic || MB_TOLOWER(c1) != MB_TOLOWER(c2))) { match = FALSE; *************** *** 5448,5469 **** #ifdef FEAT_MBYTE /* check that no composing char follows */ && !(enc_utf8 ! && utf_iscomposing(PTR2CHAR(regline + col + len2))) #endif ) { 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; } --- 5425,5446 ---- #ifdef FEAT_MBYTE /* check that no composing char follows */ && !(enc_utf8 ! && utf_iscomposing(PTR2CHAR(rex.line + col + len2))) #endif ) { cleanup_subexpr(); if (REG_MULTI) { ! rex.reg_startpos[0].lnum = rex.lnum; rex.reg_startpos[0].col = col; ! rex.reg_endpos[0].lnum = rex.lnum; rex.reg_endpos[0].col = col + len2; } else { ! rex.reg_startp[0] = rex.line + col; ! rex.reg_endp[0] = rex.line + col + len2; } return 1L; } *************** *** 5493,5499 **** /* * Main matching routine. * ! * Run NFA to determine whether it matches reginput. * * When "nfa_endp" is not NULL it is a required end-of-match position. * --- 5470,5476 ---- /* * Main matching routine. * ! * Run NFA to determine whether it matches rex.input. * * When "nfa_endp" is not NULL it is a required end-of-match position. * *************** *** 5549,5560 **** nfa_match = FALSE; /* Allocate memory for the lists of nodes. */ ! size = (nstate + 1) * sizeof(nfa_thread_T); list[0].t = (nfa_thread_T *)lalloc(size, TRUE); ! list[0].len = nstate + 1; list[1].t = (nfa_thread_T *)lalloc(size, TRUE); ! list[1].len = nstate + 1; if (list[0].t == NULL || list[1].t == NULL) goto theend; --- 5526,5537 ---- nfa_match = FALSE; /* Allocate memory for the lists of nodes. */ ! size = (prog->nstate + 1) * sizeof(nfa_thread_T); list[0].t = (nfa_thread_T *)lalloc(size, TRUE); ! list[0].len = prog->nstate + 1; list[1].t = (nfa_thread_T *)lalloc(size, TRUE); ! list[1].len = prog->nstate + 1; if (list[0].t == NULL || list[1].t == NULL) goto theend; *************** *** 5584,5590 **** #ifdef ENABLE_LOG fprintf(log_fd, "(---) STARTSTATE first\n"); #endif ! thislist->id = nfa_listid + 1; /* Inline optimized code for addstate(thislist, start, m, 0) if we know * it's the first MOPEN. */ --- 5561,5567 ---- #ifdef ENABLE_LOG fprintf(log_fd, "(---) STARTSTATE first\n"); #endif ! thislist->id = rex.nfa_listid + 1; /* Inline optimized code for addstate(thislist, start, m, 0) if we know * it's the first MOPEN. */ *************** *** 5592,5602 **** { if (REG_MULTI) { ! m->norm.list.multi[0].start_lnum = reglnum; ! m->norm.list.multi[0].start_col = (colnr_T)(reginput - regline); } else ! m->norm.list.line[0].start = reginput; m->norm.in_use = 1; addstate(thislist, start->out, m, NULL, 0); } --- 5569,5579 ---- { if (REG_MULTI) { ! m->norm.list.multi[0].start_lnum = rex.lnum; ! m->norm.list.multi[0].start_col = (colnr_T)(rex.input - rex.line); } else ! m->norm.list.line[0].start = rex.input; m->norm.in_use = 1; addstate(thislist, start->out, m, NULL, 0); } *************** *** 5620,5632 **** #ifdef FEAT_MBYTE if (has_mbyte) { ! curc = (*mb_ptr2char)(reginput); ! clen = (*mb_ptr2len)(reginput); } else #endif { ! curc = *reginput; clen = 1; } if (curc == NUL) --- 5597,5609 ---- #ifdef FEAT_MBYTE if (has_mbyte) { ! curc = (*mb_ptr2char)(rex.input); ! clen = (*mb_ptr2len)(rex.input); } else #endif { ! curc = *rex.input; clen = 1; } if (curc == NUL) *************** *** 5640,5648 **** nextlist = &list[flag ^= 1]; nextlist->n = 0; /* clear nextlist */ nextlist->has_pim = FALSE; ! ++nfa_listid; if (prog->re_engine == AUTOMATIC_ENGINE ! && (nfa_listid >= NFA_MAX_STATES # ifdef FEAT_EVAL || nfa_fail_for_testing # endif --- 5617,5625 ---- nextlist = &list[flag ^= 1]; nextlist->n = 0; /* clear nextlist */ nextlist->has_pim = FALSE; ! ++rex.nfa_listid; if (prog->re_engine == AUTOMATIC_ENGINE ! && (rex.nfa_listid >= NFA_MAX_STATES # ifdef FEAT_EVAL || nfa_fail_for_testing # endif *************** *** 5653,5664 **** goto theend; } ! thislist->id = nfa_listid; ! nextlist->id = nfa_listid + 1; #ifdef ENABLE_LOG fprintf(log_fd, "------------------------------------------\n"); ! fprintf(log_fd, ">>> Reginput is \"%s\"\n", reginput); fprintf(log_fd, ">>> Advanced one character... Current char is %c (code %d) \n", curc, (int)curc); fprintf(log_fd, ">>> Thislist has %d states available: ", thislist->n); { --- 5630,5641 ---- goto theend; } ! thislist->id = rex.nfa_listid; ! nextlist->id = rex.nfa_listid + 1; #ifdef ENABLE_LOG fprintf(log_fd, "------------------------------------------\n"); ! fprintf(log_fd, ">>> Reginput is \"%s\"\n", rex.input); fprintf(log_fd, ">>> Advanced one character... Current char is %c (code %d) \n", curc, (int)curc); fprintf(log_fd, ">>> Thislist has %d states available: ", thislist->n); { *************** *** 5710,5716 **** else if (REG_MULTI) col = t->subs.norm.list.multi[0].start_col; else ! col = (int)(t->subs.norm.list.line[0].start - regline); nfa_set_code(t->state->c); fprintf(log_fd, "(%d) char %d %s (start col %d)%s... \n", abs(t->state->id), (int)t->state->c, code, col, --- 5687,5693 ---- else if (REG_MULTI) col = t->subs.norm.list.multi[0].start_col; else ! col = (int)(t->subs.norm.list.line[0].start - rex.line); nfa_set_code(t->state->c); fprintf(log_fd, "(%d) char %d %s (start col %d)%s... \n", abs(t->state->id), (int)t->state->c, code, col, *************** *** 5738,5744 **** nfa_match = TRUE; copy_sub(&submatch->norm, &t->subs.norm); #ifdef FEAT_SYN_HL ! if (nfa_has_zsubexpr) copy_sub(&submatch->synt, &t->subs.synt); #endif #ifdef ENABLE_LOG --- 5715,5721 ---- nfa_match = TRUE; copy_sub(&submatch->norm, &t->subs.norm); #ifdef FEAT_SYN_HL ! if (rex.nfa_has_zsubexpr) copy_sub(&submatch->synt, &t->subs.synt); #endif #ifdef ENABLE_LOG *************** *** 5746,5752 **** #endif /* Found the left-most longest match, do not look at any other * states at this position. When the list of states is going ! * to be empty quit without advancing, so that "reginput" is * correct. */ if (nextlist->n == 0) clen = 0; --- 5723,5729 ---- #endif /* Found the left-most longest match, do not look at any other * states at this position. When the list of states is going ! * to be empty quit without advancing, so that "rex.input" is * correct. */ if (nextlist->n == 0) clen = 0; *************** *** 5772,5794 **** { if (REG_MULTI) fprintf(log_fd, "Current lnum: %d, endp lnum: %d; current col: %d, endp col: %d\n", ! (int)reglnum, (int)nfa_endp->se_u.pos.lnum, ! (int)(reginput - regline), nfa_endp->se_u.pos.col); else fprintf(log_fd, "Current col: %d, endp col: %d\n", ! (int)(reginput - regline), ! (int)(nfa_endp->se_u.ptr - reginput)); } #endif /* If "nfa_endp" is set it's only a match if it ends at * "nfa_endp" */ if (nfa_endp != NULL && (REG_MULTI ! ? (reglnum != nfa_endp->se_u.pos.lnum ! || (int)(reginput - regline) != nfa_endp->se_u.pos.col) ! : reginput != nfa_endp->se_u.ptr)) break; /* do not set submatches for \@! */ --- 5749,5771 ---- { if (REG_MULTI) fprintf(log_fd, "Current lnum: %d, endp lnum: %d; current col: %d, endp col: %d\n", ! (int)rex.lnum, (int)nfa_endp->se_u.pos.lnum, ! (int)(rex.input - rex.line), nfa_endp->se_u.pos.col); else fprintf(log_fd, "Current col: %d, endp col: %d\n", ! (int)(rex.input - rex.line), ! (int)(nfa_endp->se_u.ptr - rex.input)); } #endif /* If "nfa_endp" is set it's only a match if it ends at * "nfa_endp" */ if (nfa_endp != NULL && (REG_MULTI ! ? (rex.lnum != nfa_endp->se_u.pos.lnum ! || (int)(rex.input - rex.line) != nfa_endp->se_u.pos.col) ! : rex.input != nfa_endp->se_u.ptr)) break; /* do not set submatches for \@! */ *************** *** 5796,5802 **** { copy_sub(&m->norm, &t->subs.norm); #ifdef FEAT_SYN_HL ! if (nfa_has_zsubexpr) copy_sub(&m->synt, &t->subs.synt); #endif } --- 5773,5779 ---- { copy_sub(&m->norm, &t->subs.norm); #ifdef FEAT_SYN_HL ! if (rex.nfa_has_zsubexpr) copy_sub(&m->synt, &t->subs.synt); #endif } *************** *** 5838,5844 **** * of what happens on success below. */ copy_sub_off(&m->norm, &t->subs.norm); #ifdef FEAT_SYN_HL ! if (nfa_has_zsubexpr) copy_sub_off(&m->synt, &t->subs.synt); #endif --- 5815,5821 ---- * of what happens on success below. */ copy_sub_off(&m->norm, &t->subs.norm); #ifdef FEAT_SYN_HL ! if (rex.nfa_has_zsubexpr) copy_sub_off(&m->synt, &t->subs.synt); #endif *************** *** 5866,5872 **** /* Copy submatch info from the recursive call */ copy_sub_off(&t->subs.norm, &m->norm); #ifdef FEAT_SYN_HL ! if (nfa_has_zsubexpr) copy_sub_off(&t->subs.synt, &m->synt); #endif /* If the pattern has \ze and it matched in the --- 5843,5849 ---- /* Copy submatch info from the recursive call */ copy_sub_off(&t->subs.norm, &m->norm); #ifdef FEAT_SYN_HL ! if (rex.nfa_has_zsubexpr) copy_sub_off(&t->subs.synt, &m->synt); #endif /* If the pattern has \ze and it matched in the *************** *** 5899,5909 **** #endif if (REG_MULTI) { ! pim.end.pos.col = (int)(reginput - regline); ! pim.end.pos.lnum = reglnum; } else ! pim.end.ptr = reginput; /* t->state->out1 is the corresponding END_INVISIBLE * node; Add its out to the current list (zero-width --- 5876,5886 ---- #endif if (REG_MULTI) { ! pim.end.pos.col = (int)(rex.input - rex.line); ! pim.end.pos.lnum = rex.lnum; } else ! pim.end.ptr = rex.input; /* t->state->out1 is the corresponding END_INVISIBLE * node; Add its out to the current list (zero-width *************** *** 5959,5965 **** * happens afterwards. */ copy_sub_off(&m->norm, &t->subs.norm); #ifdef FEAT_SYN_HL ! if (nfa_has_zsubexpr) copy_sub_off(&m->synt, &t->subs.synt); #endif --- 5936,5942 ---- * happens afterwards. */ copy_sub_off(&m->norm, &t->subs.norm); #ifdef FEAT_SYN_HL ! if (rex.nfa_has_zsubexpr) copy_sub_off(&m->synt, &t->subs.synt); #endif *************** *** 5982,5988 **** /* Copy submatch info from the recursive call */ copy_sub_off(&t->subs.norm, &m->norm); #ifdef FEAT_SYN_HL ! if (nfa_has_zsubexpr) copy_sub_off(&t->subs.synt, &m->synt); #endif /* Now we need to skip over the matched text and then --- 5959,5965 ---- /* Copy submatch info from the recursive call */ copy_sub_off(&t->subs.norm, &m->norm); #ifdef FEAT_SYN_HL ! if (rex.nfa_has_zsubexpr) copy_sub_off(&t->subs.synt, &m->synt); #endif /* Now we need to skip over the matched text and then *************** *** 5990,5998 **** if (REG_MULTI) /* TODO: multi-line match */ bytelen = m->norm.list.multi[0].end_col ! - (int)(reginput - regline); else ! bytelen = (int)(m->norm.list.line[0].end - reginput); #ifdef ENABLE_LOG fprintf(log_fd, "NFA_START_PATTERN length: %d\n", bytelen); --- 5967,5975 ---- if (REG_MULTI) /* TODO: multi-line match */ bytelen = m->norm.list.multi[0].end_col ! - (int)(rex.input - rex.line); else ! bytelen = (int)(m->norm.list.line[0].end - rex.input); #ifdef ENABLE_LOG fprintf(log_fd, "NFA_START_PATTERN length: %d\n", bytelen); *************** *** 6025,6031 **** } case NFA_BOL: ! if (reginput == regline) { add_here = TRUE; add_state = t->state->out; --- 6002,6008 ---- } case NFA_BOL: ! if (rex.input == rex.line) { add_here = TRUE; add_state = t->state->out; *************** *** 6051,6057 **** 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) --- 6028,6034 ---- int this_class; /* Get class of current and previous char (if it exists). */ ! this_class = mb_get_class_buf(rex.input, rex.reg_buf); if (this_class <= 1) result = FALSE; else if (reg_prev_class() == this_class) *************** *** 6059,6066 **** } #endif else if (!vim_iswordc_buf(curc, rex.reg_buf) ! || (reginput > regline ! && vim_iswordc_buf(reginput[-1], rex.reg_buf))) result = FALSE; if (result) { --- 6036,6043 ---- } #endif else if (!vim_iswordc_buf(curc, rex.reg_buf) ! || (rex.input > rex.line ! && vim_iswordc_buf(rex.input[-1], rex.reg_buf))) result = FALSE; if (result) { *************** *** 6071,6077 **** case NFA_EOW: result = TRUE; ! if (reginput == regline) result = FALSE; #ifdef FEAT_MBYTE else if (has_mbyte) --- 6048,6054 ---- case NFA_EOW: result = TRUE; ! if (rex.input == rex.line) result = FALSE; #ifdef FEAT_MBYTE else if (has_mbyte) *************** *** 6079,6093 **** 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) --- 6056,6070 ---- int this_class, prev_class; /* Get class of current and previous char (if it exists). */ ! this_class = mb_get_class_buf(rex.input, 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(rex.input[-1], rex.reg_buf) ! || (rex.input[0] != NUL && vim_iswordc_buf(curc, rex.reg_buf))) result = FALSE; if (result) *************** *** 6098,6104 **** break; case NFA_BOF: ! if (reglnum == 0 && reginput == regline && (!REG_MULTI || rex.reg_firstlnum == 1)) { add_here = TRUE; --- 6075,6081 ---- break; case NFA_BOF: ! if (rex.lnum == 0 && rex.input == rex.line && (!REG_MULTI || rex.reg_firstlnum == 1)) { add_here = TRUE; *************** *** 6107,6113 **** break; case NFA_EOF: ! if (reglnum == rex.reg_maxline && curc == NUL) { add_here = TRUE; add_state = t->state->out; --- 6084,6090 ---- break; case NFA_EOF: ! if (rex.lnum == rex.reg_maxline && curc == NUL) { add_here = TRUE; add_state = t->state->out; *************** *** 6159,6165 **** * Get them into cchars[] first. */ while (len < clen) { ! mc = mb_ptr2char(reginput + len); cchars[ccount++] = mc; len += mb_char2len(mc); if (ccount == MAX_MCO) --- 6136,6142 ---- * Get them into cchars[] first. */ while (len < clen) { ! mc = mb_ptr2char(rex.input + len); cchars[ccount++] = mc; len += mb_char2len(mc); if (ccount == MAX_MCO) *************** *** 6194,6200 **** 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 --- 6171,6177 ---- case NFA_NEWL: if (curc == NUL && !rex.reg_line_lbr && REG_MULTI ! && rex.lnum <= rex.reg_maxline) { go_to_nextline = TRUE; /* Pass -1 for the offset, which means taking the position *************** *** 6323,6335 **** 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; --- 6300,6312 ---- break; case NFA_KWORD: /* \k */ ! result = vim_iswordp_buf(rex.input, rex.reg_buf); ADD_STATE_IF_MATCH(t->state); break; case NFA_SKWORD: /* \K */ result = !VIM_ISDIGIT(curc) ! && vim_iswordp_buf(rex.input, rex.reg_buf); ADD_STATE_IF_MATCH(t->state); break; *************** *** 6344,6355 **** break; case NFA_PRINT: /* \p */ ! result = vim_isprintc(PTR2CHAR(reginput)); ADD_STATE_IF_MATCH(t->state); break; case NFA_SPRINT: /* \P */ ! result = !VIM_ISDIGIT(curc) && vim_isprintc(PTR2CHAR(reginput)); ADD_STATE_IF_MATCH(t->state); break; --- 6321,6332 ---- break; case NFA_PRINT: /* \p */ ! result = vim_isprintc(PTR2CHAR(rex.input)); ADD_STATE_IF_MATCH(t->state); break; case NFA_SPRINT: /* \P */ ! result = !VIM_ISDIGIT(curc) && vim_isprintc(PTR2CHAR(rex.input)); ADD_STATE_IF_MATCH(t->state); break; *************** *** 6552,6558 **** 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; --- 6529,6535 ---- case NFA_LNUM_LT: result = (REG_MULTI && nfa_re_num_cmp(t->state->val, t->state->c - NFA_LNUM, ! (long_u)(rex.lnum + rex.reg_firstlnum))); if (result) { add_here = TRUE; *************** *** 6564,6570 **** case NFA_COL_GT: case NFA_COL_LT: result = nfa_re_num_cmp(t->state->val, t->state->c - NFA_COL, ! (long_u)(reginput - regline) + 1); if (result) { add_here = TRUE; --- 6541,6547 ---- case NFA_COL_GT: case NFA_COL_LT: result = nfa_re_num_cmp(t->state->val, t->state->c - NFA_COL, ! (long_u)(rex.input - rex.line) + 1); if (result) { add_here = TRUE; *************** *** 6577,6583 **** case NFA_VCOL_LT: { 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 --- 6554,6560 ---- case NFA_VCOL_LT: { int op = t->state->c - NFA_VCOL; ! colnr_T col = (colnr_T)(rex.input - rex.line); win_T *wp = rex.reg_win == NULL ? curwin : rex.reg_win; /* Bail out quickly when there can't be a match, avoid the *************** *** 6601,6607 **** } if (!result) result = nfa_re_num_cmp(t->state->val, op, ! (long_u)win_linetabsize(wp, regline, col) + 1); if (result) { add_here = TRUE; --- 6578,6584 ---- } if (!result) result = nfa_re_num_cmp(t->state->val, op, ! (long_u)win_linetabsize(wp, rex.line, col) + 1); if (result) { add_here = TRUE; *************** *** 6619,6631 **** /* 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) --- 6596,6608 ---- /* 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 == rex.lnum + rex.reg_firstlnum ! ? (pos->col == (colnr_T)(rex.input - rex.line) ? t->state->c == NFA_MARK ! : (pos->col < (colnr_T)(rex.input - rex.line) ? t->state->c == NFA_MARK_GT : t->state->c == NFA_MARK_LT)) ! : (pos->lnum < rex.lnum + rex.reg_firstlnum ? t->state->c == NFA_MARK_GT : t->state->c == NFA_MARK_LT))); if (result) *************** *** 6638,6646 **** 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) { --- 6615,6623 ---- case NFA_CURSOR: result = (rex.reg_win != NULL ! && (rex.lnum + rex.reg_firstlnum == rex.reg_win->w_cursor.lnum) ! && ((colnr_T)(rex.input - rex.line) == rex.reg_win->w_cursor.col)); if (result) { *************** *** 6701,6707 **** /* 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); break; --- 6678,6684 ---- /* 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(rex.input); #endif ADD_STATE_IF_MATCH(t->state); break; *************** *** 6746,6752 **** /* Copy submatch info from the recursive call */ copy_sub_off(&pim->subs.norm, &m->norm); #ifdef FEAT_SYN_HL ! if (nfa_has_zsubexpr) copy_sub_off(&pim->subs.synt, &m->synt); #endif } --- 6723,6729 ---- /* Copy submatch info from the recursive call */ copy_sub_off(&pim->subs.norm, &m->norm); #ifdef FEAT_SYN_HL ! if (rex.nfa_has_zsubexpr) copy_sub_off(&pim->subs.synt, &m->synt); #endif } *************** *** 6773,6779 **** /* Copy submatch info from the recursive call */ copy_sub_off(&t->subs.norm, &pim->subs.norm); #ifdef FEAT_SYN_HL ! if (nfa_has_zsubexpr) copy_sub_off(&t->subs.synt, &pim->subs.synt); #endif } --- 6750,6756 ---- /* Copy submatch info from the recursive call */ copy_sub_off(&t->subs.norm, &pim->subs.norm); #ifdef FEAT_SYN_HL ! if (rex.nfa_has_zsubexpr) copy_sub_off(&t->subs.synt, &pim->subs.synt); #endif } *************** *** 6817,6833 **** * Also don't start a match past the first line. */ if (nfa_match == FALSE && ((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 ! || (reglnum == nfa_endp->se_u.pos.lnum ! && (int)(reginput - regline) < nfa_endp->se_u.pos.col)) ! : reginput < nfa_endp->se_u.ptr)))) { #ifdef ENABLE_LOG fprintf(log_fd, "(---) STARTSTATE\n"); --- 6794,6810 ---- * Also don't start a match past the first line. */ if (nfa_match == FALSE && ((toplevel ! && rex.lnum == 0 && clen != 0 && (rex.reg_maxcol == 0 ! || (colnr_T)(rex.input - rex.line) < rex.reg_maxcol)) || (nfa_endp != NULL && (REG_MULTI ! ? (rex.lnum < nfa_endp->se_u.pos.lnum ! || (rex.lnum == nfa_endp->se_u.pos.lnum ! && (int)(rex.input - rex.line) < nfa_endp->se_u.pos.col)) ! : rex.input < nfa_endp->se_u.ptr)))) { #ifdef ENABLE_LOG fprintf(log_fd, "(---) STARTSTATE\n"); *************** *** 6843,6849 **** { if (nextlist->n == 0) { ! colnr_T col = (colnr_T)(reginput - regline) + clen; /* Nextlist is empty, we can skip ahead to the * character that must appear at the start. */ --- 6820,6826 ---- { if (nextlist->n == 0) { ! colnr_T col = (colnr_T)(rex.input - rex.line) + clen; /* Nextlist is empty, we can skip ahead to the * character that must appear at the start. */ *************** *** 6851,6865 **** break; #ifdef ENABLE_LOG fprintf(log_fd, " Skipping ahead %d bytes to regstart\n", ! col - ((colnr_T)(reginput - regline) + clen)); #endif ! reginput = regline + col - clen; } else { /* 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))) { --- 6828,6842 ---- break; #ifdef ENABLE_LOG fprintf(log_fd, " Skipping ahead %d bytes to regstart\n", ! col - ((colnr_T)(rex.input - rex.line) + clen)); #endif ! rex.input = rex.line + col - clen; } else { /* Checking if the required start character matches is * cheaper than adding a state that won't match. */ ! c = PTR2CHAR(rex.input + clen); if (c != prog->regstart && (!rex.reg_ic || MB_TOLOWER(c) != MB_TOLOWER(prog->regstart))) { *************** *** 6875,6883 **** { if (REG_MULTI) m->norm.list.multi[0].start_col = ! (colnr_T)(reginput - regline) + clen; else ! m->norm.list.line[0].start = reginput + clen; addstate(nextlist, start->out, m, NULL, clen); } } --- 6852,6860 ---- { if (REG_MULTI) m->norm.list.multi[0].start_col = ! (colnr_T)(rex.input - rex.line) + clen; else ! m->norm.list.line[0].start = rex.input + clen; addstate(nextlist, start->out, m, NULL, clen); } } *************** *** 6900,6908 **** /* Advance to the next character, or advance to the next line, or * finish. */ if (clen != 0) ! reginput += clen; else if (go_to_nextline || (nfa_endp != NULL && REG_MULTI ! && reglnum < nfa_endp->se_u.pos.lnum)) reg_nextline(); else break; --- 6877,6885 ---- /* Advance to the next character, or advance to the next line, or * finish. */ if (clen != 0) ! rex.input += clen; else if (go_to_nextline || (nfa_endp != NULL && REG_MULTI ! && rex.lnum < nfa_endp->se_u.pos.lnum)) reg_nextline(); else break; *************** *** 6942,6948 **** } /* ! * Try match of "prog" with at regline["col"]. * Returns <= 0 for failure, number of lines contained in the match otherwise. */ static long --- 6919,6925 ---- } /* ! * Try match of "prog" with at rex.line["col"]. * Returns <= 0 for failure, number of lines contained in the match otherwise. */ static long *************** *** 6960,6966 **** FILE *f; #endif ! reginput = regline + col; #ifdef FEAT_RELTIME nfa_time_limit = tm; nfa_timed_out = timed_out; --- 6937,6943 ---- FILE *f; #endif ! rex.input = rex.line + col; #ifdef FEAT_RELTIME nfa_time_limit = tm; nfa_timed_out = timed_out; *************** *** 6975,6981 **** #ifdef DEBUG fprintf(f, "\tRegexp is \"%s\"\n", nfa_regengine.expr); #endif ! fprintf(f, "\tInput text is \"%s\" \n", reginput); fprintf(f, "\t=======================================================\n\n"); nfa_print_state(f, start); fprintf(f, "\n\n"); --- 6952,6958 ---- #ifdef DEBUG fprintf(f, "\tRegexp is \"%s\"\n", nfa_regengine.expr); #endif ! fprintf(f, "\tInput text is \"%s\" \n", rex.input); fprintf(f, "\t=======================================================\n\n"); nfa_print_state(f, start); fprintf(f, "\n\n"); *************** *** 7018,7029 **** 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 { --- 6995,7006 ---- if (rex.reg_endpos[0].lnum < 0) { /* pattern has a \ze but it didn't match, use current end */ ! rex.reg_endpos[0].lnum = rex.lnum; ! rex.reg_endpos[0].col = (int)(rex.input - rex.line); } else /* Use line number of "\ze". */ ! rex.lnum = rex.reg_endpos[0].lnum; } else { *************** *** 7034,7042 **** } 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 --- 7011,7019 ---- } if (rex.reg_startp[0] == NULL) ! rex.reg_startp[0] = rex.line + col; if (rex.reg_endp[0] == NULL) ! rex.reg_endp[0] = rex.input; } #ifdef FEAT_SYN_HL *************** *** 7077,7083 **** } #endif ! return 1 + reglnum; } /* --- 7054,7060 ---- } #endif ! return 1 + rex.lnum; } /* *************** *** 7131,7159 **** rex.reg_icombine = TRUE; #endif ! regline = line; ! reglnum = 0; /* relative to line */ ! nfa_has_zend = prog->has_zend; ! nfa_has_backref = prog->has_backref; ! nfa_nsubexpr = prog->nsubexp; ! nfa_listid = 1; ! nfa_alt_listid = 2; nfa_regengine.expr = prog->pattern; if (prog->reganch && col > 0) return 0L; ! need_clear_subexpr = TRUE; #ifdef FEAT_SYN_HL /* Clear the external match subpointers if necessary. */ if (prog->reghasz == REX_SET) { ! nfa_has_zsubexpr = TRUE; ! need_clear_zsubexpr = TRUE; } else ! nfa_has_zsubexpr = FALSE; #endif if (prog->regstart != NUL) --- 7108,7141 ---- rex.reg_icombine = TRUE; #endif ! rex.line = line; ! rex.lnum = 0; /* relative to line */ ! rex.nfa_has_zend = prog->has_zend; ! rex.nfa_has_backref = prog->has_backref; ! rex.nfa_nsubexpr = prog->nsubexp; ! rex.nfa_listid = 1; ! rex.nfa_alt_listid = 2; ! #ifdef DEBUG nfa_regengine.expr = prog->pattern; + #endif if (prog->reganch && col > 0) return 0L; ! rex.need_clear_subexpr = TRUE; #ifdef FEAT_SYN_HL /* Clear the external match subpointers if necessary. */ if (prog->reghasz == REX_SET) { ! rex.nfa_has_zsubexpr = TRUE; ! rex.need_clear_zsubexpr = TRUE; } else ! { ! rex.nfa_has_zsubexpr = FALSE; ! rex.need_clear_zsubexpr = FALSE; ! } #endif if (prog->regstart != NUL) *************** *** 7177,7184 **** if (rex.reg_maxcol > 0 && col >= rex.reg_maxcol) goto theend; ! nstate = prog->nstate; ! for (i = 0; i < nstate; ++i) { prog->state[i].id = i; prog->state[i].lastlist[0] = 0; --- 7159,7168 ---- if (rex.reg_maxcol > 0 && col >= rex.reg_maxcol) goto theend; ! // Set the "nstate" used by nfa_regcomp() to zero to trigger an error when ! // it's accidentally used during execution. ! nstate = 0; ! for (i = 0; i < prog->nstate; ++i) { prog->state[i].id = i; prog->state[i].lastlist[0] = 0; *************** *** 7187,7193 **** --- 7171,7179 ---- retval = nfa_regtry(prog, col, tm, timed_out); + #ifdef DEBUG nfa_regengine.expr = NULL; + #endif theend: return retval; *************** *** 7207,7213 **** --- 7193,7201 ---- if (expr == NULL) return NULL; + #ifdef DEBUG nfa_regengine.expr = expr; + #endif nfa_re_flags = re_flags; init_class_tab(); *************** *** 7255,7260 **** --- 7243,7249 ---- if (prog == NULL) goto fail; state_ptr = prog->state; + prog->re_in_use = FALSE; /* * PASS 2 *************** *** 7267,7274 **** prog->regflags = regflags; prog->engine = &nfa_regengine; prog->nstate = nstate; ! prog->has_zend = nfa_has_zend; ! prog->has_backref = nfa_has_backref; prog->nsubexp = regnpar; nfa_postprocess(prog); --- 7256,7263 ---- prog->regflags = regflags; prog->engine = &nfa_regengine; prog->nstate = nstate; ! prog->has_zend = rex.nfa_has_zend; ! prog->has_backref = rex.nfa_has_backref; prog->nsubexp = regnpar; nfa_postprocess(prog); *************** *** 7286,7292 **** --- 7275,7283 ---- prog->reghasz = re_has_z; #endif prog->pattern = vim_strsave(expr); + #ifdef DEBUG nfa_regengine.expr = NULL; + #endif out: VIM_CLEAR(post_start); *************** *** 7299,7305 **** --- 7290,7298 ---- #ifdef ENABLE_LOG nfa_postfix_dump(expr, FAIL); #endif + #ifdef DEBUG nfa_regengine.expr = NULL; + #endif goto out; } *** ../vim-8.1.0191/src/version.c 2018-07-16 18:08:56.326109917 +0200 --- src/version.c 2018-07-17 05:10:12.956018803 +0200 *************** *** 791,792 **** --- 791,794 ---- { /* Add new patch number below this line */ + /**/ + 192, /**/ -- hundred-and-one symptoms of being an internet addict: 262. Your computer has it's own phone line - but your daughter doesn't. /// 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 ///