summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Marriott <basilisk@internode.on.net>2024-05-20 19:18:26 +0200
committerChristian Brabandt <cb@256bit.org>2024-05-20 19:18:26 +0200
commit8c85a2a49acf80e4f53ec51e6ff2a5f3830eeddb (patch)
treed6554cf3c98aeef4af872d35ded945933bf911f8
parent69dff00dfb37077f4a80fd9635ea963889ad4b49 (diff)
patch 9.1.0426: too many strlen() calls in search.cv9.1.0426
Problem: too many strlen() calls in search.c Solution: refactor code and remove more strlen() calls, use explicit variable to remember strlen (John Marriott) closes: #14796 Signed-off-by: John Marriott <basilisk@internode.on.net> Signed-off-by: Christian Brabandt <cb@256bit.org>
-rw-r--r--src/cmdhist.c9
-rw-r--r--src/evalfunc.c34
-rw-r--r--src/ex_cmds.c15
-rw-r--r--src/ex_docmd.c4
-rw-r--r--src/ex_getln.c10
-rw-r--r--src/gui.c4
-rw-r--r--src/insexpand.c67
-rw-r--r--src/normal.c95
-rw-r--r--src/proto/cmdhist.pro2
-rw-r--r--src/proto/search.pro8
-rw-r--r--src/quickfix.c2
-rw-r--r--src/search.c297
-rw-r--r--src/spell.c5
-rw-r--r--src/structs.h1
-rw-r--r--src/tag.c14
-rw-r--r--src/version.c2
16 files changed, 395 insertions, 174 deletions
diff --git a/src/cmdhist.c b/src/cmdhist.c
index 6342f02bdd..7cdcee6b86 100644
--- a/src/cmdhist.c
+++ b/src/cmdhist.c
@@ -297,11 +297,11 @@ static int last_maptick = -1; // last seen maptick
add_to_history(
int histype,
char_u *new_entry,
+ size_t new_entrylen,
int in_map, // consider maptick when inside a mapping
int sep) // separator character used (search hist)
{
histentry_T *hisptr;
- int len;
if (hislen == 0) // no history
return;
@@ -336,10 +336,9 @@ add_to_history(
vim_free(hisptr->hisstr);
// Store the separator after the NUL of the string.
- len = (int)STRLEN(new_entry);
- hisptr->hisstr = vim_strnsave(new_entry, len + 2);
+ hisptr->hisstr = vim_strnsave(new_entry, new_entrylen + 2);
if (hisptr->hisstr != NULL)
- hisptr->hisstr[len + 1] = sep;
+ hisptr->hisstr[new_entrylen + 1] = sep;
hisptr->hisnum = ++hisnum[histype];
hisptr->viminfo = FALSE;
@@ -566,7 +565,7 @@ f_histadd(typval_T *argvars UNUSED, typval_T *rettv)
return;
init_history();
- add_to_history(histype, str, FALSE, NUL);
+ add_to_history(histype, str, STRLEN(str), FALSE, NUL);
rettv->vval.v_number = TRUE;
}
diff --git a/src/evalfunc.c b/src/evalfunc.c
index 571ac08626..903205ad31 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -9712,6 +9712,7 @@ search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp)
{
int flags;
char_u *pat;
+ size_t patlen;
pos_T pos;
pos_T save_cursor;
int save_p_ws = p_ws;
@@ -9786,10 +9787,12 @@ search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp)
sia.sa_tm = time_limit;
#endif
+ patlen = STRLEN(pat);
+
// Repeat until {skip} returns FALSE.
for (;;)
{
- subpatnum = searchit(curwin, curbuf, &pos, NULL, dir, pat, 1L,
+ subpatnum = searchit(curwin, curbuf, &pos, NULL, dir, pat, patlen, 1L,
options, RE_SEARCH, &sia);
// finding the first match again means there is no match where {skip}
// evaluates to zero.
@@ -10202,6 +10205,13 @@ do_searchpair(
{
char_u *save_cpo;
char_u *pat, *pat2 = NULL, *pat3 = NULL;
+ size_t patlen;
+ size_t spatlen;
+ size_t epatlen;
+ size_t pat2size;
+ size_t pat2len;
+ size_t pat3size;
+ size_t pat3len;
long retval = 0;
pos_T pos;
pos_T firstpos;
@@ -10221,15 +10231,24 @@ do_searchpair(
// Make two search patterns: start/end (pat2, for in nested pairs) and
// start/middle/end (pat3, for the top pair).
- pat2 = alloc(STRLEN(spat) + STRLEN(epat) + 17);
- pat3 = alloc(STRLEN(spat) + STRLEN(mpat) + STRLEN(epat) + 25);
- if (pat2 == NULL || pat3 == NULL)
+ spatlen = STRLEN(spat);
+ epatlen = STRLEN(epat);
+ pat2size = spatlen + epatlen + 17;
+ pat2 = alloc(pat2size);
+ if (pat2 == NULL)
+ goto theend;
+ pat3size = spatlen + STRLEN(mpat) + epatlen + 25;
+ pat3 = alloc(pat3size);
+ if (pat3 == NULL)
goto theend;
- sprintf((char *)pat2, "\\m\\(%s\\m\\)\\|\\(%s\\m\\)", spat, epat);
+ pat2len = vim_snprintf((char *)pat2, pat2size, "\\m\\(%s\\m\\)\\|\\(%s\\m\\)", spat, epat);
if (*mpat == NUL)
+ {
STRCPY(pat3, pat2);
+ pat3len = pat2len;
+ }
else
- sprintf((char *)pat3, "\\m\\(%s\\m\\)\\|\\(%s\\m\\)\\|\\(%s\\m\\)",
+ pat3len = vim_snprintf((char *)pat3, pat3size, "\\m\\(%s\\m\\)\\|\\(%s\\m\\)\\|\\(%s\\m\\)",
spat, epat, mpat);
if (flags & SP_START)
options |= SEARCH_START;
@@ -10246,13 +10265,14 @@ do_searchpair(
CLEAR_POS(&firstpos);
CLEAR_POS(&foundpos);
pat = pat3;
+ patlen = pat3len;
for (;;)
{
searchit_arg_T sia;
CLEAR_FIELD(sia);
sia.sa_stop_lnum = lnum_stop;
- n = searchit(curwin, curbuf, &pos, NULL, dir, pat, 1L,
+ n = searchit(curwin, curbuf, &pos, NULL, dir, pat, patlen, 1L,
options, RE_SEARCH, &sia);
if (n == FAIL || (firstpos.lnum != 0 && EQUAL_POS(pos, firstpos)))
// didn't find it or found the first match again: FAIL
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
index 5c34e8645d..8143c24060 100644
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -3750,6 +3750,7 @@ ex_substitute(exarg_T *eap)
int save_do_all; // remember user specified 'g' flag
int save_do_ask; // remember user specified 'c' flag
char_u *pat = NULL, *sub = NULL; // init for GCC
+ size_t patlen = 0;
int delimiter;
int sublen;
int got_quit = FALSE;
@@ -3823,6 +3824,7 @@ ex_substitute(exarg_T *eap)
if (*cmd != '&')
which_pat = RE_SEARCH; // use last '/' pattern
pat = (char_u *)""; // empty search pattern
+ patlen = 0;
delimiter = *cmd++; // remember delimiter character
}
else // find the end of the regexp
@@ -3830,6 +3832,7 @@ ex_substitute(exarg_T *eap)
which_pat = RE_LAST; // use last used regexp
delimiter = *cmd++; // remember delimiter character
pat = cmd; // remember start of search pat
+ patlen = STRLEN(pat);
cmd = skip_regexp_ex(cmd, delimiter, magic_isset(),
&eap->arg, NULL, NULL);
if (cmd[0] == delimiter) // end delimiter found
@@ -3883,6 +3886,7 @@ ex_substitute(exarg_T *eap)
return;
}
pat = NULL; // search_regcomp() will use previous pattern
+ patlen = 0;
sub = vim_strsave(old_sub);
// Vi compatibility quirk: repeating with ":s" keeps the cursor in the
@@ -3929,9 +3933,9 @@ ex_substitute(exarg_T *eap)
}
if ((cmdmod.cmod_flags & CMOD_KEEPPATTERNS) == 0)
- save_re_pat(RE_SUBST, pat, magic_isset());
+ save_re_pat(RE_SUBST, pat, patlen, magic_isset());
// put pattern in history
- add_to_history(HIST_SEARCH, pat, TRUE, NUL);
+ add_to_history(HIST_SEARCH, pat, patlen, TRUE, NUL);
vim_free(sub);
return;
@@ -4066,7 +4070,7 @@ ex_substitute(exarg_T *eap)
return;
}
- if (search_regcomp(pat, NULL, RE_SUBST, which_pat, SEARCH_HIS, &regmatch) == FAIL)
+ if (search_regcomp(pat, patlen, NULL, RE_SUBST, which_pat, SEARCH_HIS, &regmatch) == FAIL)
{
if (subflags.do_error)
emsg(_(e_invalid_command));
@@ -5104,6 +5108,7 @@ ex_global(exarg_T *eap)
char_u delim; // delimiter, normally '/'
char_u *pat;
+ size_t patlen;
char_u *used_pat;
regmmatch_T regmatch;
int match;
@@ -5150,6 +5155,7 @@ ex_global(exarg_T *eap)
which_pat = RE_SEARCH; // use previous search pattern
++cmd;
pat = (char_u *)"";
+ patlen = 0;
}
else if (*cmd == NUL)
{
@@ -5165,12 +5171,13 @@ ex_global(exarg_T *eap)
delim = *cmd; // get the delimiter
++cmd; // skip delimiter if there is one
pat = cmd; // remember start of pattern
+ patlen = STRLEN(pat);
cmd = skip_regexp_ex(cmd, delim, magic_isset(), &eap->arg, NULL, NULL);
if (cmd[0] == delim) // end delimiter found
*cmd++ = NUL; // replace it with a NUL
}
- if (search_regcomp(pat, &used_pat, RE_BOTH, which_pat, SEARCH_HIS,
+ if (search_regcomp(pat, patlen, &used_pat, RE_BOTH, which_pat, SEARCH_HIS,
&regmatch) == FAIL)
{
emsg(_(e_invalid_command));
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index a588f2665e..c2aaca0656 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -4567,7 +4567,7 @@ get_address(
curwin->w_cursor.col = 0;
searchcmdlen = 0;
flags = silent ? 0 : SEARCH_HIS | SEARCH_MSG;
- if (!do_search(NULL, c, c, cmd, 1L, flags, NULL))
+ if (!do_search(NULL, c, c, cmd, STRLEN(cmd), 1L, flags, NULL))
{
curwin->w_cursor = pos;
cmd = NULL;
@@ -4621,7 +4621,7 @@ get_address(
pos.coladd = 0;
if (searchit(curwin, curbuf, &pos, NULL,
*cmd == '?' ? BACKWARD : FORWARD,
- (char_u *)"", 1L, SEARCH_MSG, i, NULL) != FAIL)
+ (char_u *)"", 0, 1L, SEARCH_MSG, i, NULL) != FAIL)
lnum = pos.lnum;
else
{
diff --git a/src/ex_getln.c b/src/ex_getln.c
index 1731d2952c..3ae4958f8e 100644
--- a/src/ex_getln.c
+++ b/src/ex_getln.c
@@ -493,7 +493,7 @@ may_do_incsearch_highlighting(
sia.sa_tm = 500;
#endif
found = do_search(NULL, firstc == ':' ? '/' : firstc, search_delim,
- ccline.cmdbuff + skiplen, count, search_flags,
+ ccline.cmdbuff + skiplen, patlen, count, search_flags,
#ifdef FEAT_RELTIME
&sia
#else
@@ -654,7 +654,7 @@ may_adjust_incsearch_highlighting(
pat[patlen] = NUL;
i = searchit(curwin, curbuf, &t, NULL,
c == Ctrl_G ? FORWARD : BACKWARD,
- pat, count, search_flags, RE_SEARCH, NULL);
+ pat, patlen, count, search_flags, RE_SEARCH, NULL);
--emsg_off;
pat[patlen] = save;
if (i)
@@ -2539,12 +2539,14 @@ returncmd:
if (ccline.cmdlen && firstc != NUL
&& (some_key_typed || histype == HIST_SEARCH))
{
- add_to_history(histype, ccline.cmdbuff, TRUE,
+ size_t cmdbufflen = STRLEN(ccline.cmdbuff);
+
+ add_to_history(histype, ccline.cmdbuff, cmdbufflen, TRUE,
histype == HIST_SEARCH ? firstc : NUL);
if (firstc == ':')
{
vim_free(new_last_cmdline);
- new_last_cmdline = vim_strsave(ccline.cmdbuff);
+ new_last_cmdline = vim_strnsave(ccline.cmdbuff, cmdbufflen);
}
}
diff --git a/src/gui.c b/src/gui.c
index 1953691021..25662ef2cb 100644
--- a/src/gui.c
+++ b/src/gui.c
@@ -5312,7 +5312,7 @@ gui_do_findrepl(
i = msg_scroll;
if (down)
{
- (void)do_search(NULL, '/', '/', ga.ga_data, 1L, searchflags, NULL);
+ (void)do_search(NULL, '/', '/', ga.ga_data, STRLEN(ga.ga_data), 1L, searchflags, NULL);
}
else
{
@@ -5320,7 +5320,7 @@ gui_do_findrepl(
// direction
p = vim_strsave_escaped(ga.ga_data, (char_u *)"?");
if (p != NULL)
- (void)do_search(NULL, '?', '?', p, 1L, searchflags, NULL);
+ (void)do_search(NULL, '?', '?', p, STRLEN(p), 1L, searchflags, NULL);
vim_free(p);
}
diff --git a/src/insexpand.c b/src/insexpand.c
index 1520d57609..c420c0ed93 100644
--- a/src/insexpand.c
+++ b/src/insexpand.c
@@ -176,6 +176,7 @@ static int ctrl_x_mode = CTRL_X_NORMAL;
static int compl_matches = 0; // number of completion matches
static char_u *compl_pattern = NULL;
+static size_t compl_patternlen = 0;
static int compl_direction = FORWARD;
static int compl_shows_dir = FORWARD;
static int compl_pending = 0; // > 1 for postponed CTRL-N
@@ -1708,6 +1709,7 @@ ins_compl_free(void)
int i;
VIM_CLEAR(compl_pattern);
+ compl_patternlen = 0;
VIM_CLEAR(compl_leader);
if (compl_first_match == NULL)
@@ -1747,6 +1749,7 @@ ins_compl_clear(void)
compl_started = FALSE;
compl_matches = 0;
VIM_CLEAR(compl_pattern);
+ compl_patternlen = 0;
VIM_CLEAR(compl_leader);
edit_submode_extra = NULL;
VIM_CLEAR(compl_orig_text);
@@ -3374,7 +3377,7 @@ done:
get_next_include_file_completion(int compl_type)
{
find_pattern_in_path(compl_pattern, compl_direction,
- (int)STRLEN(compl_pattern), FALSE, FALSE,
+ compl_patternlen, FALSE, FALSE,
(compl_type == CTRL_X_PATH_DEFINES
&& !(compl_cont_status & CONT_SOL))
? FIND_DEFINE : FIND_ANY, 1L, ACTION_EXPAND,
@@ -3478,8 +3481,7 @@ get_next_cmdline_completion(void)
int num_matches;
if (expand_cmdline(&compl_xp, compl_pattern,
- (int)STRLEN(compl_pattern),
- &num_matches, &matches) == EXPAND_OK)
+ compl_patternlen, &num_matches, &matches) == EXPAND_OK)
ins_compl_add_matches(num_matches, matches, FALSE);
}
@@ -3644,8 +3646,8 @@ get_next_default_completion(ins_compl_next_state_T *st, pos_T *start_pos)
st->cur_match_pos, compl_direction, compl_pattern);
else
found_new_match = searchit(NULL, st->ins_buf, st->cur_match_pos,
- NULL, compl_direction, compl_pattern, 1L,
- SEARCH_KEEP + SEARCH_NFMSG, RE_LAST, NULL);
+ NULL, compl_direction, compl_pattern, compl_patternlen,
+ 1L, SEARCH_KEEP + SEARCH_NFMSG, RE_LAST, NULL);
--msg_silent;
if (!compl_started || st->set_match_pos)
{
@@ -4383,7 +4385,8 @@ ins_compl_use_match(int c)
/*
* Get the pattern, column and length for normal completion (CTRL-N CTRL-P
* completion)
- * Sets the global variables: compl_col, compl_length and compl_pattern.
+ * Sets the global variables: compl_col, compl_length, compl_pattern and
+ * compl_patternlen.
* Uses the global variables: compl_cont_status and ctrl_x_mode
*/
static int
@@ -4404,32 +4407,45 @@ get_normal_compl_info(char_u *line, int startcol, colnr_T curs_col)
else
compl_pattern = vim_strnsave(line + compl_col, compl_length);
if (compl_pattern == NULL)
+ {
+ compl_patternlen = 0;
return FAIL;
+ }
}
else if (compl_status_adding())
{
char_u *prefix = (char_u *)"\\<";
+ size_t prefixlen = STRLEN_LITERAL("\\<");
// we need up to 2 extra chars for the prefix
compl_pattern = alloc(quote_meta(NULL, line + compl_col,
- compl_length) + 2);
+ compl_length) + prefixlen);
if (compl_pattern == NULL)
+ {
+ compl_patternlen = 0;
return FAIL;
+ }
if (!vim_iswordp(line + compl_col)
|| (compl_col > 0
&& (vim_iswordp(mb_prevptr(line, line + compl_col)))))
+ {
prefix = (char_u *)"";
+ prefixlen = 0;
+ }
STRCPY((char *)compl_pattern, prefix);
- (void)quote_meta(compl_pattern + STRLEN(prefix),
+ (void)quote_meta(compl_pattern + prefixlen,
line + compl_col, compl_length);
}
else if (--startcol < 0
|| !vim_iswordp(mb_prevptr(line, line + startcol + 1)))
{
// Match any word of at least two chars
- compl_pattern = vim_strsave((char_u *)"\\<\\k\\k");
+ compl_pattern = vim_strnsave((char_u *)"\\<\\k\\k", STRLEN_LITERAL("\\<\\k\\k"));
if (compl_pattern == NULL)
+ {
+ compl_patternlen = 0;
return FAIL;
+ }
compl_col += curs_col;
compl_length = 0;
}
@@ -4465,7 +4481,10 @@ get_normal_compl_info(char_u *line, int startcol, colnr_T curs_col)
// alloc(7) is enough -- Acevedo
compl_pattern = alloc(7);
if (compl_pattern == NULL)
+ {
+ compl_patternlen = 0;
return FAIL;
+ }
STRCPY((char *)compl_pattern, "\\<");
(void)quote_meta(compl_pattern + 2, line + compl_col, 1);
STRCAT((char *)compl_pattern, "\\k");
@@ -4475,13 +4494,18 @@ get_normal_compl_info(char_u *line, int startcol, colnr_T curs_col)
compl_pattern = alloc(quote_meta(NULL, line + compl_col,
compl_length) + 2);
if (compl_pattern == NULL)
+ {
+ compl_patternlen = 0;
return FAIL;
+ }
STRCPY((char *)compl_pattern, "\\<");
(void)quote_meta(compl_pattern + 2, line + compl_col,
compl_length);
}
}
+ compl_patternlen = STRLEN(compl_pattern);
+
return OK;
}
@@ -4503,7 +4527,12 @@ get_wholeline_compl_info(char_u *line, colnr_T curs_col)
else
compl_pattern = vim_strnsave(line + compl_col, compl_length);
if (compl_pattern == NULL)
+ {
+ compl_patternlen = 0;
return FAIL;
+ }
+
+ compl_patternlen = STRLEN(compl_pattern);
return OK;
}
@@ -4533,7 +4562,12 @@ get_filename_compl_info(char_u *line, int startcol, colnr_T curs_col)
compl_length = (int)curs_col - startcol;
compl_pattern = addstar(line + compl_col, compl_length, EXPAND_FILES);
if (compl_pattern == NULL)
+ {
+ compl_patternlen = 0;
return FAIL;
+ }
+
+ compl_patternlen = STRLEN(compl_pattern);
return OK;
}
@@ -4547,9 +4581,13 @@ get_cmdline_compl_info(char_u *line, colnr_T curs_col)
{
compl_pattern = vim_strnsave(line, curs_col);
if (compl_pattern == NULL)
+ {
+ compl_patternlen = 0;
return FAIL;
+ }
+ compl_patternlen = curs_col;
set_cmd_context(&compl_xp, compl_pattern,
- (int)STRLEN(compl_pattern), curs_col, FALSE);
+ compl_patternlen, curs_col, FALSE);
if (compl_xp.xp_context == EXPAND_UNSUCCESSFUL
|| compl_xp.xp_context == EXPAND_NOTHING)
// No completion possible, use an empty pattern to get a
@@ -4647,8 +4685,12 @@ get_userdefined_compl_info(colnr_T curs_col UNUSED)
compl_length = curs_col - compl_col;
compl_pattern = vim_strnsave(line + compl_col, compl_length);
if (compl_pattern == NULL)
+ {
+ compl_patternlen = 0;
return FAIL;
+ }
+ compl_patternlen = compl_length;
ret = OK;
#endif
@@ -4685,8 +4727,12 @@ get_spell_compl_info(int startcol UNUSED, colnr_T curs_col UNUSED)
line = ml_get(curwin->w_cursor.lnum);
compl_pattern = vim_strnsave(line + compl_col, compl_length);
if (compl_pattern == NULL)
+ {
+ compl_patternlen = 0;
return FAIL;
+ }
+ compl_patternlen = compl_length;
ret = OK;
#endif
@@ -4907,6 +4953,7 @@ ins_compl_start(void)
-1, NULL, NULL, NULL, 0, flags, FALSE) != OK)
{
VIM_CLEAR(compl_pattern);
+ compl_patternlen = 0;
VIM_CLEAR(compl_orig_text);
return FAIL;
}
diff --git a/src/normal.c b/src/normal.c
index 580eb72298..38c6bad80f 100644
--- a/src/normal.c
+++ b/src/normal.c
@@ -61,7 +61,7 @@ static void nv_end(cmdarg_T *cap);
static void nv_dollar(cmdarg_T *cap);
static void nv_search(cmdarg_T *cap);
static void nv_next(cmdarg_T *cap);
-static int normal_search(cmdarg_T *cap, int dir, char_u *pat, int opt, int *wrapped);
+static int normal_search(cmdarg_T *cap, int dir, char_u *pat, size_t patlen, int opt, int *wrapped);
static void nv_csearch(cmdarg_T *cap);
static void nv_brackets(cmdarg_T *cap);
static void nv_percent(cmdarg_T *cap);
@@ -2169,6 +2169,7 @@ find_decl(
int flags_arg) // flags passed to searchit()
{
char_u *pat;
+ size_t patlen;
pos_T old_pos;
pos_T par_pos;
pos_T found_pos;
@@ -2185,8 +2186,9 @@ find_decl(
// Put "\V" before the pattern to avoid that the special meaning of "."
// and "~" causes trouble.
- sprintf((char *)pat, vim_iswordp(ptr) ? "\\V\\<%.*s\\>" : "\\V%.*s",
- len, ptr);
+ patlen = vim_snprintf((char *)pat, len + 7,
+ vim_iswordp(ptr) ? "\\V\\<%.*s\\>" : "\\V%.*s", len, ptr);
+
old_pos = curwin->w_cursor;
save_p_ws = p_ws;
save_p_scs = p_scs;
@@ -2215,7 +2217,7 @@ find_decl(
for (;;)
{
t = searchit(curwin, curbuf, &curwin->w_cursor, NULL, FORWARD,
- pat, 1L, searchflags, RE_LAST, NULL);
+ pat, patlen, 1L, searchflags, RE_LAST, NULL);
if (curwin->w_cursor.lnum >= old_pos.lnum)
t = FAIL; // match after start is failure too
@@ -3332,7 +3334,8 @@ nv_K_getcmd(
char_u **ptr_arg,
int n,
char_u *buf,
- unsigned buflen)
+ size_t bufsize,
+ size_t *buflen)
{
char_u *ptr = *ptr_arg;
int isman;
@@ -3342,6 +3345,7 @@ nv_K_getcmd(
{
// in the help buffer
STRCPY(buf, "he! ");
+ *buflen = STRLEN_LITERAL("he! ");
return n;
}
@@ -3349,10 +3353,9 @@ nv_K_getcmd(
{
// 'keywordprog' is an ex command
if (cap->count0 != 0)
- vim_snprintf((char *)buf, buflen, "%s %ld", kp, cap->count0);
+ *buflen = vim_snprintf((char *)buf, bufsize, "%s %ld ", kp, cap->count0);
else
- STRCPY(buf, kp);
- STRCAT(buf, " ");
+ *buflen = vim_snprintf((char *)buf, bufsize, "%s ", kp);
return n;
}
@@ -3377,19 +3380,16 @@ nv_K_getcmd(
isman = (STRCMP(kp, "man") == 0);
isman_s = (STRCMP(kp, "man -s") == 0);
if (cap->count0 != 0 && !(isman || isman_s))
- sprintf((char *)buf, ".,.+%ld", cap->count0 - 1);
+ *buflen = vim_snprintf((char *)buf, bufsize, ".,.+%ld! ", cap->count0 - 1);
+ else
+ *buflen = vim_snprintf((char *)buf, bufsize, "! ");
- STRCAT(buf, "! ");
if (cap->count0 == 0 && isman_s)
- STRCAT(buf, "man");
+ *buflen += vim_snprintf((char *)buf + *buflen, bufsize - *buflen, "man ");
else
- STRCAT(buf, kp);
- STRCAT(buf, " ");
+ *buflen += vim_snprintf((char *)buf + *buflen, bufsize - *buflen, "%s ", kp);
if (cap->count0 != 0 && (isman || isman_s))
- {
- sprintf((char *)buf + STRLEN(buf), "%ld", cap->count0);
- STRCAT(buf, " ");
- }
+ *buflen += vim_snprintf((char *)buf + *buflen, bufsize - *buflen, "%ld ", cap->count0);
*ptr_arg = ptr;
return n;
@@ -3408,7 +3408,8 @@ nv_ident(cmdarg_T *cap)
{
char_u *ptr = NULL;
char_u *buf;
- unsigned buflen;
+ size_t bufsize;
+ size_t buflen;
char_u *newbuf;
char_u *p;
char_u *kp; // value of 'keywordprg'
@@ -3463,11 +3464,12 @@ nv_ident(cmdarg_T *cap)
return;
}
kp_ex = (*kp == ':');
- buflen = (unsigned)(n * 2 + 30 + STRLEN(kp));
- buf = alloc(buflen);
+ bufsize = (size_t)(n * 2 + 30 + STRLEN(kp));
+ buf = alloc(bufsize);
if (buf == NULL)
return;
buf[0] = NUL;
+ buflen = 0;
switch (cmdchar)
{
@@ -3481,12 +3483,15 @@ nv_ident(cmdarg_T *cap)
curwin->w_cursor.col = (colnr_T) (ptr - ml_get_curline());
if (!g_cmd && vim_iswordp(ptr))
+ {
STRCPY(buf, "\\<");
+ buflen = STRLEN_LITERAL("\\<");
+ }
no_smartcase = TRUE; // don't use 'smartcase' now
break;
case 'K':
- n = nv_K_getcmd(cap, kp, kp_help, kp_ex, &ptr, n, buf, buflen);
+ n = nv_K_getcmd(cap, kp, kp_help, kp_ex, &ptr, n, buf, bufsize, &buflen);
if (n == 0)
return;
break;
@@ -3495,30 +3500,47 @@ nv_ident(cmdarg_T *cap)
tag_cmd = TRUE;
#ifdef FEAT_CSCOPE
if (p_cst)
+ {
STRCPY(buf, "cstag ");
+ buflen = STRLEN_LITERAL("cstag ");
+ }
else
#endif
+ {
STRCPY(buf, "ts ");
+ buflen = STRLEN_LITERAL("ts ");
+ }
break;
default:
tag_cmd = TRUE;
if (curbuf->b_help)
+ {
STRCPY(buf, "he! ");
+ buflen = STRLEN_LITERAL("he! ");
+ }
else
{
if (g_cmd)
+ {
STRCPY(buf, "tj ");
+ buflen = STRLEN_LITERAL("tj ");
+ }
else if (cap->count0 == 0)
+ {
STRCPY(buf, "ta ");
+ buflen = STRLEN_LITERAL("ta ");
+ }
else
- sprintf((char *)buf, ":%ldta ", cap->count0);
+ buflen = vim_snprintf((char *)buf, bufsize, ":%ldta ", cap->count0);
}
}
// Now grab the chars in the identifier
if (cmdchar == 'K' && !kp_help)
{
+ size_t plen;
+
ptr = vim_strnsave(ptr, n);
if (kp_ex)
// Escape the argument properly for an Ex command
@@ -3532,7 +3554,8 @@ nv_ident(cmdarg_T *cap)
vim_free(buf);
return;
}
- newbuf = vim_realloc(buf, STRLEN(buf) + STRLEN(p) + 1);
+ plen = STRLEN(p);
+ newbuf = vim_realloc(buf, buflen + plen + 1);
if (newbuf == NULL)
{
vim_free(buf);
@@ -3540,7 +3563,8 @@ nv_ident(cmdarg_T *cap)
return;
}
buf = newbuf;
- STRCAT(buf, p);
+ STRCPY(buf + buflen, p);
+ buflen += plen;
vim_free(p);
}
else
@@ -3560,12 +3584,13 @@ nv_ident(cmdarg_T *cap)
else
aux_ptr = (char_u *)"\\|\"\n*?[";
- p = buf + STRLEN(buf);
+ p = buf + buflen;
while (n-- > 0)
{
// put a backslash before \ and some others
if (vim_strchr(aux_ptr, *ptr) != NULL)
*p++ = '\\';
+
// When current byte is a part of multibyte character, copy all
// bytes of that character.
if (has_mbyte)
@@ -3579,6 +3604,7 @@ nv_ident(cmdarg_T *cap)
*p++ = *ptr++;
}
*p = NUL;
+ buflen = p - buf;
}
// Execute the command.
@@ -3587,13 +3613,16 @@ nv_ident(cmdarg_T *cap)
if (!g_cmd && (has_mbyte
? vim_iswordp(mb_prevptr(ml_get_curline(), ptr))
: vim_iswordc(ptr[-1])))
- STRCAT(buf, "\\>");
+ {
+ STRCPY(buf + buflen, "\\>");
+ buflen += STRLEN_LITERAL("\\>");
+ }
// put pattern in search history
init_history();
- add_to_history(HIST_SEARCH, buf, TRUE, NUL);
+ add_to_history(HIST_SEARCH, buf, buflen, TRUE, NUL);
- (void)normal_search(cap, cmdchar == '*' ? '/' : '?', buf, 0, NULL);
+ (void)normal_search(cap, cmdchar == '*' ? '/' : '?', buf, buflen, 0, NULL);
}
else
{
@@ -4117,7 +4146,7 @@ nv_search(cmdarg_T *cap)
return;
}
- (void)normal_search(cap, cap->cmdchar, cap->searchbuf,
+ (void)normal_search(cap, cap->cmdchar, cap->searchbuf, STRLEN(cap->searchbuf),
(cap->arg || !EQUAL_POS(save_cursor, curwin->w_cursor))
? 0 : SEARCH_MARK, NULL);
}
@@ -4132,7 +4161,7 @@ nv_next(cmdarg_T *cap)
{
pos_T old = curwin->w_cursor;
int wrapped = FALSE;
- int i = normal_search(cap, 0, NULL, SEARCH_MARK | cap->arg, &wrapped);
+ int i = normal_search(cap, 0, NULL, 0, SEARCH_MARK | cap->arg, &wrapped);
if (i == 1 && !wrapped && EQUAL_POS(old, curwin->w_cursor))
{
@@ -4140,7 +4169,7 @@ nv_next(cmdarg_T *cap)
// happen when an offset is given and the cursor is on the last char
// in the buffer: Repeat with count + 1.
cap->count1 += 1;
- (void)normal_search(cap, 0, NULL, SEARCH_MARK | cap->arg, NULL);
+ (void)normal_search(cap, 0, NULL, 0, SEARCH_MARK | cap->arg, NULL);
cap->count1 -= 1;
}
@@ -4161,6 +4190,7 @@ normal_search(
cmdarg_T *cap,
int dir,
char_u *pat,
+ size_t patlen,
int opt, // extra flags for do_search()
int *wrapped)
{
@@ -4176,7 +4206,7 @@ normal_search(
curwin->w_set_curswant = TRUE;
CLEAR_FIELD(sia);
- i = do_search(cap->oap, dir, dir, pat, cap->count1,
+ i = do_search(cap->oap, dir, dir, pat, patlen, cap->count1,
opt | SEARCH_OPT | SEARCH_ECHO | SEARCH_MSG, &sia);
if (wrapped != NULL)
*wrapped = sia.sa_wrapped;
@@ -4201,6 +4231,7 @@ normal_search(
// "/$" will put the cursor after the end of the line, may need to
// correct that here
check_cursor();
+
return i;
}
diff --git a/src/proto/cmdhist.pro b/src/proto/cmdhist.pro
index 9c9e56c075..5bf4b8da44 100644
--- a/src/proto/cmdhist.pro
+++ b/src/proto/cmdhist.pro
@@ -9,7 +9,7 @@ char_u *get_history_arg(expand_T *xp, int idx);
void init_history(void);
void clear_hist_entry(histentry_T *hisptr);
int in_history(int type, char_u *str, int move_to_front, int sep, int writing);
-void add_to_history(int histype, char_u *new_entry, int in_map, int sep);
+void add_to_history(int histype, char_u *new_entry, size_t new_entrylen, int in_map, int sep);
void f_histadd(typval_T *argvars, typval_T *rettv);
void f_histdel(typval_T *argvars, typval_T *rettv);
void f_histget(typval_T *argvars, typval_T *rettv);
diff --git a/src/proto/search.pro b/src/proto/search.pro
index 5b2b889317..d9cb16aa84 100644
--- a/src/proto/search.pro
+++ b/src/proto/search.pro
@@ -1,7 +1,7 @@
/* search.c */
-int search_regcomp(char_u *pat, char_u **used_pat, int pat_save, int pat_use, int options, regmmatch_T *regmatch);
+int search_regcomp(char_u *pat, size_t patlen, char_u **used_pat, int pat_save, int pat_use, int options, regmmatch_T *regmatch);
char_u *get_search_pat(void);
-void save_re_pat(int idx, char_u *pat, int magic);
+void save_re_pat(int idx, char_u *pat, size_t patlen, int magic);
void save_search_patterns(void);
void restore_search_patterns(void);
void free_search_patterns(void);
@@ -21,9 +21,9 @@ char_u *last_search_pat(void);
void reset_search_dir(void);
void set_last_search_pat(char_u *s, int idx, int magic, int setlast);
void last_pat_prog(regmmatch_T *regmatch);
-int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, int dir, char_u *pat, long count, int options, int pat_use, searchit_arg_T *extra_arg);
+int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, int dir, char_u *pat, size_t patlen, long count, int options, int pat_use, searchit_arg_T *extra_arg);
void set_search_direction(int cdir);
-int do_search(oparg_T *oap, int dirc, int search_delim, char_u *pat, long count, int options, searchit_arg_T *sia);
+int do_search(oparg_T *oap, int dirc, int search_delim, char_u *pat, size_t patlen, long count, int options, searchit_arg_T *sia);
int search_for_exact_line(buf_T *buf, pos_T *pos, int dir, char_u *pat);
int searchc(cmdarg_T *cap, int t_cmd);
pos_T *findmatch(oparg_T *oap, int initc);
diff --git a/src/quickfix.c b/src/quickfix.c
index 660622fc50..414fe650d7 100644
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -3388,7 +3388,7 @@ qf_jump_goto_line(
// Move the cursor to the first line in the buffer
save_cursor = curwin->w_cursor;
curwin->w_cursor.lnum = 0;
- if (!do_search(NULL, '/', '/', qf_pattern, (long)1, SEARCH_KEEP, NULL))
+ if (!do_search(NULL, '/', '/', qf_pattern, STRLEN(qf_pattern), (long)1, SEARCH_KEEP, NULL))
curwin->w_cursor = save_cursor;
}
}
diff --git a/src/search.c b/src/search.c
index 166ef4a580..43c40e03d5 100644
--- a/src/search.c
+++ b/src/search.c
@@ -17,8 +17,8 @@ static void set_vv_searchforward(void);
static int first_submatch(regmmatch_T *rp);
#endif
#ifdef FEAT_FIND_ID
-static void show_pat_in_path(char_u *, int,
- int, int, FILE *, linenr_T *, long);
+static char_u *get_line_and_copy(linenr_T lnum, char_u *buf);
+static void show_pat_in_path(char_u *, int, int, int, FILE *, linenr_T *, long);
#endif
typedef struct searchstat
@@ -32,8 +32,27 @@ typedef struct searchstat
int last_maxcount; // the max count of the last search
} searchstat_T;
-static void cmdline_search_stat(int dirc, pos_T *pos, pos_T *cursor_pos, int show_top_bot_msg, char_u *msgbuf, int recompute, int maxcount, long timeout);
+#ifdef FEAT_SEARCH_EXTRA
+static void save_incsearch_state(void);
+static void restore_incsearch_state(void);
+#endif
+static int check_prevcol(char_u *linep, int col, int ch, int *prevcol);
+static int find_rawstring_end(char_u *linep, pos_T *startpos, pos_T *endpos);
+static void find_mps_values(int *initc, int *findc, int *backwards, int switchit);
+static int is_zero_width(char_u *pattern, size_t patternlen, int move, pos_T *cur, int direction);
+static void cmdline_search_stat(int dirc, pos_T *pos, pos_T *cursor_pos, int show_top_bot_msg, char_u *msgbuf, size_t msgbuflen, int recompute, int maxcount, long timeout);
static void update_search_stat(int dirc, pos_T *pos, pos_T *cursor_pos, searchstat_T *stat, int recompute, int maxcount, long timeout);
+static int fuzzy_match_compute_score(char_u *str, int strSz, int_u *matches, int numMatches);
+static int fuzzy_match_recursive(char_u *fuzpat, char_u *str, int_u strIdx, int *outScore, char_u *strBegin, int strLen, int_u *srcMatches, int_u *matches, int maxMatches, int nextMatch, int *recursionCount);
+#if defined(FEAT_EVAL) || defined(FEAT_PROTO)
+static int fuzzy_match_item_compare(const void *s1, const void *s2);
+static void fuzzy_match_in_list(list_T *l, char_u *str, int matchseq, char_u *key, callback_T *item_cb, int retmatchpos, list_T *fmatchlist, long max_matches);
+static void do_fuzzymatch(typval_T *argvars, typval_T *rettv, int retmatchpos);
+#endif
+static int fuzzy_match_str_compare(const void *s1, const void *s2);
+static void fuzzy_match_str_sort(fuzmatch_str_T *fm, int sz);
+static int fuzzy_match_func_compare(const void *s1, const void *s2);
+static void fuzzy_match_func_sort(fuzmatch_str_T *fm, int sz);
#define SEARCH_STAT_DEF_TIMEOUT 40L
#define SEARCH_STAT_DEF_MAX_COUNT 99
@@ -6