summaryrefslogtreecommitdiff
path: root/src/regexp_nfa.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2017-06-17 18:44:21 +0200
committerBram Moolenaar <Bram@vim.org>2017-06-17 18:44:21 +0200
commitfbd0b0af6800f6ff89857863d6a07ea03f09ff6c (patch)
treed970232ff584511e30efcfe2f7ea5eefb9e9f8d4 /src/regexp_nfa.c
parent8cf91286ca46a501d24e4b7d631b193256782c88 (diff)
downloadvim-git-fbd0b0af6800f6ff89857863d6a07ea03f09ff6c.tar.gz
patch 8.0.0643: when a pattern search is slow Vim becomes unusablev8.0.0643
Problem: When 'hlsearch' is set and matching with the last search pattern is very slow, Vim becomes unusable. Cannot quit search by pressing CTRL-C. Solution: When the search times out set a flag and don't try again. Check for timeout and CTRL-C in NFA loop that adds states.
Diffstat (limited to 'src/regexp_nfa.c')
-rw-r--r--src/regexp_nfa.c54
1 files changed, 43 insertions, 11 deletions
diff --git a/src/regexp_nfa.c b/src/regexp_nfa.c
index 4e111f169..5ba80f2fe 100644
--- a/src/regexp_nfa.c
+++ b/src/regexp_nfa.c
@@ -311,12 +311,12 @@ static int check_char_class(int class, int c);
static void nfa_save_listids(nfa_regprog_T *prog, int *list);
static void nfa_restore_listids(nfa_regprog_T *prog, int *list);
static int nfa_re_num_cmp(long_u val, int op, long_u pos);
-static long nfa_regtry(nfa_regprog_T *prog, colnr_T col, proftime_T *tm);
-static long nfa_regexec_both(char_u *line, colnr_T col, proftime_T *tm);
+static long nfa_regtry(nfa_regprog_T *prog, colnr_T col, proftime_T *tm, int *timed_out);
+static long nfa_regexec_both(char_u *line, colnr_T col, proftime_T *tm, int *timed_out);
static regprog_T *nfa_regcomp(char_u *expr, int re_flags);
static void nfa_regfree(regprog_T *prog);
static int nfa_regexec_nl(regmatch_T *rmp, char_u *line, colnr_T col, int line_lbr);
-static long nfa_regexec_multi(regmmatch_T *rmp, win_T *win, buf_T *buf, linenr_T lnum, colnr_T col, proftime_T *tm);
+static long nfa_regexec_multi(regmmatch_T *rmp, win_T *win, buf_T *buf, linenr_T lnum, colnr_T col, proftime_T *tm, int *timed_out);
static int match_follows(nfa_state_T *startstate, int depth);
static int failure_chance(nfa_state_T *state, int depth);
@@ -3959,6 +3959,7 @@ pim_info(nfa_pim_T *pim)
static int nfa_match;
#ifdef FEAT_RELTIME
static proftime_T *nfa_time_limit;
+static int *nfa_timed_out;
static int nfa_time_count;
#endif
@@ -5508,6 +5509,20 @@ find_match_text(colnr_T startcol, int regstart, char_u *match_text)
return 0L;
}
+#ifdef FEAT_RELTIME
+ static int
+nfa_did_time_out()
+{
+ if (nfa_time_limit != NULL && profile_passed_limit(nfa_time_limit))
+ {
+ if (nfa_timed_out != NULL)
+ *nfa_timed_out = TRUE;
+ return TRUE;
+ }
+ return FALSE;
+}
+#endif
+
/*
* Main matching routine.
*
@@ -5551,7 +5566,7 @@ nfa_regmatch(
if (got_int)
return FALSE;
#ifdef FEAT_RELTIME
- if (nfa_time_limit != NULL && profile_passed_limit(nfa_time_limit))
+ if (nfa_did_time_out())
return FALSE;
#endif
@@ -5694,6 +5709,19 @@ nfa_regmatch(
/* compute nextlist */
for (listidx = 0; listidx < thislist->n; ++listidx)
{
+ /* If the list gets very long there probably is something wrong.
+ * At least allow interrupting with CTRL-C. */
+ fast_breakcheck();
+ if (got_int)
+ break;
+#ifdef FEAT_RELTIME
+ if (nfa_time_limit != NULL && ++nfa_time_count == 20)
+ {
+ nfa_time_count = 0;
+ if (nfa_did_time_out())
+ break;
+ }
+#endif
t = &thislist->t[listidx];
#ifdef NFA_REGEXP_DEBUG_LOG
@@ -6915,7 +6943,7 @@ nextchar:
if (nfa_time_limit != NULL && ++nfa_time_count == 20)
{
nfa_time_count = 0;
- if (profile_passed_limit(nfa_time_limit))
+ if (nfa_did_time_out())
break;
}
#endif
@@ -6948,7 +6976,8 @@ theend:
nfa_regtry(
nfa_regprog_T *prog,
colnr_T col,
- proftime_T *tm UNUSED) /* timeout limit or NULL */
+ proftime_T *tm UNUSED, /* timeout limit or NULL */
+ int *timed_out UNUSED) /* flag set on timeout or NULL */
{
int i;
regsubs_T subs, m;
@@ -6961,6 +6990,7 @@ nfa_regtry(
reginput = regline + col;
#ifdef FEAT_RELTIME
nfa_time_limit = tm;
+ nfa_timed_out = timed_out;
nfa_time_count = 0;
#endif
@@ -7087,7 +7117,8 @@ nfa_regtry(
nfa_regexec_both(
char_u *line,
colnr_T startcol, /* column to start looking for match */
- proftime_T *tm) /* timeout limit or NULL */
+ proftime_T *tm, /* timeout limit or NULL */
+ int *timed_out) /* flag set on timeout or NULL */
{
nfa_regprog_T *prog;
long retval = 0L;
@@ -7181,7 +7212,7 @@ nfa_regexec_both(
prog->state[i].lastlist[1] = 0;
}
- retval = nfa_regtry(prog, col, tm);
+ retval = nfa_regtry(prog, col, tm, timed_out);
nfa_regengine.expr = NULL;
@@ -7340,7 +7371,7 @@ nfa_regexec_nl(
rex.reg_icombine = FALSE;
#endif
rex.reg_maxcol = 0;
- return nfa_regexec_both(line, col, NULL);
+ return nfa_regexec_both(line, col, NULL, NULL);
}
@@ -7376,7 +7407,8 @@ nfa_regexec_multi(
buf_T *buf, /* buffer in which to search */
linenr_T lnum, /* nr of line to start looking for match */
colnr_T col, /* column to start looking for match */
- proftime_T *tm) /* timeout limit or NULL */
+ proftime_T *tm, /* timeout limit or NULL */
+ int *timed_out) /* flag set on timeout or NULL */
{
rex.reg_match = NULL;
rex.reg_mmatch = rmp;
@@ -7391,7 +7423,7 @@ nfa_regexec_multi(
#endif
rex.reg_maxcol = rmp->rmm_maxcol;
- return nfa_regexec_both(NULL, col, tm);
+ return nfa_regexec_both(NULL, col, tm, timed_out);
}
#ifdef DEBUG