0
0
mirror of https://github.com/vim/vim.git synced 2025-07-26 11:04:33 -04:00

patch 8.0.0643: when a pattern search is slow Vim becomes unusable

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.
This commit is contained in:
Bram Moolenaar 2017-06-17 18:44:21 +02:00
parent 8cf91286ca
commit fbd0b0af68
19 changed files with 124 additions and 68 deletions

View File

@ -4512,7 +4512,7 @@ ins_compl_get_exp(pos_T *ini)
found_new_match = searchit(NULL, ins_buf, pos, found_new_match = searchit(NULL, ins_buf, pos,
compl_direction, compl_direction,
compl_pattern, 1L, SEARCH_KEEP + SEARCH_NFMSG, compl_pattern, 1L, SEARCH_KEEP + SEARCH_NFMSG,
RE_LAST, (linenr_T)0, NULL); RE_LAST, (linenr_T)0, NULL, NULL);
--msg_silent; --msg_silent;
if (!compl_started || set_match_pos) if (!compl_started || set_match_pos)
{ {

View File

@ -9281,7 +9281,7 @@ search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp)
pos = save_cursor = curwin->w_cursor; pos = save_cursor = curwin->w_cursor;
subpatnum = searchit(curwin, curbuf, &pos, dir, pat, 1L, subpatnum = searchit(curwin, curbuf, &pos, dir, pat, 1L,
options, RE_SEARCH, (linenr_T)lnum_stop, &tm); options, RE_SEARCH, (linenr_T)lnum_stop, &tm, NULL);
if (subpatnum != FAIL) if (subpatnum != FAIL)
{ {
if (flags & SP_SUBPAT) if (flags & SP_SUBPAT)
@ -9619,7 +9619,7 @@ do_searchpair(
for (;;) for (;;)
{ {
n = searchit(curwin, curbuf, &pos, dir, pat, 1L, n = searchit(curwin, curbuf, &pos, dir, pat, 1L,
options, RE_SEARCH, lnum_stop, &tm); options, RE_SEARCH, lnum_stop, &tm, NULL);
if (n == FAIL || (firstpos.lnum != 0 && EQUAL_POS(pos, firstpos))) if (n == FAIL || (firstpos.lnum != 0 && EQUAL_POS(pos, firstpos)))
/* didn't find it or found the first match again: FAIL */ /* didn't find it or found the first match again: FAIL */
break; break;

View File

@ -5096,7 +5096,7 @@ do_sub(exarg_T *eap)
); ++lnum) ); ++lnum)
{ {
nmatch = vim_regexec_multi(&regmatch, curwin, curbuf, lnum, nmatch = vim_regexec_multi(&regmatch, curwin, curbuf, lnum,
(colnr_T)0, NULL); (colnr_T)0, NULL, NULL);
if (nmatch) if (nmatch)
{ {
colnr_T copycol; colnr_T copycol;
@ -5695,7 +5695,7 @@ skip:
|| nmatch_tl > 0 || nmatch_tl > 0
|| (nmatch = vim_regexec_multi(&regmatch, curwin, || (nmatch = vim_regexec_multi(&regmatch, curwin,
curbuf, sub_firstlnum, curbuf, sub_firstlnum,
matchcol, NULL)) == 0 matchcol, NULL, NULL)) == 0
|| regmatch.startpos[0].lnum > 0) || regmatch.startpos[0].lnum > 0)
{ {
if (new_start != NULL) if (new_start != NULL)
@ -5760,7 +5760,7 @@ skip:
} }
if (nmatch == -1 && !lastone) if (nmatch == -1 && !lastone)
nmatch = vim_regexec_multi(&regmatch, curwin, curbuf, nmatch = vim_regexec_multi(&regmatch, curwin, curbuf,
sub_firstlnum, matchcol, NULL); sub_firstlnum, matchcol, NULL, NULL);
/* /*
* 5. break if there isn't another match in this line * 5. break if there isn't another match in this line
@ -6012,7 +6012,7 @@ ex_global(exarg_T *eap)
{ {
lnum = curwin->w_cursor.lnum; lnum = curwin->w_cursor.lnum;
match = vim_regexec_multi(&regmatch, curwin, curbuf, lnum, match = vim_regexec_multi(&regmatch, curwin, curbuf, lnum,
(colnr_T)0, NULL); (colnr_T)0, NULL, NULL);
if ((type == 'g' && match) || (type == 'v' && !match)) if ((type == 'g' && match) || (type == 'v' && !match))
global_exe_one(cmd, lnum); global_exe_one(cmd, lnum);
} }
@ -6025,7 +6025,7 @@ ex_global(exarg_T *eap)
{ {
/* a match on this line? */ /* a match on this line? */
match = vim_regexec_multi(&regmatch, curwin, curbuf, lnum, match = vim_regexec_multi(&regmatch, curwin, curbuf, lnum,
(colnr_T)0, NULL); (colnr_T)0, NULL, NULL);
if ((type == 'g' && match) || (type == 'v' && !match)) if ((type == 'g' && match) || (type == 'v' && !match))
{ {
ml_setmarked(lnum); ml_setmarked(lnum);

View File

@ -4556,7 +4556,7 @@ get_address(
curwin->w_cursor.col = 0; curwin->w_cursor.col = 0;
searchcmdlen = 0; searchcmdlen = 0;
if (!do_search(NULL, c, cmd, 1L, if (!do_search(NULL, c, cmd, 1L,
SEARCH_HIS | SEARCH_MSG, NULL)) SEARCH_HIS | SEARCH_MSG, NULL, NULL))
{ {
curwin->w_cursor = pos; curwin->w_cursor = pos;
cmd = NULL; cmd = NULL;
@ -4613,7 +4613,7 @@ get_address(
if (searchit(curwin, curbuf, &pos, if (searchit(curwin, curbuf, &pos,
*cmd == '?' ? BACKWARD : FORWARD, *cmd == '?' ? BACKWARD : FORWARD,
(char_u *)"", 1L, SEARCH_MSG, (char_u *)"", 1L, SEARCH_MSG,
i, (linenr_T)0, NULL) != FAIL) i, (linenr_T)0, NULL, NULL) != FAIL)
lnum = pos.lnum; lnum = pos.lnum;
else else
{ {

View File

@ -1693,7 +1693,7 @@ getcmdline(
i = searchit(curwin, curbuf, &t, i = searchit(curwin, curbuf, &t,
c == Ctrl_G ? FORWARD : BACKWARD, c == Ctrl_G ? FORWARD : BACKWARD,
ccline.cmdbuff, count, search_flags, ccline.cmdbuff, count, search_flags,
RE_SEARCH, 0, NULL); RE_SEARCH, 0, NULL, NULL);
--emsg_off; --emsg_off;
if (i) if (i)
{ {
@ -1903,9 +1903,9 @@ cmdline_changed:
i = do_search(NULL, firstc, ccline.cmdbuff, count, i = do_search(NULL, firstc, ccline.cmdbuff, count,
SEARCH_KEEP + SEARCH_OPT + SEARCH_NOOF + SEARCH_PEEK, SEARCH_KEEP + SEARCH_OPT + SEARCH_NOOF + SEARCH_PEEK,
#ifdef FEAT_RELTIME #ifdef FEAT_RELTIME
&tm &tm, NULL
#else #else
NULL NULL, NULL
#endif #endif
); );
--emsg_off; --emsg_off;

View File

@ -5361,7 +5361,7 @@ gui_do_findrepl(
searchflags += SEARCH_START; searchflags += SEARCH_START;
i = msg_scroll; i = msg_scroll;
(void)do_search(NULL, down ? '/' : '?', ga.ga_data, 1L, (void)do_search(NULL, down ? '/' : '?', ga.ga_data, 1L,
searchflags, NULL); searchflags, NULL, NULL);
msg_scroll = i; /* don't let an error message set msg_scroll */ msg_scroll = i; /* don't let an error message set msg_scroll */
} }

View File

@ -4358,7 +4358,7 @@ find_decl(
{ {
valid = FALSE; valid = FALSE;
t = searchit(curwin, curbuf, &curwin->w_cursor, FORWARD, t = searchit(curwin, curbuf, &curwin->w_cursor, FORWARD,
pat, 1L, searchflags, RE_LAST, (linenr_T)0, NULL); pat, 1L, searchflags, RE_LAST, (linenr_T)0, NULL, NULL);
if (curwin->w_cursor.lnum >= old_pos.lnum) if (curwin->w_cursor.lnum >= old_pos.lnum)
t = FAIL; /* match after start is failure too */ t = FAIL; /* match after start is failure too */
@ -6380,7 +6380,7 @@ normal_search(
curwin->w_set_curswant = TRUE; curwin->w_set_curswant = TRUE;
i = do_search(cap->oap, dir, pat, cap->count1, i = do_search(cap->oap, dir, pat, cap->count1,
opt | SEARCH_OPT | SEARCH_ECHO | SEARCH_MSG, NULL); opt | SEARCH_OPT | SEARCH_ECHO | SEARCH_MSG, NULL, NULL);
if (i == 0) if (i == 0)
clearop(cap->oap); clearop(cap->oap);
else else

View File

@ -16,5 +16,5 @@ void vim_regfree(regprog_T *prog);
int vim_regexec_prog(regprog_T **prog, int ignore_case, char_u *line, colnr_T col); int vim_regexec_prog(regprog_T **prog, int ignore_case, char_u *line, colnr_T col);
int vim_regexec(regmatch_T *rmp, char_u *line, colnr_T col); int vim_regexec(regmatch_T *rmp, char_u *line, colnr_T col);
int vim_regexec_nl(regmatch_T *rmp, char_u *line, colnr_T col); int vim_regexec_nl(regmatch_T *rmp, char_u *line, colnr_T col);
long vim_regexec_multi(regmmatch_T *rmp, win_T *win, buf_T *buf, linenr_T lnum, colnr_T col, proftime_T *tm); long vim_regexec_multi(regmmatch_T *rmp, win_T *win, buf_T *buf, linenr_T lnum, colnr_T col, proftime_T *tm, int *timed_out);
/* vim: set ft=c : */ /* vim: set ft=c : */

View File

@ -19,9 +19,9 @@ char_u *last_search_pat(void);
void reset_search_dir(void); void reset_search_dir(void);
void set_last_search_pat(char_u *s, int idx, int magic, int setlast); void set_last_search_pat(char_u *s, int idx, int magic, int setlast);
void last_pat_prog(regmmatch_T *regmatch); void last_pat_prog(regmmatch_T *regmatch);
int searchit(win_T *win, buf_T *buf, pos_T *pos, int dir, char_u *pat, long count, int options, int pat_use, linenr_T stop_lnum, proftime_T *tm); int searchit(win_T *win, buf_T *buf, pos_T *pos, int dir, char_u *pat, long count, int options, int pat_use, linenr_T stop_lnum, proftime_T *tm, int *timed_out);
void set_search_direction(int cdir); void set_search_direction(int cdir);
int do_search(oparg_T *oap, int dirc, char_u *pat, long count, int options, proftime_T *tm); int do_search(oparg_T *oap, int dirc, char_u *pat, long count, int options, proftime_T *tm, int *timed_out);
int search_for_exact_line(buf_T *buf, pos_T *pos, int dir, char_u *pat); int search_for_exact_line(buf_T *buf, pos_T *pos, int dir, char_u *pat);
int searchc(cmdarg_T *cap, int t_cmd); int searchc(cmdarg_T *cap, int t_cmd);
pos_T *findmatch(oparg_T *oap, int initc); pos_T *findmatch(oparg_T *oap, int initc);

View File

@ -2415,7 +2415,7 @@ win_found:
save_cursor = curwin->w_cursor; save_cursor = curwin->w_cursor;
curwin->w_cursor.lnum = 0; curwin->w_cursor.lnum = 0;
if (!do_search(NULL, '/', qf_ptr->qf_pattern, (long)1, if (!do_search(NULL, '/', qf_ptr->qf_pattern, (long)1,
SEARCH_KEEP, NULL)) SEARCH_KEEP, NULL, NULL))
curwin->w_cursor = save_cursor; curwin->w_cursor = save_cursor;
} }
@ -4237,7 +4237,7 @@ ex_vimgrep(exarg_T *eap)
{ {
col = 0; col = 0;
while (vim_regexec_multi(&regmatch, curwin, buf, lnum, while (vim_regexec_multi(&regmatch, curwin, buf, lnum,
col, NULL) > 0) col, NULL, NULL) > 0)
{ {
/* Pass the buffer number so that it gets used even for a /* Pass the buffer number so that it gets used even for a
* dummy buffer, unless duplicate_name is set, then the * dummy buffer, unless duplicate_name is set, then the

View File

@ -3479,7 +3479,7 @@ typedef struct regbehind_S
} regbehind_T; } regbehind_T;
static char_u *reg_getline(linenr_T lnum); static char_u *reg_getline(linenr_T lnum);
static long bt_regexec_both(char_u *line, colnr_T col, proftime_T *tm); static long bt_regexec_both(char_u *line, colnr_T col, proftime_T *tm, int *timed_out);
static long regtry(bt_regprog_T *prog, colnr_T col); static long regtry(bt_regprog_T *prog, colnr_T col);
static void cleanup_subexpr(void); static void cleanup_subexpr(void);
#ifdef FEAT_SYN_HL #ifdef FEAT_SYN_HL
@ -3722,7 +3722,7 @@ bt_regexec_nl(
#endif #endif
rex.reg_maxcol = 0; rex.reg_maxcol = 0;
return bt_regexec_both(line, col, NULL); return bt_regexec_both(line, col, NULL, NULL);
} }
/* /*
@ -3740,7 +3740,8 @@ bt_regexec_multi(
buf_T *buf, /* buffer in which to search */ buf_T *buf, /* buffer in which to search */
linenr_T lnum, /* nr of line to start looking for match */ linenr_T lnum, /* nr of line to start looking for match */
colnr_T col, /* column 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_match = NULL;
rex.reg_mmatch = rmp; rex.reg_mmatch = rmp;
@ -3755,7 +3756,7 @@ bt_regexec_multi(
#endif #endif
rex.reg_maxcol = rmp->rmm_maxcol; rex.reg_maxcol = rmp->rmm_maxcol;
return bt_regexec_both(NULL, col, tm); return bt_regexec_both(NULL, col, tm, timed_out);
} }
/* /*
@ -3767,7 +3768,8 @@ bt_regexec_multi(
bt_regexec_both( bt_regexec_both(
char_u *line, char_u *line,
colnr_T col, /* column to start looking for match */ colnr_T col, /* column to start looking for match */
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 */
{ {
bt_regprog_T *prog; bt_regprog_T *prog;
char_u *s; char_u *s;
@ -3968,8 +3970,12 @@ bt_regexec_both(
{ {
tm_count = 0; tm_count = 0;
if (profile_passed_limit(tm)) if (profile_passed_limit(tm))
{
if (timed_out != NULL)
*timed_out = TRUE;
break; break;
} }
}
#endif #endif
} }
} }
@ -8308,7 +8314,8 @@ vim_regexec_multi(
buf_T *buf, /* buffer in which to search */ buf_T *buf, /* buffer in which to search */
linenr_T lnum, /* nr of line to start looking for match */ linenr_T lnum, /* nr of line to start looking for match */
colnr_T col, /* column 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 is set when timeout limit reached */
{ {
int result; int result;
regexec_T rex_save; regexec_T rex_save;
@ -8319,7 +8326,8 @@ vim_regexec_multi(
rex_save = rex; rex_save = rex;
rex_in_use = TRUE; rex_in_use = TRUE;
result = rmp->regprog->engine->regexec_multi(rmp, win, buf, lnum, col, tm); result = rmp->regprog->engine->regexec_multi(
rmp, win, buf, lnum, col, tm, timed_out);
/* NFA engine aborted because it's very slow. */ /* NFA engine aborted because it's very slow. */
if (rmp->regprog->re_engine == AUTOMATIC_ENGINE if (rmp->regprog->re_engine == AUTOMATIC_ENGINE
@ -8339,7 +8347,7 @@ vim_regexec_multi(
rmp->regprog = vim_regcomp(pat, re_flags); rmp->regprog = vim_regcomp(pat, re_flags);
if (rmp->regprog != NULL) if (rmp->regprog != NULL)
result = rmp->regprog->engine->regexec_multi( result = rmp->regprog->engine->regexec_multi(
rmp, win, buf, lnum, col, tm); rmp, win, buf, lnum, col, tm, timed_out);
vim_free(pat); vim_free(pat);
} }
p_re = save_p_re; p_re = save_p_re;

View File

@ -166,7 +166,7 @@ struct regengine
regprog_T *(*regcomp)(char_u*, int); regprog_T *(*regcomp)(char_u*, int);
void (*regfree)(regprog_T *); void (*regfree)(regprog_T *);
int (*regexec_nl)(regmatch_T *, char_u *, colnr_T, int); int (*regexec_nl)(regmatch_T *, char_u *, colnr_T, int);
long (*regexec_multi)(regmmatch_T*, win_T*, buf_T*, linenr_T, colnr_T, proftime_T*); long (*regexec_multi)(regmmatch_T *, win_T *, buf_T *, linenr_T, colnr_T, proftime_T *, int *);
char_u *expr; char_u *expr;
}; };

View File

@ -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_save_listids(nfa_regprog_T *prog, int *list);
static void nfa_restore_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 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_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); 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 regprog_T *nfa_regcomp(char_u *expr, int re_flags);
static void nfa_regfree(regprog_T *prog); 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 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 match_follows(nfa_state_T *startstate, int depth);
static int failure_chance(nfa_state_T *state, 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; static int nfa_match;
#ifdef FEAT_RELTIME #ifdef FEAT_RELTIME
static proftime_T *nfa_time_limit; static proftime_T *nfa_time_limit;
static int *nfa_timed_out;
static int nfa_time_count; static int nfa_time_count;
#endif #endif
@ -5508,6 +5509,20 @@ find_match_text(colnr_T startcol, int regstart, char_u *match_text)
return 0L; 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. * Main matching routine.
* *
@ -5551,7 +5566,7 @@ nfa_regmatch(
if (got_int) if (got_int)
return FALSE; return FALSE;
#ifdef FEAT_RELTIME #ifdef FEAT_RELTIME
if (nfa_time_limit != NULL && profile_passed_limit(nfa_time_limit)) if (nfa_did_time_out())
return FALSE; return FALSE;
#endif #endif
@ -5694,6 +5709,19 @@ nfa_regmatch(
/* compute nextlist */ /* compute nextlist */
for (listidx = 0; listidx < thislist->n; ++listidx) 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]; t = &thislist->t[listidx];
#ifdef NFA_REGEXP_DEBUG_LOG #ifdef NFA_REGEXP_DEBUG_LOG
@ -6915,7 +6943,7 @@ nextchar:
if (nfa_time_limit != NULL && ++nfa_time_count == 20) if (nfa_time_limit != NULL && ++nfa_time_count == 20)
{ {
nfa_time_count = 0; nfa_time_count = 0;
if (profile_passed_limit(nfa_time_limit)) if (nfa_did_time_out())
break; break;
} }
#endif #endif
@ -6948,7 +6976,8 @@ theend:
nfa_regtry( nfa_regtry(
nfa_regprog_T *prog, nfa_regprog_T *prog,
colnr_T col, 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; int i;
regsubs_T subs, m; regsubs_T subs, m;
@ -6961,6 +6990,7 @@ nfa_regtry(
reginput = regline + col; reginput = regline + col;
#ifdef FEAT_RELTIME #ifdef FEAT_RELTIME
nfa_time_limit = tm; nfa_time_limit = tm;
nfa_timed_out = timed_out;
nfa_time_count = 0; nfa_time_count = 0;
#endif #endif
@ -7087,7 +7117,8 @@ nfa_regtry(
nfa_regexec_both( nfa_regexec_both(
char_u *line, char_u *line,
colnr_T startcol, /* column to start looking for match */ 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; nfa_regprog_T *prog;
long retval = 0L; long retval = 0L;
@ -7181,7 +7212,7 @@ nfa_regexec_both(
prog->state[i].lastlist[1] = 0; prog->state[i].lastlist[1] = 0;
} }
retval = nfa_regtry(prog, col, tm); retval = nfa_regtry(prog, col, tm, timed_out);
nfa_regengine.expr = NULL; nfa_regengine.expr = NULL;
@ -7340,7 +7371,7 @@ nfa_regexec_nl(
rex.reg_icombine = FALSE; rex.reg_icombine = FALSE;
#endif #endif
rex.reg_maxcol = 0; 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 */ buf_T *buf, /* buffer in which to search */
linenr_T lnum, /* nr of line to start looking for match */ linenr_T lnum, /* nr of line to start looking for match */
colnr_T col, /* column 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_match = NULL;
rex.reg_mmatch = rmp; rex.reg_mmatch = rmp;
@ -7391,7 +7423,7 @@ nfa_regexec_multi(
#endif #endif
rex.reg_maxcol = rmp->rmm_maxcol; rex.reg_maxcol = rmp->rmm_maxcol;
return nfa_regexec_both(NULL, col, tm); return nfa_regexec_both(NULL, col, tm, timed_out);
} }
#ifdef DEBUG #ifdef DEBUG

View File

@ -7800,20 +7800,21 @@ next_search_hl(
int regprog_is_copy = (shl != &search_hl && cur != NULL int regprog_is_copy = (shl != &search_hl && cur != NULL
&& shl == &cur->hl && shl == &cur->hl
&& cur->match.regprog == cur->hl.rm.regprog); && cur->match.regprog == cur->hl.rm.regprog);
int timed_out = FALSE;
nmatched = vim_regexec_multi(&shl->rm, win, shl->buf, lnum, nmatched = vim_regexec_multi(&shl->rm, win, shl->buf, lnum,
matchcol, matchcol,
#ifdef FEAT_RELTIME #ifdef FEAT_RELTIME
&(shl->tm) &(shl->tm), &timed_out
#else #else
NULL NULL, NULL
#endif #endif
); );
/* Copy the regprog, in case it got freed and recompiled. */ /* Copy the regprog, in case it got freed and recompiled. */
if (regprog_is_copy) if (regprog_is_copy)
cur->match.regprog = cur->hl.rm.regprog; cur->match.regprog = cur->hl.rm.regprog;
if (called_emsg || got_int) if (called_emsg || got_int || timed_out)
{ {
/* Error while handling regexp: stop using this regexp. */ /* Error while handling regexp: stop using this regexp. */
if (shl == &search_hl) if (shl == &search_hl)

View File

@ -593,7 +593,8 @@ searchit(
int options, int options,
int pat_use, /* which pattern to use when "pat" is empty */ int pat_use, /* which pattern to use when "pat" is empty */
linenr_T stop_lnum, /* stop after this line number when != 0 */ linenr_T stop_lnum, /* stop after this line number when != 0 */
proftime_T *tm UNUSED) /* timeout limit or NULL */ proftime_T *tm UNUSED, /* timeout limit or NULL */
int *timed_out UNUSED) /* set when timed out or NULL */
{ {
int found; int found;
linenr_T lnum; /* no init to shut up Apollo cc */ linenr_T lnum; /* no init to shut up Apollo cc */
@ -715,13 +716,17 @@ searchit(
nmatched = vim_regexec_multi(&regmatch, win, buf, nmatched = vim_regexec_multi(&regmatch, win, buf,
lnum, col, lnum, col,
#ifdef FEAT_RELTIME #ifdef FEAT_RELTIME
tm tm, timed_out
#else #else
NULL NULL, NULL
#endif #endif
); );
/* Abort searching on an error (e.g., out of stack). */ /* Abort searching on an error (e.g., out of stack). */
if (called_emsg) if (called_emsg
#ifdef FEAT_RELTIME
|| (timed_out != NULL && *timed_out)
#endif
)
break; break;
if (nmatched > 0) if (nmatched > 0)
{ {
@ -810,9 +815,9 @@ searchit(
win, buf, lnum + matchpos.lnum, win, buf, lnum + matchpos.lnum,
matchcol, matchcol,
#ifdef FEAT_RELTIME #ifdef FEAT_RELTIME
tm tm, timed_out
#else #else
NULL NULL, NULL
#endif #endif
)) == 0) )) == 0)
{ {
@ -922,9 +927,9 @@ searchit(
win, buf, lnum + matchpos.lnum, win, buf, lnum + matchpos.lnum,
matchcol, matchcol,
#ifdef FEAT_RELTIME #ifdef FEAT_RELTIME
tm tm, timed_out
#else #else
NULL NULL, NULL
#endif #endif
)) == 0) )) == 0)
break; break;
@ -1019,6 +1024,9 @@ searchit(
* twice. * twice.
*/ */
if (!p_ws || stop_lnum != 0 || got_int || called_emsg if (!p_ws || stop_lnum != 0 || got_int || called_emsg
#ifdef FEAT_RELTIME
|| (timed_out != NULL && *timed_out)
#endif
#ifdef FEAT_SEARCH_EXTRA #ifdef FEAT_SEARCH_EXTRA
|| break_loop || break_loop
#endif #endif
@ -1041,6 +1049,9 @@ searchit(
? top_bot_msg : bot_top_msg), TRUE); ? top_bot_msg : bot_top_msg), TRUE);
} }
if (got_int || called_emsg if (got_int || called_emsg
#ifdef FEAT_RELTIME
|| (timed_out != NULL && *timed_out)
#endif
#ifdef FEAT_SEARCH_EXTRA #ifdef FEAT_SEARCH_EXTRA
|| break_loop || break_loop
#endif #endif
@ -1147,7 +1158,8 @@ do_search(
char_u *pat, char_u *pat,
long count, long count,
int options, int options,
proftime_T *tm) /* timeout limit or NULL */ proftime_T *tm, /* timeout limit or NULL */
int *timed_out) /* flag set on timeout or NULL */
{ {
pos_T pos; /* position of the last match */ pos_T pos; /* position of the last match */
char_u *searchstr; char_u *searchstr;
@ -1433,7 +1445,7 @@ do_search(
(SEARCH_KEEP + SEARCH_PEEK + SEARCH_HIS (SEARCH_KEEP + SEARCH_PEEK + SEARCH_HIS
+ SEARCH_MSG + SEARCH_START + SEARCH_MSG + SEARCH_START
+ ((pat != NULL && *pat == ';') ? 0 : SEARCH_NOOF))), + ((pat != NULL && *pat == ';') ? 0 : SEARCH_NOOF))),
RE_LAST, (linenr_T)0, tm); RE_LAST, (linenr_T)0, tm, timed_out);
if (dircp != NULL) if (dircp != NULL)
*dircp = dirc; /* restore second '/' or '?' for normal_cmd() */ *dircp = dirc; /* restore second '/' or '?' for normal_cmd() */
@ -4672,7 +4684,7 @@ current_search(
result = searchit(curwin, curbuf, &pos, (dir ? FORWARD : BACKWARD), result = searchit(curwin, curbuf, &pos, (dir ? FORWARD : BACKWARD),
spats[last_idx].pat, (long) (i ? count : 1), spats[last_idx].pat, (long) (i ? count : 1),
SEARCH_KEEP | flags, RE_SEARCH, 0, NULL); SEARCH_KEEP | flags, RE_SEARCH, 0, NULL, NULL);
/* First search may fail, but then start searching from the /* First search may fail, but then start searching from the
* beginning of the file (cursor might be on the search match) * beginning of the file (cursor might be on the search match)
@ -4719,7 +4731,8 @@ current_search(
* already on the next match */ * already on the next match */
if (!one_char) if (!one_char)
result = searchit(curwin, curbuf, &pos, (forward ? FORWARD : BACKWARD), result = searchit(curwin, curbuf, &pos, (forward ? FORWARD : BACKWARD),
spats[last_idx].pat, 0L, flags | SEARCH_KEEP, RE_SEARCH, 0, NULL); spats[last_idx].pat, 0L, flags | SEARCH_KEEP, RE_SEARCH, 0,
NULL, NULL);
if (!VIsual_active) if (!VIsual_active)
VIsual = start_pos; VIsual = start_pos;
@ -4800,7 +4813,7 @@ is_one_char(char_u *pattern, int move, pos_T *cur)
} }
if (searchit(curwin, curbuf, &pos, FORWARD, pattern, 1, if (searchit(curwin, curbuf, &pos, FORWARD, pattern, 1,
SEARCH_KEEP + flag, RE_SEARCH, 0, NULL) != FAIL) SEARCH_KEEP + flag, RE_SEARCH, 0, NULL, NULL) != FAIL)
{ {
/* Zero-width pattern should match somewhere, then we can check if /* Zero-width pattern should match somewhere, then we can check if
* start and end are in the same position. */ * start and end are in the same position. */
@ -4809,7 +4822,7 @@ is_one_char(char_u *pattern, int move, pos_T *cur)
{ {
regmatch.startpos[0].col++; regmatch.startpos[0].col++;
nmatched = vim_regexec_multi(&regmatch, curwin, curbuf, nmatched = vim_regexec_multi(&regmatch, curwin, curbuf,
pos.lnum, regmatch.startpos[0].col, NULL); pos.lnum, regmatch.startpos[0].col, NULL, NULL);
if (!nmatched) if (!nmatched)
break; break;
} while (regmatch.startpos[0].col < pos.col); } while (regmatch.startpos[0].col < pos.col);

View File

@ -3675,7 +3675,7 @@ ex_spellrepall(exarg_T *eap UNUSED)
curwin->w_cursor.lnum = 0; curwin->w_cursor.lnum = 0;
while (!got_int) while (!got_int)
{ {
if (do_search(NULL, '/', frompat, 1L, SEARCH_KEEP, NULL) == 0 if (do_search(NULL, '/', frompat, 1L, SEARCH_KEEP, NULL, NULL) == 0
|| u_save_cursor() == FAIL) || u_save_cursor() == FAIL)
break; break;

View File

@ -3303,7 +3303,7 @@ syn_regexec(
#endif #endif
rmp->rmm_maxcol = syn_buf->b_p_smc; rmp->rmm_maxcol = syn_buf->b_p_smc;
r = vim_regexec_multi(rmp, syn_win, syn_buf, lnum, col, NULL); r = vim_regexec_multi(rmp, syn_win, syn_buf, lnum, col, NULL, NULL);
#ifdef FEAT_PROFILE #ifdef FEAT_PROFILE
if (syn_time_on) if (syn_time_on)

View File

@ -3308,7 +3308,7 @@ jumpto_tag(
save_lnum = curwin->w_cursor.lnum; save_lnum = curwin->w_cursor.lnum;
curwin->w_cursor.lnum = 0; /* start search before first line */ curwin->w_cursor.lnum = 0; /* start search before first line */
if (do_search(NULL, pbuf[0], pbuf + 1, (long)1, if (do_search(NULL, pbuf[0], pbuf + 1, (long)1,
search_options, NULL)) search_options, NULL, NULL))
retval = OK; retval = OK;
else else
{ {
@ -3320,7 +3320,7 @@ jumpto_tag(
*/ */
p_ic = TRUE; p_ic = TRUE;
if (!do_search(NULL, pbuf[0], pbuf + 1, (long)1, if (!do_search(NULL, pbuf[0], pbuf + 1, (long)1,
search_options, NULL)) search_options, NULL, NULL))
{ {
/* /*
* Failed to find pattern, take a guess: "^func (" * Failed to find pattern, take a guess: "^func ("
@ -3331,13 +3331,13 @@ jumpto_tag(
*tagp.tagname_end = NUL; *tagp.tagname_end = NUL;
sprintf((char *)pbuf, "^%s\\s\\*(", tagp.tagname); sprintf((char *)pbuf, "^%s\\s\\*(", tagp.tagname);
if (!do_search(NULL, '/', pbuf, (long)1, if (!do_search(NULL, '/', pbuf, (long)1,
search_options, NULL)) search_options, NULL, NULL))
{ {
/* Guess again: "^char * \<func (" */ /* Guess again: "^char * \<func (" */
sprintf((char *)pbuf, "^\\[#a-zA-Z_]\\.\\*\\<%s\\s\\*(", sprintf((char *)pbuf, "^\\[#a-zA-Z_]\\.\\*\\<%s\\s\\*(",
tagp.tagname); tagp.tagname);
if (!do_search(NULL, '/', pbuf, (long)1, if (!do_search(NULL, '/', pbuf, (long)1,
search_options, NULL)) search_options, NULL, NULL))
found = 0; found = 0;
} }
*tagp.tagname_end = cc; *tagp.tagname_end = cc;

View File

@ -764,6 +764,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
643,
/**/ /**/
642, 642,
/**/ /**/