aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBilly Su <g4691821@gmail.com>2019-03-07 13:08:15 +0800
committerBilly Su <g4691821@gmail.com>2019-03-07 23:27:19 +0800
commit241b905b1378c5c45d8d284bb191b16807ff2a44 (patch)
treece1726447334ae05c894b1b7bd59718058a12a32
parent5f84b1dc4154ea8def87b6113fa9b9ed058d83d2 (diff)
downloadrneovim-241b905b1378c5c45d8d284bb191b16807ff2a44.tar.gz
rneovim-241b905b1378c5c45d8d284bb191b16807ff2a44.tar.bz2
rneovim-241b905b1378c5c45d8d284bb191b16807ff2a44.zip
vim-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. https://github.com/vim/vim/commit/fbd0b0af6800f6ff89857863d6a07ea03f09ff6c
-rw-r--r--src/nvim/edit.c9
-rw-r--r--src/nvim/eval.c9
-rw-r--r--src/nvim/ex_cmds.c12
-rw-r--r--src/nvim/ex_docmd.c4
-rw-r--r--src/nvim/ex_getln.c4
-rw-r--r--src/nvim/normal.c9
-rw-r--r--src/nvim/quickfix.c5
-rw-r--r--src/nvim/regexp.c36
-rw-r--r--src/nvim/regexp_defs.h8
-rw-r--r--src/nvim/regexp_nfa.c48
-rw-r--r--src/nvim/screen.c8
-rw-r--r--src/nvim/search.c67
-rw-r--r--src/nvim/spell.c5
-rw-r--r--src/nvim/syntax.c2
-rw-r--r--src/nvim/tag.c23
15 files changed, 150 insertions, 99 deletions
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index 6b31406b0c..667bc54e2e 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -3907,10 +3907,11 @@ static int ins_compl_get_exp(pos_T *ini)
compl_direction, compl_pattern);
} else
found_new_match = searchit(NULL, ins_buf, pos,
- compl_direction,
- compl_pattern, 1L, SEARCH_KEEP + SEARCH_NFMSG,
- RE_LAST, (linenr_T)0, NULL);
- --msg_silent;
+ compl_direction,
+ compl_pattern, 1L,
+ SEARCH_KEEP + SEARCH_NFMSG,
+ RE_LAST, (linenr_T)0, NULL, NULL);
+ msg_silent--;
if (!compl_started || set_match_pos) {
/* set "compl_started" even on fail */
compl_started = TRUE;
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index d18884ff07..aa0d925ff2 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -13793,7 +13793,7 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp)
pos = save_cursor = curwin->w_cursor;
subpatnum = searchit(curwin, curbuf, &pos, dir, (char_u *)pat, 1,
- options, RE_SEARCH, (linenr_T)lnum_stop, &tm);
+ options, RE_SEARCH, (linenr_T)lnum_stop, &tm, NULL);
if (subpatnum != FAIL) {
if (flags & SP_SUBPAT)
retval = subpatnum;
@@ -14295,10 +14295,11 @@ do_searchpair(
pat = pat3;
for (;; ) {
n = searchit(curwin, curbuf, &pos, dir, pat, 1L,
- options, RE_SEARCH, lnum_stop, &tm);
- if (n == FAIL || (firstpos.lnum != 0 && equalpos(pos, firstpos)))
- /* didn't find it or found the first match again: FAIL */
+ options, RE_SEARCH, lnum_stop, &tm, NULL);
+ if (n == FAIL || (firstpos.lnum != 0 && equalpos(pos, firstpos))) {
+ // didn't find it or found the first match again: FAIL
break;
+ }
if (firstpos.lnum == 0)
firstpos = pos;
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 2a5793f0d4..4356767cc9 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -3432,7 +3432,7 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout,
|| lnum <= curwin->w_botline);
lnum++) {
long nmatch = vim_regexec_multi(&regmatch, curwin, curbuf, lnum,
- (colnr_T)0, NULL);
+ (colnr_T)0, NULL, NULL);
if (nmatch) {
colnr_T copycol;
colnr_T matchcol;
@@ -3951,8 +3951,8 @@ skip:
if (lastone
|| nmatch_tl > 0
|| (nmatch = vim_regexec_multi(&regmatch, curwin,
- curbuf, sub_firstlnum,
- matchcol, NULL)) == 0
+ curbuf, sub_firstlnum,
+ matchcol, NULL, NULL)) == 0
|| regmatch.startpos[0].lnum > 0) {
if (new_start != NULL) {
/*
@@ -4016,7 +4016,7 @@ skip:
}
if (nmatch == -1 && !lastone)
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
@@ -4314,7 +4314,7 @@ void ex_global(exarg_T *eap)
if (global_busy) {
lnum = curwin->w_cursor.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)) {
global_exe_one(cmd, lnum);
}
@@ -4323,7 +4323,7 @@ void ex_global(exarg_T *eap)
for (lnum = eap->line1; lnum <= eap->line2 && !got_int; lnum++) {
// a match on this line?
match = vim_regexec_multi(&regmatch, curwin, curbuf, lnum,
- (colnr_T)0, NULL);
+ (colnr_T)0, NULL, NULL);
if ((type == 'g' && match) || (type == 'v' && !match)) {
ml_setmarked(lnum);
ndone++;
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 6b39ad8e87..5b9b4fed12 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -3699,7 +3699,7 @@ static linenr_T get_address(exarg_T *eap,
}
searchcmdlen = 0;
if (!do_search(NULL, c, cmd, 1L,
- SEARCH_HIS | SEARCH_MSG, NULL)) {
+ SEARCH_HIS | SEARCH_MSG, NULL, NULL)) {
curwin->w_cursor = pos;
cmd = NULL;
goto error;
@@ -3737,7 +3737,7 @@ static linenr_T get_address(exarg_T *eap,
if (searchit(curwin, curbuf, &pos,
*cmd == '?' ? BACKWARD : FORWARD,
(char_u *)"", 1L, SEARCH_MSG,
- i, (linenr_T)0, NULL) != FAIL)
+ i, (linenr_T)0, NULL, NULL) != FAIL)
lnum = pos.lnum;
else {
cmd = NULL;
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index a50e18efce..8e6fc5ad4f 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -1061,7 +1061,7 @@ static void command_line_next_incsearch(CommandLineState *s, bool next_match)
s->i = searchit(curwin, curbuf, &t,
next_match ? FORWARD : BACKWARD,
pat, s->count, search_flags,
- RE_SEARCH, 0, NULL);
+ RE_SEARCH, 0, NULL, NULL);
emsg_off--;
ui_busy_stop();
if (s->i) {
@@ -1847,7 +1847,7 @@ static int command_line_changed(CommandLineState *s)
}
s->i = do_search(NULL, s->firstc, ccline.cmdbuff, s->count,
search_flags,
- &tm);
+ &tm, NULL);
emsg_off--;
// if interrupted while searching, behave like it failed
if (got_int) {
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 49eef72a05..0b85714e39 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -3782,9 +3782,10 @@ find_decl (
valid = false;
(void)valid; // Avoid "dead assignment" warning.
t = searchit(curwin, curbuf, &curwin->w_cursor, FORWARD,
- pat, 1L, searchflags, RE_LAST, (linenr_T)0, NULL);
- if (curwin->w_cursor.lnum >= old_pos.lnum)
- t = false; /* match after start is failure too */
+ pat, 1L, searchflags, RE_LAST, (linenr_T)0, NULL, NULL);
+ if (curwin->w_cursor.lnum >= old_pos.lnum) {
+ t = false; // match after start is failure too
+ }
if (thisblock && t != false) {
const int64_t maxtravel = old_pos.lnum - curwin->w_cursor.lnum + 1;
@@ -5384,7 +5385,7 @@ static int normal_search(
curwin->w_set_curswant = true;
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) {
clearop(cap->oap);
} else {
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index f0c37c0e38..ee1cf2182f 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -2128,8 +2128,9 @@ win_found:
save_cursor = curwin->w_cursor;
curwin->w_cursor.lnum = 0;
if (!do_search(NULL, '/', qf_ptr->qf_pattern, (long)1,
- SEARCH_KEEP, NULL))
+ SEARCH_KEEP, NULL, NULL)) {
curwin->w_cursor = save_cursor;
+ }
}
if ((fdo_flags & FDO_QUICKFIX) && old_KeyTyped)
@@ -3758,7 +3759,7 @@ void ex_vimgrep(exarg_T *eap)
++lnum) {
col = 0;
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
// dummy buffer, unless duplicate_name is set, then the
// buffer will be wiped out below.
diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c
index c043d4a173..25fa67c112 100644
--- a/src/nvim/regexp.c
+++ b/src/nvim/regexp.c
@@ -3297,7 +3297,7 @@ bt_regexec_nl (
rex.reg_icombine = false;
rex.reg_maxcol = 0;
- long r = bt_regexec_both(line, col, NULL);
+ long r = bt_regexec_both(line, col, NULL, NULL);
assert(r <= INT_MAX);
return (int)r;
}
@@ -3357,7 +3357,8 @@ static inline char_u *cstrchr(const char_u *const s, const int c)
/// @return zero if there is no match and number of lines contained in the match
/// otherwise.
static long bt_regexec_multi(regmmatch_T *rmp, win_T *win, buf_T *buf,
- linenr_T lnum, colnr_T col, proftime_T *tm)
+ linenr_T lnum, colnr_T col,
+ proftime_T *tm, int *timed_out)
{
rex.reg_match = NULL;
rex.reg_mmatch = rmp;
@@ -3370,7 +3371,7 @@ static long bt_regexec_multi(regmmatch_T *rmp, win_T *win, buf_T *buf,
rex.reg_icombine = false;
rex.reg_maxcol = rmp->rmm_maxcol;
- return bt_regexec_both(NULL, col, tm);
+ return bt_regexec_both(NULL, col, tm, timed_out);
}
/*
@@ -3379,8 +3380,10 @@ static long bt_regexec_multi(regmmatch_T *rmp, win_T *win, buf_T *buf,
* Returns 0 for failure, number of lines contained in the match otherwise.
*/
static long bt_regexec_both(char_u *line,
- colnr_T col, /* column to start looking for match */
- proftime_T *tm /* timeout limit or NULL */
+ // column to start looking for match
+ colnr_T col,
+ proftime_T *tm, // timeout limit or NULL
+ int *timed_out // flag set on timeout or NULL
)
{
bt_regprog_T *prog;
@@ -3525,8 +3528,12 @@ static long bt_regexec_both(char_u *line,
/* Check for timeout once in a twenty times to avoid overhead. */
if (tm != NULL && ++tm_count == 20) {
tm_count = 0;
- if (profile_passed_limit(*tm))
+ if (profile_passed_limit(*tm)) {
+ if (timed_out != NULL) {
+ *timed_out = true;
+ }
break;
+ }
}
}
}
@@ -7275,12 +7282,13 @@ int vim_regexec_nl(regmatch_T *rmp, char_u *line, colnr_T col)
/// Return zero if there is no match. Return number of lines contained in the
/// match otherwise.
long vim_regexec_multi(
- regmmatch_T *rmp,
- win_T *win, /* window in which to search or NULL */
- 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 */
+ regmmatch_T *rmp,
+ win_T *win, // window in which to search or NULL
+ 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
+ int *timed_out // flag is set when timeout limit reached
)
{
regexec_T rex_save;
@@ -7293,7 +7301,7 @@ long vim_regexec_multi(
rex_in_use = true;
int result = rmp->regprog->engine->regexec_multi(rmp, win, buf, lnum, col,
- tm);
+ tm, timed_out);
// NFA engine aborted because it's very slow, use backtracking engine instead.
if (rmp->regprog->re_engine == AUTOMATIC_ENGINE
@@ -7313,7 +7321,7 @@ long vim_regexec_multi(
if (rmp->regprog != NULL) {
result = rmp->regprog->engine->regexec_multi(rmp, win, buf, lnum, col,
- tm);
+ tm, timed_out);
}
xfree(pat);
diff --git a/src/nvim/regexp_defs.h b/src/nvim/regexp_defs.h
index b5d56e07fc..298d82fc6b 100644
--- a/src/nvim/regexp_defs.h
+++ b/src/nvim/regexp_defs.h
@@ -156,11 +156,11 @@ struct reg_extmatch {
};
struct regengine {
- regprog_T *(*regcomp)(char_u*, int);
+ regprog_T *(*regcomp)(char_u *, int);
void (*regfree)(regprog_T *);
- int (*regexec_nl)(regmatch_T*, char_u*, colnr_T, bool);
- long (*regexec_multi)(regmmatch_T*, win_T*, buf_T*, linenr_T, colnr_T,
- proftime_T*);
+ int (*regexec_nl)(regmatch_T *, char_u *, colnr_T, bool);
+ long (*regexec_multi)(regmmatch_T *, win_T *, buf_T *, linenr_T, colnr_T,
+ proftime_T *, int *);
char_u *expr;
};
diff --git a/src/nvim/regexp_nfa.c b/src/nvim/regexp_nfa.c
index 95030974d8..0df67336d3 100644
--- a/src/nvim/regexp_nfa.c
+++ b/src/nvim/regexp_nfa.c
@@ -3568,6 +3568,7 @@ static char *pim_info(nfa_pim_T *pim)
// Used during execution: whether a match has been found.
static int nfa_match;
static proftime_T *nfa_time_limit;
+static int *nfa_timed_out;
static int nfa_time_count;
// Copy postponed invisible match info from "from" to "to".
@@ -4939,6 +4940,17 @@ static long find_match_text(colnr_T startcol, int regstart, char_u *match_text)
#undef PTR2LEN
}
+static int nfa_did_time_out(void)
+{
+ if (nfa_time_limit != NULL && profile_passed_limit(*nfa_time_limit)) {
+ if (nfa_timed_out != NULL) {
+ *nfa_timed_out = true;
+ }
+ return true;
+ }
+ return false;
+}
+
/// Main matching routine.
///
/// Run NFA to determine whether it matches reginput.
@@ -4982,7 +4994,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start,
#endif
return false;
}
- if (nfa_time_limit != NULL && profile_passed_limit(*nfa_time_limit)) {
+ if (nfa_did_time_out()) {
#ifdef NFA_REGEXP_DEBUG_LOG
fclose(debug);
#endif
@@ -5095,8 +5107,20 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start,
if (thislist->n == 0)
break;
- /* compute nextlist */
- for (listidx = 0; listidx < thislist->n; ++listidx) {
+ // 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;
+ }
+ if (nfa_time_limit != NULL && ++nfa_time_count == 20) {
+ nfa_time_count = 0;
+ if (nfa_did_time_out()) {
+ break;
+ }
+ }
t = &thislist->t[listidx];
#ifdef NFA_REGEXP_DEBUG_LOG
@@ -6218,7 +6242,7 @@ nextchar:
// Check for timeout once every twenty times to avoid overhead.
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;
}
}
@@ -6245,7 +6269,8 @@ theend:
// Try match of "prog" with at regline["col"].
// Returns <= 0 for failure, number of lines contained in the match otherwise.
-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)
{
int i;
regsubs_T subs, m;
@@ -6256,6 +6281,7 @@ static long nfa_regtry(nfa_regprog_T *prog, colnr_T col, proftime_T *tm)
reginput = regline + col;
nfa_time_limit = tm;
+ nfa_timed_out = timed_out;
nfa_time_count = 0;
#ifdef REGEXP_DEBUG
@@ -6367,7 +6393,8 @@ static long nfa_regtry(nfa_regprog_T *prog, colnr_T col, proftime_T *tm)
///
/// @return <= 0 if there is no match and number of lines contained in the
/// match otherwise.
-static long nfa_regexec_both(char_u *line, colnr_T startcol, proftime_T *tm)
+static long nfa_regexec_both(char_u *line, colnr_T startcol,
+ proftime_T *tm, int *timed_out)
{
nfa_regprog_T *prog;
long retval = 0L;
@@ -6449,7 +6476,7 @@ static long nfa_regexec_both(char_u *line, colnr_T startcol, proftime_T *tm)
prog->state[i].lastlist[1] = 0;
}
- retval = nfa_regtry(prog, col, tm);
+ retval = nfa_regtry(prog, col, tm, timed_out);
nfa_regengine.expr = NULL;
@@ -6596,7 +6623,7 @@ nfa_regexec_nl (
rex.reg_ic = rmp->rm_ic;
rex.reg_icombine = false;
rex.reg_maxcol = 0;
- return nfa_regexec_both(line, col, NULL);
+ return nfa_regexec_both(line, col, NULL, NULL);
}
/// Matches a regexp against multiple lines.
@@ -6634,7 +6661,8 @@ nfa_regexec_nl (
/// @par
/// FIXME if this behavior is not compatible.
static long nfa_regexec_multi(regmmatch_T *rmp, win_T *win, buf_T *buf,
- linenr_T lnum, colnr_T col, proftime_T *tm)
+ linenr_T lnum, colnr_T col,
+ proftime_T *tm, int *timed_out)
{
rex.reg_match = NULL;
rex.reg_mmatch = rmp;
@@ -6647,5 +6675,5 @@ static long nfa_regexec_multi(regmmatch_T *rmp, win_T *win, buf_T *buf,
rex.reg_icombine = false;
rex.reg_maxcol = rmp->rmm_maxcol;
- return nfa_regexec_both(NULL, col, tm);
+ return nfa_regexec_both(NULL, col, tm, timed_out);
}
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index 08bb4e4a52..5255fd2a51 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -5651,13 +5651,15 @@ next_search_hl (
&& cur != NULL
&& shl == &cur->hl
&& cur->match.regprog == cur->hl.rm.regprog);
+ int timed_out = false;
- nmatched = vim_regexec_multi(&shl->rm, win, shl->buf, lnum, matchcol, &(shl->tm));
- /* Copy the regprog, in case it got freed and recompiled. */
+ nmatched = vim_regexec_multi(&shl->rm, win, shl->buf, lnum, matchcol,
+ &(shl->tm), &timed_out);
+ // Copy the regprog, in case it got freed and recompiled.
if (regprog_is_copy) {
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.
if (shl == &search_hl) {
// don't free regprog in the match list, it's a copy
diff --git a/src/nvim/search.c b/src/nvim/search.c
index f6b80d1b79..3d95ad0e92 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -523,9 +523,10 @@ int searchit(
char_u *pat,
long count,
int options,
- int pat_use, /* which pattern to use when "pat" is empty */
- linenr_T stop_lnum, /* stop after this line number when != 0 */
- proftime_T *tm /* timeout limit or NULL */
+ int pat_use, // which pattern to use when "pat" is empty
+ linenr_T stop_lnum, // stop after this line number when != 0
+ proftime_T *tm, // timeout limit or NULL
+ int *timed_out // set when timed out or NULL
)
{
int found;
@@ -620,9 +621,9 @@ int searchit(
// Look for a match somewhere in line "lnum".
colnr_T col = at_first_line && (options & SEARCH_COL) ? pos->col : 0;
nmatched = vim_regexec_multi(&regmatch, win, buf,
- lnum, col, tm);
+ lnum, col, tm, timed_out);
// Abort searching on an error (e.g., out of stack).
- if (called_emsg) {
+ if (called_emsg || (timed_out != NULL && *timed_out)) {
break;
}
if (nmatched > 0) {
@@ -686,8 +687,9 @@ int searchit(
}
if (ptr[matchcol] == NUL
- || (nmatched = vim_regexec_multi(&regmatch, win, buf, lnum,
- matchcol, tm)) == 0) {
+ || (nmatched = vim_regexec_multi(&regmatch, win, buf,
+ lnum, matchcol, tm,
+ timed_out)) == 0) {
match_ok = false;
break;
}
@@ -771,7 +773,7 @@ int searchit(
if (ptr[matchcol] == NUL
|| (nmatched = vim_regexec_multi(
&regmatch, win, buf, lnum + matchpos.lnum, matchcol,
- tm)) == 0) {
+ tm, timed_out)) == 0) {
// If the search timed out, we did find a match
// but it might be the wrong one, so that's not
// OK.
@@ -855,30 +857,35 @@ int searchit(
* twice.
*/
if (!p_ws || stop_lnum != 0 || got_int || called_emsg
+ || (timed_out != NULL && timed_out)
|| break_loop
- || found || loop)
+ || found || loop) {
break;
-
- /*
- * If 'wrapscan' is set we continue at the other end of the file.
- * If 'shortmess' does not contain 's', we give a message.
- * This message is also remembered in keep_msg for when the screen
- * is redrawn. The keep_msg is cleared whenever another message is
- * written.
- */
- if (dir == BACKWARD) /* start second loop at the other end */
+ }
+ //
+ // If 'wrapscan' is set we continue at the other end of the file.
+ // If 'shortmess' does not contain 's', we give a message.
+ // This message is also remembered in keep_msg for when the screen
+ // is redrawn. The keep_msg is cleared whenever another message is
+ // written.
+ //
+ if (dir == BACKWARD) { // start second loop at the other end
lnum = buf->b_ml.ml_line_count;
- else
+ } else {
lnum = 1;
- if (!shortmess(SHM_SEARCH) && (options & SEARCH_MSG))
+ }
+ if (!shortmess(SHM_SEARCH) && (options & SEARCH_MSG)) {
give_warning((char_u *)_(dir == BACKWARD
- ? top_bot_msg : bot_top_msg), true);
+ ? top_bot_msg : bot_top_msg), true);
+ }
}
if (got_int || called_emsg
+ || (timed_out != NULL && *timed_out)
|| break_loop
- )
+ ) {
break;
- } while (--count > 0 && found); /* stop after count matches or no match */
+ }
+ } while (--count > 0 && found); // stop after count matches or no match
vim_regfree(regmatch.regprog);
@@ -965,7 +972,8 @@ int do_search(
char_u *pat,
long count,
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 */
@@ -1195,7 +1203,7 @@ int do_search(
& (SEARCH_KEEP + SEARCH_PEEK + SEARCH_HIS + SEARCH_MSG
+ SEARCH_START
+ ((pat != NULL && *pat == ';') ? 0 : SEARCH_NOOF)))),
- RE_LAST, (linenr_T)0, tm);
+ RE_LAST, (linenr_T)0, tm, timed_out);
if (dircp != NULL)
*dircp = dirc; /* restore second '/' or '?' for normal_cmd() */
@@ -3978,7 +3986,7 @@ current_search(
result = searchit(curwin, curbuf, &pos, (dir ? FORWARD : BACKWARD),
spats[last_idx].pat, 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
* beginning of the file (cursor might be on the search match)
@@ -4025,7 +4033,7 @@ current_search(
for (int i = 0; i < 2; i++) {
result = searchit(curwin, curbuf, &pos, direction,
spats[last_idx].pat, 0L, flags | SEARCH_KEEP, RE_SEARCH,
- 0, NULL);
+ 0, NULL, NULL);
// Search successfull, break out from the loop
if (result) {
break;
@@ -4104,14 +4112,15 @@ static int is_one_char(char_u *pattern, bool move, pos_T *cur,
flag = SEARCH_START;
}
if (searchit(curwin, curbuf, &pos, direction, 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
// start and end are in the same position.
called_emsg = false;
do {
regmatch.startpos[0].col++;
nmatched = vim_regexec_multi(&regmatch, curwin, curbuf,
- pos.lnum, regmatch.startpos[0].col, NULL);
+ pos.lnum, regmatch.startpos[0].col,
+ NULL, NULL);
if (!nmatched) {
break;
}
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index ff61c2e5de..ec4da88ea1 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -3048,9 +3048,10 @@ void ex_spellrepall(exarg_T *eap)
sub_nlines = 0;
curwin->w_cursor.lnum = 0;
while (!got_int) {
- if (do_search(NULL, '/', frompat, 1L, SEARCH_KEEP, NULL) == 0
- || u_save_cursor() == FAIL)
+ if (do_search(NULL, '/', frompat, 1L, SEARCH_KEEP, NULL, NULL) == 0
+ || u_save_cursor() == FAIL) {
break;
+ }
// Only replace when the right word isn't there yet. This happens
// when changing "etc" to "etc.".
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index b6b7dfff11..0104f0d834 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -2902,7 +2902,7 @@ static int syn_regexec(regmmatch_T *rmp, linenr_T lnum, colnr_T col, syn_time_T
}
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);
if (l_syn_time_on) {
pt = profile_end(pt);
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index 50397d40e6..bd837a531d 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -2508,9 +2508,9 @@ static int jumpto_tag(
save_lnum = curwin->w_cursor.lnum;
curwin->w_cursor.lnum = 0; /* start search before first line */
if (do_search(NULL, pbuf[0], pbuf + 1, (long)1,
- search_options, NULL))
+ search_options, NULL, NULL)) {
retval = OK;
- else {
+ } else {
int found = 1;
int cc;
@@ -2519,23 +2519,22 @@ static int jumpto_tag(
*/
p_ic = TRUE;
if (!do_search(NULL, pbuf[0], pbuf + 1, (long)1,
- search_options, NULL)) {
- /*
- * Failed to find pattern, take a guess: "^func ("
- */
+ search_options, NULL, NULL)) {
+ // Failed to find pattern, take a guess: "^func ("
found = 2;
(void)test_for_static(&tagp);
cc = *tagp.tagname_end;
*tagp.tagname_end = NUL;
- sprintf((char *)pbuf, "^%s\\s\\*(", tagp.tagname);
+ snprintf((char *)pbuf, LSIZE, "^%s\\s\\*(", tagp.tagname);
if (!do_search(NULL, '/', pbuf, (long)1,
- search_options, NULL)) {
- /* Guess again: "^char * \<func (" */
- sprintf((char *)pbuf, "^\\[#a-zA-Z_]\\.\\*\\<%s\\s\\*(",
- tagp.tagname);
+ search_options, NULL, NULL)) {
+ // Guess again: "^char * \<func ("
+ snprintf((char *)pbuf, LSIZE, "^\\[#a-zA-Z_]\\.\\*\\<%s\\s\\*(",
+ tagp.tagname);
if (!do_search(NULL, '/', pbuf, (long)1,
- search_options, NULL))
+ search_options, NULL, NULL)) {
found = 0;
+ }
}
*tagp.tagname_end = cc;
}