aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2024-05-21 06:22:23 +0800
committerzeertzjq <zeertzjq@outlook.com>2024-05-22 06:37:26 +0800
commitb86381f425223adf0ff91fa0746914a5774ddabb (patch)
tree3a954980956a6ac250fc2e1a875802d5057bddde /src
parent879d17ea8d62c199ea0c91c5f37a4f25495be7ce (diff)
downloadrneovim-b86381f425223adf0ff91fa0746914a5774ddabb.tar.gz
rneovim-b86381f425223adf0ff91fa0746914a5774ddabb.tar.bz2
rneovim-b86381f425223adf0ff91fa0746914a5774ddabb.zip
vim-patch:9.1.0426: too many strlen() calls in search.c
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: vim/vim#14796 https://github.com/vim/vim/commit/8c85a2a49acf80e4f53ec51e6ff2a5f3830eeddb Co-authored-by: John Marriott <basilisk@internode.on.net>
Diffstat (limited to 'src')
-rw-r--r--src/nvim/cmdhist.c9
-rw-r--r--src/nvim/eval/funcs.c27
-rw-r--r--src/nvim/ex_cmds.c22
-rw-r--r--src/nvim/ex_docmd.c4
-rw-r--r--src/nvim/ex_getln.c9
-rw-r--r--src/nvim/insexpand.c36
-rw-r--r--src/nvim/normal.c80
-rw-r--r--src/nvim/quickfix.c2
-rw-r--r--src/nvim/search.c250
-rw-r--r--src/nvim/search.h1
-rw-r--r--src/nvim/spell.c8
-rw-r--r--src/nvim/tag.c18
12 files changed, 275 insertions, 191 deletions
diff --git a/src/nvim/cmdhist.c b/src/nvim/cmdhist.c
index 6a9290270a..eb1658aa1f 100644
--- a/src/nvim/cmdhist.c
+++ b/src/nvim/cmdhist.c
@@ -294,7 +294,7 @@ static int last_maptick = -1; // last seen maptick
/// @param histype may be one of the HIST_ values.
/// @param in_map consider maptick when inside a mapping
/// @param sep separator character used (search hist)
-void add_to_history(int histype, const char *new_entry, int in_map, int sep)
+void add_to_history(int histype, const char *new_entry, size_t new_entrylen, bool in_map, int sep)
{
histentry_T *hisptr;
@@ -334,11 +334,10 @@ void add_to_history(int histype, const char *new_entry, int in_map, int sep)
hist_free_entry(hisptr);
// Store the separator after the NUL of the string.
- size_t len = strlen(new_entry);
- hisptr->hisstr = xstrnsave(new_entry, len + 2);
+ hisptr->hisstr = xstrnsave(new_entry, new_entrylen + 2);
hisptr->timestamp = os_time();
hisptr->additional_elements = NULL;
- hisptr->hisstr[len + 1] = (char)sep;
+ hisptr->hisstr[new_entrylen + 1] = (char)sep;
hisptr->hisnum = ++hisnum[histype];
if (histype == HIST_SEARCH && in_map) {
@@ -536,7 +535,7 @@ void f_histadd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
}
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/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index 0240e08dad..1d01f3ad98 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -7076,12 +7076,13 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp)
.sa_tm = &tm,
};
+ const size_t patlen = strlen(pat);
int subpatnum;
// Repeat until {skip} returns false.
while (true) {
- subpatnum
- = searchit(curwin, curbuf, &pos, NULL, dir, (char *)pat, 1, options, RE_SEARCH, &sia);
+ subpatnum = searchit(curwin, curbuf, &pos, NULL, dir, (char *)pat, patlen, 1,
+ options, RE_SEARCH, &sia);
// finding the first match again means there is no match where {skip}
// evaluates to zero.
if (firstpos.lnum != 0 && equalpos(pos, firstpos)) {
@@ -7636,16 +7637,20 @@ int do_searchpair(const char *spat, const char *mpat, const char *epat, int dir,
// Make two search patterns: start/end (pat2, for in nested pairs) and
// start/middle/end (pat3, for the top pair).
- const size_t pat2_len = strlen(spat) + strlen(epat) + 17;
- char *pat2 = xmalloc(pat2_len);
- const size_t pat3_len = strlen(spat) + strlen(mpat) + strlen(epat) + 25;
- char *pat3 = xmalloc(pat3_len);
- snprintf(pat2, pat2_len, "\\m\\(%s\\m\\)\\|\\(%s\\m\\)", spat, epat);
+ const size_t spatlen = strlen(spat);
+ const size_t epatlen = strlen(epat);
+ const size_t pat2size = spatlen + epatlen + 17;
+ char *pat2 = xmalloc(pat2size);
+ const size_t pat3size = spatlen + strlen(mpat) + epatlen + 25;
+ char *pat3 = xmalloc(pat3size);
+ int pat2len = snprintf(pat2, pat2size, "\\m\\(%s\\m\\)\\|\\(%s\\m\\)", spat, epat);
+ int pat3len;
if (*mpat == NUL) {
STRCPY(pat3, pat2);
+ pat3len = pat2len;
} else {
- snprintf(pat3, pat3_len,
- "\\m\\(%s\\m\\)\\|\\(%s\\m\\)\\|\\(%s\\m\\)", spat, epat, mpat);
+ pat3len = snprintf(pat3, pat3size,
+ "\\m\\(%s\\m\\)\\|\\(%s\\m\\)\\|\\(%s\\m\\)", spat, epat, mpat);
}
if (flags & SP_START) {
options |= SEARCH_START;
@@ -7662,13 +7667,15 @@ int do_searchpair(const char *spat, const char *mpat, const char *epat, int dir,
pos_T foundpos;
clearpos(&foundpos);
char *pat = pat3;
+ assert(pat3len >= 0);
+ size_t patlen = (size_t)pat3len;
while (true) {
searchit_arg_T sia = {
.sa_stop_lnum = lnum_stop,
.sa_tm = &tm,
};
- int n = searchit(curwin, curbuf, &pos, NULL, dir, pat, 1,
+ int n = searchit(curwin, curbuf, &pos, NULL, dir, pat, patlen, 1,
options, RE_SEARCH, &sia);
if (n == FAIL || (firstpos.lnum != 0 && equalpos(pos, firstpos))) {
// didn't find it or found the first match again: FAIL
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 55d94e165a..834cc6698a 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -3099,8 +3099,9 @@ void sub_set_replacement(SubReplacementString sub)
/// @param[in] save Save pattern to options, history
///
/// @returns true if :substitute can be replaced with a join command
-static bool sub_joining_lines(exarg_T *eap, char *pat, const char *sub, const char *cmd, bool save)
- FUNC_ATTR_NONNULL_ARG(1, 3, 4)
+static bool sub_joining_lines(exarg_T *eap, char *pat, size_t patlen, const char *sub,
+ const char *cmd, bool save)
+ FUNC_ATTR_NONNULL_ARG(1, 4, 5)
{
// TODO(vim): find a generic solution to make line-joining operations more
// efficient, avoid allocating a string that grows in size.
@@ -3138,10 +3139,10 @@ static bool sub_joining_lines(exarg_T *eap, char *pat, const char *sub, const ch
if (save) {
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);
}
return true;
@@ -3332,6 +3333,7 @@ static int do_sub(exarg_T *eap, const proftime_T timeout, const int cmdpreview_n
};
char *pat = NULL;
char *sub = NULL; // init for GCC
+ size_t patlen = 0;
int delimiter;
bool has_second_delim = false;
int sublen;
@@ -3383,12 +3385,14 @@ static int do_sub(exarg_T *eap, const proftime_T timeout, const int cmdpreview_n
which_pat = RE_SEARCH; // use last '/' pattern
}
pat = ""; // empty search pattern
+ patlen = 0;
delimiter = (uint8_t)(*cmd++); // remember delimiter character
has_second_delim = true;
} else { // find the end of the regexp
which_pat = RE_LAST; // use last used regexp
delimiter = (uint8_t)(*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
*cmd++ = NUL; // replace it with a NUL
@@ -3415,6 +3419,7 @@ static int do_sub(exarg_T *eap, const proftime_T timeout, const int cmdpreview_n
return 0;
}
pat = NULL; // search_regcomp() will use previous pattern
+ patlen = 0;
sub = xstrdup(old_sub.sub);
// Vi compatibility quirk: repeating with ":s" keeps the cursor in the
@@ -3422,7 +3427,7 @@ static int do_sub(exarg_T *eap, const proftime_T timeout, const int cmdpreview_n
endcolumn = (curwin->w_curswant == MAXCOL);
}
- if (sub != NULL && sub_joining_lines(eap, pat, sub, cmd, cmdpreview_ns <= 0)) {
+ if (sub != NULL && sub_joining_lines(eap, pat, patlen, sub, cmd, cmdpreview_ns <= 0)) {
xfree(sub);
return 0;
}
@@ -3477,7 +3482,7 @@ static int do_sub(exarg_T *eap, const proftime_T timeout, const int cmdpreview_n
return 0;
}
- if (search_regcomp(pat, NULL, RE_SUBST, which_pat,
+ if (search_regcomp(pat, patlen, NULL, RE_SUBST, which_pat,
(cmdpreview_ns > 0 ? 0 : SEARCH_HIS), &regmatch) == FAIL) {
if (subflags.do_error) {
emsg(_(e_invcmd));
@@ -4390,6 +4395,7 @@ void ex_global(exarg_T *eap)
char delim; // delimiter, normally '/'
char *pat;
+ size_t patlen;
regmmatch_T regmatch;
// When nesting the command works on one line. This allows for
@@ -4425,6 +4431,7 @@ void ex_global(exarg_T *eap)
}
cmd++;
pat = "";
+ patlen = 0;
} else if (*cmd == NUL) {
emsg(_("E148: Regular expression missing from global"));
return;
@@ -4434,6 +4441,7 @@ void 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
@@ -4441,7 +4449,7 @@ void ex_global(exarg_T *eap)
}
char *used_pat;
- if (search_regcomp(pat, &used_pat, RE_BOTH, which_pat,
+ if (search_regcomp(pat, patlen, &used_pat, RE_BOTH, which_pat,
SEARCH_HIS, &regmatch) == FAIL) {
emsg(_(e_invcmd));
return;
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index fb4acaec04..1fcfc505df 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -3506,7 +3506,7 @@ static linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, bool
}
searchcmdlen = 0;
flags = silent ? 0 : SEARCH_HIS | SEARCH_MSG;
- if (!do_search(NULL, c, c, cmd, 1, flags, NULL)) {
+ if (!do_search(NULL, c, c, cmd, strlen(cmd), 1, flags, NULL)) {
curwin->w_cursor = pos;
cmd = NULL;
goto error;
@@ -3543,7 +3543,7 @@ static linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, bool
pos.coladd = 0;
if (searchit(curwin, curbuf, &pos, NULL,
*cmd == '?' ? BACKWARD : FORWARD,
- "", 1, SEARCH_MSG, i, NULL) != FAIL) {
+ "", 0, 1, SEARCH_MSG, i, NULL) != FAIL) {
lnum = pos.lnum;
} else {
cmd = NULL;
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 8c9e6e454a..f18dc0f747 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -470,7 +470,7 @@ static void may_do_incsearch_highlighting(int firstc, int count, incsearch_state
.sa_tm = &tm,
};
found = do_search(NULL, firstc == ':' ? '/' : firstc, search_delim,
- ccline.cmdbuff + skiplen, count,
+ ccline.cmdbuff + skiplen, (size_t)patlen, count,
search_flags, &sia);
ccline.cmdbuff[skiplen + patlen] = next_char;
emsg_off--;
@@ -884,11 +884,12 @@ static uint8_t *command_line_enter(int firstc, int count, int indent, bool clear
&& ccline.cmdlen
&& s->firstc != NUL
&& (s->some_key_typed || s->histype == HIST_SEARCH)) {
- add_to_history(s->histype, ccline.cmdbuff, true,
+ size_t cmdbufflen = strlen(ccline.cmdbuff);
+ add_to_history(s->histype, ccline.cmdbuff, cmdbufflen, true,
s->histype == HIST_SEARCH ? s->firstc : NUL);
if (s->firstc == ':') {
xfree(new_last_cmdline);
- new_last_cmdline = xstrdup(ccline.cmdbuff);
+ new_last_cmdline = xstrnsave(ccline.cmdbuff, cmdbufflen);
}
}
@@ -1451,7 +1452,7 @@ static int may_do_command_line_next_incsearch(int firstc, int count, incsearch_s
pat[patlen] = NUL;
int found = searchit(curwin, curbuf, &t, NULL,
next_match ? FORWARD : BACKWARD,
- pat, count, search_flags,
+ pat, (size_t)patlen, count, search_flags,
RE_SEARCH, NULL);
emsg_off--;
pat[patlen] = save;
diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c
index c51b3b916d..cec1e4a9e3 100644
--- a/src/nvim/insexpand.c
+++ b/src/nvim/insexpand.c
@@ -253,6 +253,7 @@ static int ctrl_x_mode = CTRL_X_NORMAL;
static int compl_matches = 0; ///< number of completion matches
static char *compl_pattern = NULL;
+static size_t compl_patternlen = 0;
static Direction compl_direction = FORWARD;
static Direction compl_shows_dir = FORWARD;
static int compl_pending = 0; ///< > 1 for postponed CTRL-N
@@ -1583,6 +1584,7 @@ static char *find_line_end(char *ptr)
static void ins_compl_free(void)
{
XFREE_CLEAR(compl_pattern);
+ compl_patternlen = 0;
XFREE_CLEAR(compl_leader);
if (compl_first_match == NULL) {
@@ -1617,6 +1619,7 @@ void ins_compl_clear(void)
compl_started = false;
compl_matches = 0;
XFREE_CLEAR(compl_pattern);
+ compl_patternlen = 0;
XFREE_CLEAR(compl_leader);
edit_submode_extra = NULL;
kv_destroy(compl_orig_extmarks);
@@ -2991,7 +2994,7 @@ done:
static void get_next_include_file_completion(int compl_type)
{
find_pattern_in_path(compl_pattern, compl_direction,
- strlen(compl_pattern), false, false,
+ compl_patternlen, false, false,
((compl_type == CTRL_X_PATH_DEFINES
&& !(compl_cont_status & CONT_SOL))
? FIND_DEFINE : FIND_ANY),
@@ -3074,8 +3077,7 @@ static void get_next_cmdline_completion(void)
char **matches;
int num_matches;
if (expand_cmdline(&compl_xp, compl_pattern,
- (int)strlen(compl_pattern),
- &num_matches, &matches) == EXPAND_OK) {
+ (int)compl_patternlen, &num_matches, &matches) == EXPAND_OK) {
ins_compl_add_matches(num_matches, matches, false);
}
}
@@ -3217,8 +3219,8 @@ static int get_next_default_completion(ins_compl_next_state_T *st, pos_T *start_
compl_direction, compl_pattern);
} else {
found_new_match = searchit(NULL, st->ins_buf, st->cur_match_pos,
- NULL, compl_direction, compl_pattern, 1,
- SEARCH_KEEP + SEARCH_NFMSG, RE_LAST, NULL);
+ NULL, compl_direction, compl_pattern, compl_patternlen,
+ 1, SEARCH_KEEP + SEARCH_NFMSG, RE_LAST, NULL);
}
msg_silent--;
if (!compl_started || st->set_match_pos) {
@@ -3902,7 +3904,8 @@ static bool 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 get_normal_compl_info(char *line, int startcol, colnr_T curs_col)
{
@@ -3919,21 +3922,23 @@ static int get_normal_compl_info(char *line, int startcol, colnr_T curs_col)
}
} else if (compl_status_adding()) {
char *prefix = "\\<";
+ size_t prefixlen = STRLEN_LITERAL("\\<");
// we need up to 2 extra chars for the prefix
- compl_pattern = xmalloc(quote_meta(NULL, line + compl_col, compl_length) + 2);
+ compl_pattern = xmalloc(quote_meta(NULL, line + compl_col,
+ compl_length) + prefixlen);
if (!vim_iswordp(line + compl_col)
|| (compl_col > 0
&& (vim_iswordp(mb_prevptr(line, line + compl_col))))) {
prefix = "";
+ prefixlen = 0;
}
STRCPY(compl_pattern, prefix);
- quote_meta(compl_pattern + strlen(prefix),
- line + compl_col, compl_length);
+ 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 = xstrdup("\\<\\k\\k");
+ compl_pattern = xstrnsave(S_LEN("\\<\\k\\k"));
compl_col += curs_col;
compl_length = 0;
} else {
@@ -3965,6 +3970,8 @@ static int get_normal_compl_info(char *line, int startcol, colnr_T curs_col)
}
}
+ compl_patternlen = strlen(compl_pattern);
+
return OK;
}
@@ -3984,6 +3991,8 @@ static int get_wholeline_compl_info(char *line, colnr_T curs_col)
compl_pattern = xstrnsave(line + compl_col, (size_t)compl_length);
}
+ compl_patternlen = strlen(compl_pattern);
+
return OK;
}
@@ -4009,6 +4018,7 @@ static int get_filename_compl_info(char *line, int startcol, colnr_T curs_col)
compl_col += startcol;
compl_length = (int)curs_col - startcol;
compl_pattern = addstar(line + compl_col, (size_t)compl_length, EXPAND_FILES);
+ compl_patternlen = strlen(compl_pattern);
return OK;
}
@@ -4018,7 +4028,8 @@ static int get_filename_compl_info(char *line, int startcol, colnr_T curs_col)
static int get_cmdline_compl_info(char *line, colnr_T curs_col)
{
compl_pattern = xstrnsave(line, (size_t)curs_col);
- set_cmd_context(&compl_xp, compl_pattern, (int)strlen(compl_pattern), curs_col, false);
+ compl_patternlen = (size_t)curs_col;
+ set_cmd_context(&compl_xp, compl_pattern, (int)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
@@ -4104,6 +4115,7 @@ static int get_userdefined_compl_info(colnr_T curs_col)
char *line = ml_get(curwin->w_cursor.lnum);
compl_length = curs_col - compl_col;
compl_pattern = xstrnsave(line + compl_col, (size_t)compl_length);
+ compl_patternlen = (size_t)compl_length;
return OK;
}
@@ -4129,6 +4141,7 @@ static int get_spell_compl_info(int startcol, colnr_T curs_col)
// Need to obtain "line" again, it may have become invalid.
char *line = ml_get(curwin->w_cursor.lnum);
compl_pattern = xstrnsave(line + compl_col, (size_t)compl_length);
+ compl_patternlen = (size_t)compl_length;
return OK;
}
@@ -4324,6 +4337,7 @@ static int ins_compl_start(void)
if (ins_compl_add(compl_orig_text, -1, NULL, NULL, false, NULL, 0,
flags, false) != OK) {
XFREE_CLEAR(compl_pattern);
+ compl_patternlen = 0;
XFREE_CLEAR(compl_orig_text);
kv_destroy(compl_orig_extmarks);
return FAIL;
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 9646b83106..3b1f0bf73c 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -2349,13 +2349,15 @@ bool find_decl(char *ptr, size_t len, bool locally, bool thisblock, int flags_ar
bool incll;
int searchflags = flags_arg;
- size_t patlen = len + 7;
- char *pat = xmalloc(patlen);
+ size_t patsize = len + 7;
+ char *pat = xmalloc(patsize);
// Put "\V" before the pattern to avoid that the special meaning of "."
// and "~" causes trouble.
- assert(patlen <= INT_MAX);
- snprintf(pat, patlen, vim_iswordp(ptr) ? "\\V\\<%.*s\\>" : "\\V%.*s", (int)len, ptr);
+ assert(patsize <= INT_MAX);
+ size_t patlen = (size_t)snprintf(pat, patsize,
+ vim_iswordp(ptr) ? "\\V\\<%.*s\\>" : "\\V%.*s",
+ (int)len, ptr);
pos_T old_pos = curwin->w_cursor;
bool save_p_ws = p_ws;
bool save_p_scs = p_scs;
@@ -2382,7 +2384,7 @@ bool find_decl(char *ptr, size_t len, bool locally, bool thisblock, int flags_ar
clearpos(&found_pos);
while (true) {
t = searchit(curwin, curbuf, &curwin->w_cursor, NULL, FORWARD,
- pat, 1, searchflags, RE_LAST, NULL);
+ pat, patlen, 1, searchflags, RE_LAST, NULL);
if (curwin->w_cursor.lnum >= old_pos.lnum) {
t = false; // match after start is failure too
}
@@ -3296,21 +3298,22 @@ void do_nv_ident(int c1, int c2)
/// 'K' normal-mode command. Get the command to lookup the keyword under the
/// cursor.
static size_t nv_K_getcmd(cmdarg_T *cap, char *kp, bool kp_help, bool kp_ex, char **ptr_arg,
- size_t n, char *buf, size_t buf_size)
+ size_t n, char *buf, size_t bufsize, size_t *buflen)
{
if (kp_help) {
// in the help buffer
STRCPY(buf, "he! ");
+ *buflen = STRLEN_LITERAL("he! ");
return n;
}
if (kp_ex) {
+ *buflen = 0;
// 'keywordprg' is an ex command
if (cap->count0 != 0) { // Send the count to the ex command.
- snprintf(buf, buf_size, "%" PRId64, (int64_t)(cap->count0));
+ *buflen = (size_t)snprintf(buf, bufsize, "%" PRId64, (int64_t)(cap->count0));
}
- STRCAT(buf, kp);
- STRCAT(buf, " ");
+ *buflen += (size_t)snprintf(buf + *buflen, bufsize - *buflen, "%s ", kp);
return n;
}
@@ -3335,21 +3338,19 @@ static size_t nv_K_getcmd(cmdarg_T *cap, char *kp, bool kp_help, bool kp_ex, cha
bool isman = (strcmp(kp, "man") == 0);
bool isman_s = (strcmp(kp, "man -s") == 0);
if (cap->count0 != 0 && !(isman || isman_s)) {
- snprintf(buf, buf_size, ".,.+%" PRId64, (int64_t)(cap->count0 - 1));
+ *buflen = (size_t)snprintf(buf, bufsize, ".,.+%" PRId64, (int64_t)(cap->count0 - 1));
}
do_cmdline_cmd("tabnew");
- STRCAT(buf, "terminal ");
+ *buflen += (size_t)snprintf(buf + *buflen, bufsize - *buflen, "terminal ");
if (cap->count0 == 0 && isman_s) {
- STRCAT(buf, "man");
+ *buflen += (size_t)snprintf(buf + *buflen, bufsize - *buflen, "man ");
} else {
- STRCAT(buf, kp);
+ *buflen += (size_t)snprintf(buf + *buflen, bufsize - *buflen, "%s ", kp);
}
- STRCAT(buf, " ");
if (cap->count0 != 0 && (isman || isman_s)) {
- snprintf(buf + strlen(buf), buf_size - strlen(buf), "%" PRId64,
- (int64_t)cap->count0);
- STRCAT(buf, " ");
+ *buflen += (size_t)snprintf(buf + *buflen, bufsize - *buflen,
+ "%" PRId64 " ", (int64_t)cap->count0);
}
*ptr_arg = ptr;
@@ -3412,9 +3413,10 @@ static void nv_ident(cmdarg_T *cap)
return;
}
bool kp_ex = (*kp == ':'); // 'keywordprg' is an ex command
- size_t buf_size = n * 2 + 30 + strlen(kp);
- char *buf = xmalloc(buf_size);
+ size_t bufsize = n * 2 + 30 + strlen(kp);
+ char *buf = xmalloc(bufsize);
buf[0] = NUL;
+ size_t buflen = 0;
switch (cmdchar) {
case '*':
@@ -3428,12 +3430,13 @@ static void nv_ident(cmdarg_T *cap)
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, buf_size);
+ n = nv_K_getcmd(cap, kp, kp_help, kp_ex, &ptr, n, buf, bufsize, &buflen);
if (n == 0) {
return;
}
@@ -3442,19 +3445,23 @@ static void nv_ident(cmdarg_T *cap)
case ']':
tag_cmd = true;
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 {
- snprintf(buf, buf_size, ":%" PRId64 "ta ", (int64_t)cap->count0);
+ buflen = (size_t)snprintf(buf, bufsize, ":%" PRId64 "ta ", (int64_t)cap->count0);
}
}
}
@@ -3470,9 +3477,11 @@ static void nv_ident(cmdarg_T *cap)
p = vim_strsave_shellescape(ptr, true, true);
}
xfree(ptr);
- char *newbuf = xrealloc(buf, strlen(buf) + strlen(p) + 1);
+ size_t plen = strlen(p);
+ char *newbuf = xrealloc(buf, buflen + plen + 1);
buf = newbuf;
- STRCAT(buf, p);
+ STRCPY(buf + buflen, p);
+ buflen += plen;
xfree(p);
} else {
char *aux_ptr;
@@ -3491,12 +3500,13 @@ static void nv_ident(cmdarg_T *cap)
aux_ptr = "\\|\"\n*?[";
}
- p = buf + strlen(buf);
+ p = buf + buflen;
while (n-- > 0) {
// put a backslash before \ and some others
if (vim_strchr(aux_ptr, (uint8_t)(*ptr)) != NULL) {
*p++ = '\\';
}
+
// When current byte is a part of multibyte character, copy all
// bytes of that character.
const size_t len = (size_t)(utfc_ptr2len(ptr) - 1);
@@ -3506,20 +3516,21 @@ static void nv_ident(cmdarg_T *cap)
*p++ = *ptr++;
}
*p = NUL;
+ buflen = (size_t)(p - buf);
}
// Execute the command.
if (cmdchar == '*' || cmdchar == '#') {
- if (!g_cmd
- && vim_iswordp(mb_prevptr(get_cursor_line_ptr(), ptr))) {
- STRCAT(buf, "\\>");
+ if (!g_cmd && vim_iswordp(mb_prevptr(get_cursor_line_ptr(), ptr))) {
+ 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);
- normal_search(cap, cmdchar == '*' ? '/' : '?', buf, 0, NULL);
+ normal_search(cap, cmdchar == '*' ? '/' : '?', buf, buflen, 0, NULL);
} else {
g_tag_at_cursor = true;
do_cmdline_cmd(buf);
@@ -3940,7 +3951,7 @@ static void nv_search(cmdarg_T *cap)
return;
}
- normal_search(cap, cap->cmdchar, cap->searchbuf,
+ normal_search(cap, cap->cmdchar, cap->searchbuf, strlen(cap->searchbuf),
(cap->arg || !equalpos(save_cursor, curwin->w_cursor))
? 0 : SEARCH_MARK, NULL);
}
@@ -3951,14 +3962,14 @@ static void 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 && equalpos(old, curwin->w_cursor)) {
// Avoid getting stuck on the current cursor position, which can happen when
// an offset is given and the cursor is on the last char in the buffer:
// Repeat with count + 1.
cap->count1 += 1;
- normal_search(cap, 0, NULL, SEARCH_MARK | cap->arg, NULL);
+ normal_search(cap, 0, NULL, 0, SEARCH_MARK | cap->arg, NULL);
cap->count1 -= 1;
}
}
@@ -3969,7 +3980,7 @@ static void nv_next(cmdarg_T *cap)
/// @param opt extra flags for do_search()
///
/// @return 0 for failure, 1 for found, 2 for found and line offset added.
-static int normal_search(cmdarg_T *cap, int dir, char *pat, int opt, int *wrapped)
+static int normal_search(cmdarg_T *cap, int dir, char *pat, size_t patlen, int opt, int *wrapped)
{
searchit_arg_T sia;
@@ -3979,7 +3990,7 @@ static int normal_search(cmdarg_T *cap, int dir, char *pat, int opt, int *wrappe
curwin->w_set_curswant = true;
CLEAR_FIELD(sia);
- int i = do_search(cap->oap, dir, dir, pat, cap->count1,
+ int 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;
@@ -3999,6 +4010,7 @@ static int normal_search(cmdarg_T *cap, int dir, char *pat, int opt, int *wrappe
// "/$" will put the cursor after the end of the line, may need to
// correct that here
check_cursor(curwin);
+
return i;
}
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index 2713dd2a45..e022184f2f 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -2902,7 +2902,7 @@ static void qf_jump_goto_line(linenr_T qf_lnum, int qf_col, char qf_viscol, char
// Move the cursor to the first line in the buffer
pos_T save_cursor = curwin->w_cursor;
curwin->w_cursor.lnum = 0;
- if (!do_search(NULL, '/', '/', qf_pattern, 1, SEARCH_KEEP, NULL)) {
+ if (!do_search(NULL, '/', '/', qf_pattern, strlen(qf_pattern), 1, SEARCH_KEEP, NULL)) {
curwin->w_cursor = save_cursor;
}
}
diff --git a/src/nvim/search.c b/src/nvim/search.c
index df0a9171d2..746c253708 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -99,9 +99,9 @@ static const char e_search_hit_bottom_without_match_for_str[]
static SearchPattern spats[2] = {
// Last used search pattern
- [0] = { NULL, true, false, 0, { '/', false, false, 0 }, NULL },
+ [0] = { NULL, 0, true, false, 0, { '/', false, false, 0 }, NULL },
// Last used substitute pattern
- [1] = { NULL, true, false, 0, { '/', false, false, 0 }, NULL }
+ [1] = { NULL, 0, true, false, 0, { '/', false, false, 0 }, NULL }
};
static int last_idx = 0; // index in spats[] for RE_LAST
@@ -113,13 +113,15 @@ static char lastc_bytes[MB_MAXBYTES + 1];
static int lastc_bytelen = 1; // >1 for multi-byte char
// copy of spats[], for keeping the search patterns while executing autocmds
-static SearchPattern saved_spats[2];
+static SearchPattern saved_spats[ARRAY_SIZE(spats)];
static char *saved_mr_pattern = NULL;
+static size_t saved_mr_patternlen = 0;
static int saved_spats_last_idx = 0;
static bool saved_spats_no_hlsearch = false;
// allocated copy of pattern used by search_regcomp()
static char *mr_pattern = NULL;
+static size_t mr_patternlen = 0;
// Type used by find_pattern_in_path() to remember which included files have
// been searched already.
@@ -144,8 +146,8 @@ typedef struct {
/// @param regmatch return: pattern and ignore-case flag
///
/// @return FAIL if failed, OK otherwise.
-int search_regcomp(char *pat, char **used_pat, int pat_save, int pat_use, int options,
- regmmatch_T *regmatch)
+int search_regcomp(char *pat, size_t patlen, char **used_pat, int pat_save, int pat_use,
+ int options, regmmatch_T *regmatch)
{
rc_did_emsg = false;
int magic = magic_isset();
@@ -168,10 +170,11 @@ int search_regcomp(char *pat, char **used_pat, int pat_save, int pat_use, int op
return FAIL;
}
pat = spats[i].pat;
+ patlen = spats[i].patlen;
magic = spats[i].magic;
no_smartcase = spats[i].no_scs;
} else if (options & SEARCH_HIS) { // put new pattern in history
- add_to_history(HIST_SEARCH, pat, true, NUL);
+ add_to_history(HIST_SEARCH, pat, patlen, true, NUL);
}
if (used_pat) {
@@ -182,19 +185,20 @@ int search_regcomp(char *pat, char **used_pat, int pat_save, int pat_use, int op
if (curwin->w_p_rl && *curwin->w_p_rlc == 's') {
mr_pattern = reverse_text(pat);
} else {
- mr_pattern = xstrdup(pat);
+ mr_pattern = xstrnsave(pat, patlen);
}
+ mr_patternlen = patlen;
// Save the currently used pattern in the appropriate place,
// unless the pattern should not be remembered.
if (!(options & SEARCH_KEEP) && (cmdmod.cmod_flags & CMOD_KEEPPATTERNS) == 0) {
// search or global command
if (pat_save == RE_SEARCH || pat_save == RE_BOTH) {
- save_re_pat(RE_SEARCH, pat, magic);
+ save_re_pat(RE_SEARCH, pat, patlen, magic);
}
// substitute or global command
if (pat_save == RE_SUBST || pat_save == RE_BOTH) {
- save_re_pat(RE_SUBST, pat, magic);
+ save_re_pat(RE_SUBST, pat, patlen, magic);
}
}
@@ -213,14 +217,15 @@ char *get_search_pat(void)
return mr_pattern;
}
-void save_re_pat(int idx, char *pat, int magic)
+void save_re_pat(int idx, char *pat, size_t patlen, int magic)
{
if (spats[idx].pat == pat) {
return;
}
free_spat(&spats[idx]);
- spats[idx].pat = xstrdup(pat);
+ spats[idx].pat = xstrnsave(pat, patlen);
+ spats[idx].patlen = patlen;
spats[idx].magic = magic;
spats[idx].no_scs = no_smartcase;
spats[idx].timestamp = os_time();
@@ -243,18 +248,19 @@ void save_search_patterns(void)
return;
}
- saved_spats[0] = spats[0];
- if (spats[0].pat != NULL) {
- saved_spats[0].pat = xstrdup(spats[0].pat);
- }
- saved_spats[1] = spats[1];
- if (spats[1].pat != NULL) {
- saved_spats[1].pat = xstrdup(spats[1].pat);
+ for (size_t i = 0; i < ARRAY_SIZE(spats); i++) {
+ saved_spats[i] = spats[i];
+ if (spats[i].pat != NULL) {
+ saved_spats[i].pat = xstrnsave(spats[i].pat, spats[i].patlen);
+ saved_spats[i].patlen = spats[i].patlen;
+ }
}
if (mr_pattern == NULL) {
saved_mr_pattern = NULL;
+ saved_mr_patternlen = 0;
} else {
- saved_mr_pattern = xstrdup(mr_pattern);
+ saved_mr_pattern = xstrnsave(mr_pattern, mr_patternlen);
+ saved_mr_patternlen = mr_patternlen;
}
saved_spats_last_idx = last_idx;
saved_spats_no_hlsearch = no_hlsearch;
@@ -266,13 +272,14 @@ void restore_search_patterns(void)
return;
}
- free_spat(&spats[0]);
- spats[0] = saved_spats[0];
+ for (size_t i = 0; i < ARRAY_SIZE(spats); i++) {
+ free_spat(&spats[i]);
+ spats[i] = saved_spats[i];
+ }
set_vv_searchforward();
- free_spat(&spats[1]);
- spats[1] = saved_spats[1];
xfree(mr_pattern);
mr_pattern = saved_mr_pattern;
+ mr_patternlen = saved_mr_patternlen;
last_idx = saved_spats_last_idx;
set_no_hlsearch(saved_spats_no_hlsearch);
}
@@ -286,12 +293,13 @@ static inline void free_spat(SearchPattern *const spat)
#if defined(EXITFREE)
void free_search_patterns(void)
{
- free_spat(&spats[0]);
- free_spat(&spats[1]);
-
+ for (size_t i = 0; i < ARRAY_SIZE(spats); i++) {
+ free_spat(&spats[i]);
+ }
CLEAR_FIELD(spats);
XFREE_CLEAR(mr_pattern);
+ mr_patternlen = 0;
}
#endif
@@ -320,7 +328,8 @@ void save_last_search_pattern(void)
saved_last_search_spat = spats[RE_SEARCH];
if (spats[RE_SEARCH].pat != NULL) {
- saved_last_search_spat.pat = xstrdup(spats[RE_SEARCH].pat);
+ saved_last_search_spat.pat = xstrnsave(spats[RE_SEARCH].pat, spats[RE_SEARCH].patlen);
+ saved_last_search_spat.patlen = spats[RE_SEARCH].patlen;
}
saved_last_idx = last_idx;
saved_no_hlsearch = no_hlsearch;
@@ -341,6 +350,7 @@ void restore_last_search_pattern(void)
xfree(spats[RE_SEARCH].pat);
spats[RE_SEARCH] = saved_last_search_spat;
saved_last_search_spat.pat = NULL;
+ saved_last_search_spat.patlen = 0;
set_vv_searchforward();
last_idx = saved_last_idx;
set_no_hlsearch(saved_no_hlsearch);
@@ -487,8 +497,10 @@ void set_last_search_pat(const char *s, int idx, int magic, bool setlast)
// An empty string means that nothing should be matched.
if (*s == NUL) {
spats[idx].pat = NULL;
+ spats[idx].patlen = 0;
} else {
- spats[idx].pat = xstrdup(s);
+ spats[idx].patlen = strlen(s);
+ spats[idx].pat = xstrnsave(s, spats[idx].patlen);
}
spats[idx].timestamp = os_time();
spats[idx].additional_data = NULL;
@@ -507,8 +519,10 @@ void set_last_search_pat(const char *s, int idx, int magic, bool setlast)
saved_spats[idx] = spats[0];
if (spats[idx].pat == NULL) {
saved_spats[idx].pat = NULL;
+ saved_spats[idx].patlen = 0;
} else {
- saved_spats[idx].pat = xstrdup(spats[idx].pat);
+ saved_spats[idx].pat = xstrnsave(spats[idx].pat, spats[idx].patlen);
+ saved_spats[idx].patlen = spats[idx].patlen;
}
saved_spats_last_idx = last_idx;
}
@@ -528,7 +542,7 @@ void last_pat_prog(regmmatch_T *regmatch)
return;
}
emsg_off++; // So it doesn't beep if bad expr
- search_regcomp("", NULL, 0, last_idx, SEARCH_KEEP, regmatch);
+ search_regcomp("", 0, NULL, 0, last_idx, SEARCH_KEEP, regmatch);
emsg_off--;
}
@@ -556,7 +570,7 @@ void last_pat_prog(regmmatch_T *regmatch)
/// the index of the first matching
/// subpattern plus one; one if there was none.
int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, Direction dir, char *pat,
- int count, int options, int pat_use, searchit_arg_T *extra_arg)
+ size_t patlen, int count, int options, int pat_use, searchit_arg_T *extra_arg)
{
int found;
linenr_T lnum; // no init to shut up Apollo cc
@@ -584,7 +598,7 @@ int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, Direction dir,
timed_out = &extra_arg->sa_timed_out;
}
- if (search_regcomp(pat, NULL, RE_SEARCH, pat_use,
+ if (search_regcomp(pat, patlen, NULL, RE_SEARCH, pat_use,
(options & (SEARCH_HIS + SEARCH_KEEP)), &regmatch) == FAIL) {
if ((options & SEARCH_MSG) && !rc_did_emsg) {
semsg(_("E383: Invalid search string: %s"), mr_pattern);
@@ -592,6 +606,8 @@ int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, Direction dir,
return FAIL;
}
+ const bool search_from_match_end = vim_strchr(p_cpo, CPO_SEARCH) != NULL;
+
// find the string
do { // loop for count
// When not accepting a match at the start position set "extra_col" to a
@@ -699,7 +715,7 @@ int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, Direction dir,
// If vi-compatible searching, continue at the end
// of the match, otherwise continue one position
// forward.
- if (vim_strchr(p_cpo, CPO_SEARCH) != NULL) {
+ if (search_from_match_end) {
if (nmatched > 1) {
// end is in next line, thus no match in
// this line
@@ -791,7 +807,7 @@ int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, Direction dir,
// If vi-compatible searching, continue at the end
// of the match, otherwise continue one position
// forward.
- if (vim_strchr(p_cpo, CPO_SEARCH) != NULL) {
+ if (search_from_match_end) {
if (nmatched > 1) {
break;
}
@@ -1031,11 +1047,12 @@ static int first_submatch(regmmatch_T *rp)
/// @param sia optional arguments or NULL
///
/// @return 0 for failure, 1 for found, 2 for found and line offset added.
-int do_search(oparg_T *oap, int dirc, int search_delim, char *pat, int count, int options,
- searchit_arg_T *sia)
+int do_search(oparg_T *oap, int dirc, int search_delim, char *pat, size_t patlen, int count,
+ int options, searchit_arg_T *sia)
{
pos_T pos; // position of the last match
char *searchstr;
+ size_t searchstrlen;
int retval; // Return value
char *p;
int64_t c;
@@ -1043,9 +1060,11 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char *pat, int count, in
char *strcopy = NULL;
char *ps;
char *msgbuf = NULL;
- size_t len;
+ size_t msgbuflen = 0;
bool has_offset = false;
+ searchcmdlen = 0;
+
// A line offset is not remembered, this is vi compatible.
if (spats[0].off.line && vim_strchr(p_cpo, CPO_LINEOFF) != NULL) {
spats[0].off.line = false;
@@ -1096,19 +1115,23 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char *pat, int count, in
bool show_top_bot_msg = false;
searchstr = pat;
+ searchstrlen = patlen;
+
dircp = NULL;
// use previous pattern
if (pat == NULL || *pat == NUL || *pat == search_delim) {
if (spats[RE_SEARCH].pat == NULL) { // no previous pattern
- searchstr = spats[RE_SUBST].pat;
- if (searchstr == NULL) {
+ if (spats[RE_SUBST].pat == NULL) {
emsg(_(e_noprevre));
retval = 0;
goto end_do_search;
}
+ searchstr = spats[RE_SUBST].pat;
+ searchstrlen = spats[RE_SUBST].patlen;
} else {
// make search_regcomp() use spats[RE_SEARCH].pat
searchstr = "";
+ searchstrlen = 0;
}
}
@@ -1118,12 +1141,16 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char *pat, int count, in
ps = strcopy;
p = skip_regexp_ex(pat, search_delim, magic_isset(), &strcopy, NULL, NULL);
if (strcopy != ps) {
+ size_t len = strlen(strcopy);
// made a copy of "pat" to change "\?" to "?"
- searchcmdlen += (int)(strlen(pat) - strlen(strcopy));
+ searchcmdlen += (int)(patlen - len);
pat = strcopy;
+ patlen = len;
searchstr = strcopy;
+ searchstrlen = len;
}
if (*p == search_delim) {
+ searchstrlen = (size_t)(p - pat);
dircp = p; // remember where we put the NUL
*p++ = NUL;
}
@@ -1161,12 +1188,13 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char *pat, int count, in
// compute length of search command for get_address()
searchcmdlen += (int)(p - pat);
+ patlen -= (size_t)(p - pat);
pat = p; // put pat after search command
}
+ bool show_search_stats = false;
if ((options & SEARCH_ECHO) && messaging() && !msg_silent
&& (!cmd_silent || !shortmess(SHM_SEARCHCOUNT))) {
- char *trunc;
char off_buf[40];
size_t off_len = 0;
@@ -1176,56 +1204,59 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char *pat, int count, in
// Get the offset, so we know how long it is.
if (!cmd_silent
&& (spats[0].off.line || spats[0].off.end || spats[0].off.off)) {
- p = off_buf;
- *p++ = (char)dirc;
+ off_buf[off_len++] = (char)dirc;
if (spats[0].off.end) {
- *p++ = 'e';
+ off_buf[off_len++] = 'e';
} else if (!spats[0].off.line) {
- *p++ = 's';
+ off_buf[off_len++] = 's';
}
if (spats[0].off.off > 0 || spats[0].off.line) {
- *p++ = '+';
+ off_buf[off_len++] = '+';
}
- *p = NUL;
+ off_buf[off_len] = NUL;
if (spats[0].off.off != 0 || spats[0].off.line) {
- snprintf(p, sizeof(off_buf) - 1 - (size_t)(p - off_buf),
- "%" PRId64, spats[0].off.off);
+ off_len += (size_t)snprintf(off_buf + off_len, sizeof(off_buf) - off_len,
+ "%" PRId64, spats[0].off.off);
}
- off_len = strlen(off_buf);
}
+ size_t plen;
if (*searchstr == NUL) {
p = spats[0].pat;
+ plen = spats[0].patlen;
} else {
p = searchstr;
+ plen = searchstrlen;
}
+ size_t msgbufsize;
if (!shortmess(SHM_SEARCHCOUNT) || cmd_silent) {
// Reserve enough space for the search pattern + offset +
// search stat. Use all the space available, so that the
// search state is right aligned. If there is not enough space
// msg_strtrunc() will shorten in the middle.
if (ui_has(kUIMessages)) {
- len = 0; // adjusted below
+ msgbufsize = 0; // adjusted below
} else if (msg_scrolled != 0 && !cmd_silent) {
// Use all the columns.
- len = (size_t)((Rows - msg_row) * Columns - 1);
+ msgbufsize = (size_t)((Rows - msg_row) * Columns - 1);
} else {
// Use up to 'showcmd' column.
- len = (size_t)((Rows - msg_row - 1) * Columns + sc_col - 1);
+ msgbufsize = (size_t)((Rows - msg_row - 1) * Columns + sc_col - 1);
}
- if (len < strlen(p) + off_len + SEARCH_STAT_BUF_LEN + 3) {
- len = strlen(p) + off_len + SEARCH_STAT_BUF_LEN + 3;
+ if (msgbufsize < plen + off_len + SEARCH_STAT_BUF_LEN + 3) {
+ msgbufsize = plen + off_len + SEARCH_STAT_BUF_LEN + 3;
}
} else {
// Reserve enough space for the search pattern + offset.
- len = strlen(p) + off_len + 3;
+ msgbufsize = plen + off_len + 3;
}
xfree(msgbuf);
- msgbuf = xmalloc(len);
- memset(msgbuf, ' ', len);
- msgbuf[len - 1] = NUL;
+ msgbuf = xmalloc(msgbufsize);
+ memset(msgbuf, ' ', msgbufsize);
+ msgbuflen = msgbufsize - 1;
+ msgbuf[msgbuflen] = NUL;
// do not fill the msgbuf buffer, if cmd_silent is set, leave it
// empty for the search_stat feature.
@@ -1234,18 +1265,19 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char *pat, int count, in
if (utf_iscomposing(utf_ptr2char(p))) {
// Use a space to draw the composing char on.
msgbuf[1] = ' ';
- memmove(msgbuf + 2, p, strlen(p));
+ memmove(msgbuf + 2, p, plen);
} else {
- memmove(msgbuf + 1, p, strlen(p));
+ memmove(msgbuf + 1, p, plen);
}
if (off_len > 0) {
- memmove(msgbuf + strlen(p) + 1, off_buf, off_len);
+ memmove(msgbuf + plen + 1, off_buf, off_len);
}
- trunc = msg_strtrunc(msgbuf, true);
+ char *trunc = msg_strtrunc(msgbuf, true);
if (trunc != NULL) {
xfree(msgbuf);
msgbuf = trunc;
+ msgbuflen = strlen(msgbuf);
}
// The search pattern could be shown on the right in rightleft
@@ -1260,7 +1292,7 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char *pat, int count, in
while (*r == ' ') {
r++;
}
- size_t pat_len = (size_t)(msgbuf + strlen(msgbuf) - r);
+ size_t pat_len = (size_t)(msgbuf + msgbuflen - r);
memmove(msgbuf, r, pat_len);
// overwrite old text
if ((size_t)(r - msgbuf) >= pat_len) {
@@ -1277,6 +1309,10 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char *pat, int count, in
ui_flush();
msg_nowait = true; // don't wait for this message
}
+
+ if (!shortmess(SHM_SEARCHCOUNT)) {
+ show_search_stats = true;
+ }
}
// If there is a character offset, subtract it from the current
@@ -1309,7 +1345,7 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char *pat, int count, in
}
c = searchit(curwin, curbuf, &pos, NULL, dirc == '/' ? FORWARD : BACKWARD,
- searchstr, count,
+ searchstr, searchstrlen, count,
(spats[0].off.end * SEARCH_END
+ (options
& (SEARCH_KEEP + SEARCH_PEEK + SEARCH_HIS + SEARCH_MSG
@@ -1379,14 +1415,9 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char *pat, int count, in
}
// Show [1/15] if 'S' is not in 'shortmess'.
- if ((options & SEARCH_ECHO)
- && messaging()
- && !msg_silent
- && c != FAIL
- && !shortmess(SHM_SEARCHCOUNT)
- && msgbuf != NULL) {
+ if (show_search_stats) {
cmdline_search_stat(dirc, &pos, &curwin->w_cursor,
- show_top_bot_msg, msgbuf,
+ show_top_bot_msg, msgbuf, msgbuflen,
(count != 1 || has_offset
|| (!(fdo_flags & FDO_SEARCH)
&& hasFolding(curwin, curwin->w_cursor.lnum, NULL,
@@ -1413,6 +1444,7 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char *pat, int count, in
goto end_do_search;
}
pat++;
+ patlen--;
}
if (options & SEARCH_MARK) {
@@ -2418,7 +2450,8 @@ int current_search(int count, bool forward)
}
// Is the pattern is zero-width?, this time, don't care about the direction
- int zero_width = is_zero_width(spats[last_idx].pat, true, &curwin->w_cursor, FORWARD);
+ int zero_width = is_zero_width(spats[last_idx].pat, spats[last_idx].patlen,
+ true, &curwin->w_cursor, FORWARD);
if (zero_width == -1) {
return FAIL; // pattern not found
}
@@ -2451,7 +2484,7 @@ int current_search(int count, bool forward)
result = searchit(curwin, curbuf, &pos, &end_pos,
(dir ? FORWARD : BACKWARD),
- spats[last_idx].pat, i ? count : 1,
+ spats[last_idx].pat, spats[last_idx].patlen, i ? count : 1,
SEARCH_KEEP | flags, RE_SEARCH, NULL);
p_ws = old_p_ws;
@@ -2525,7 +2558,8 @@ int current_search(int count, bool forward)
/// else from position "cur".
/// "direction" is FORWARD or BACKWARD.
/// Returns true, false or -1 for failure.
-static int is_zero_width(char *pattern, bool move, pos_T *cur, Direction direction)
+static int is_zero_width(char *pattern, size_t patternlen, bool move, pos_T *cur,
+ Direction direction)
{
regmmatch_T regmatch;
int result = -1;
@@ -2535,9 +2569,10 @@ static int is_zero_width(char *pattern, bool move, pos_T *cur, Direction directi
if (pattern == NULL) {
pattern = spats[last_idx].pat;
+ patternlen = spats[last_idx].patlen;
}
- if (search_regcomp(pattern, NULL, RE_SEARCH, RE_SEARCH,
+ if (search_regcomp(pattern, patternlen, NULL, RE_SEARCH, RE_SEARCH,
SEARCH_KEEP, &regmatch) == FAIL) {
return -1;
}
@@ -2552,7 +2587,7 @@ static int is_zero_width(char *pattern, bool move, pos_T *cur, Direction directi
// accept a match at the cursor position
flag = SEARCH_START;
}
- if (searchit(curwin, curbuf, &pos, NULL, direction, pattern, 1,
+ if (searchit(curwin, curbuf, &pos, NULL, direction, pattern, patternlen, 1,
SEARCH_KEEP + flag, RE_SEARCH, NULL) != FAIL) {
int nmatched = 0;
// Zero-width pattern should match somewhere, then we can check if
@@ -2591,7 +2626,8 @@ bool linewhite(linenr_T lnum)
/// Add the search count "[3/19]" to "msgbuf".
/// See update_search_stat() for other arguments.
static void cmdline_search_stat(int dirc, pos_T *pos, pos_T *cursor_pos, bool show_top_bot_msg,
- char *msgbuf, bool recompute, int maxcount, int timeout)
+ char *msgbuf, size_t msgbuflen, bool recompute, int maxcount,
+ int timeout)
{
searchstat_T stat;
@@ -2602,36 +2638,36 @@ static void cmdline_search_stat(int dirc, pos_T *pos, pos_T *cursor_pos, bool sh
}
char t[SEARCH_STAT_BUF_LEN];
+ size_t len;
if (curwin->w_p_rl && *curwin->w_p_rlc == 's') {
if (stat.incomplete == 1) {
- vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[?/??]");
+ len = (size_t)vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[?/??]");
} else if (stat.cnt > maxcount && stat.cur > maxcount) {
- vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[>%d/>%d]",
- maxcount, maxcount);
+ len = (size_t)vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[>%d/>%d]",
+ maxcount, maxcount);
} else if (stat.cnt > maxcount) {
- vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[>%d/%d]",
- maxcount, stat.cur);
+ len = (size_t)vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[>%d/%d]",
+ maxcount, stat.cur);
} else {
- vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[%d/%d]",
- stat.cnt, stat.cur);
+ len = (size_t)vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[%d/%d]",
+ stat.cnt, stat.cur);
}
} else {
if (stat.incomplete == 1) {
- vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[?/??]");
+ len = (size_t)vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[?/??]");
} else if (stat.cnt > maxcount && stat.cur > maxcount) {
- vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[>%d/>%d]",
- maxcount, maxcount);
+ len = (size_t)vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[>%d/>%d]",
+ maxcount, maxcount);
} else if (stat.cnt > maxcount) {
- vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[%d/>%d]",
- stat.cur, maxcount);
+ len = (size_t)vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[%d/>%d]",
+ stat.cur, maxcount);
} else {
- vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[%d/%d]",
- stat.cur, stat.cnt);
+ len = (size_t)vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[%d/%d]",
+ stat.cur, stat.cnt);
}
}
- size_t len = strlen(t);
if (show_top_bot_msg && len + 2 < SEARCH_STAT_BUF_LEN) {
memmove(t + 2, t, len);
t[0] = 'W';
@@ -2639,11 +2675,10 @@ static void cmdline_search_stat(int dirc, pos_T *pos, pos_T *cursor_pos, bool sh
len += 2;
}
- size_t msgbuf_len = strlen(msgbuf);
- if (len > msgbuf_len) {
- len = msgbuf_len;
+ if (len > msgbuflen) {
+ len = msgbuflen;
}
- memmove(msgbuf + msgbuf_len - len, t, len);
+ memmove(msgbuf + msgbuflen - len, t, len);
if (dirc == '?' && stat.cur == maxcount + 1) {
stat.cur = -1;
@@ -2726,7 +2761,7 @@ static void update_search_stat(int dirc, pos_T *pos, pos_T *cursor_pos, searchst
start = profile_setlimit(timeout);
}
while (!got_int && searchit(curwin, curbuf, &lastpos, &endpos,
- FORWARD, NULL, 1, SEARCH_KEEP, RE_LAST,
+ FORWARD, NULL, 0, 1, SEARCH_KEEP, RE_LAST,
NULL) != FAIL) {
done_search = true;
// Stop after passing the time limit.
@@ -2860,7 +2895,8 @@ void f_searchcount(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
goto the_end;
}
xfree(spats[last_idx].pat);
- spats[last_idx].pat = xstrdup(pattern);
+ spats[last_idx].patlen = strlen(pattern);
+ spats[last_idx].pat = xstrnsave(pattern, spats[last_idx].patlen);
}
if (spats[last_idx].pat == NULL || *spats[last_idx].pat == NUL) {
goto the_end; // the previous pattern was never defined
@@ -3602,10 +3638,10 @@ void find_pattern_in_path(char *ptr, Direction dir, size_t len, bool whole, bool
// when CONT_SOL is set compare "ptr" with the beginning of the
// line is faster than quote_meta/regcomp/regexec "ptr" -- Acevedo
&& !compl_status_sol()) {
- size_t patlen = len + 5;
- char *pat = xmalloc(patlen);
+ size_t patsize = len + 5;
+ char *pat = xmalloc(patsize);
assert(len <= INT_MAX);
- snprintf(pat, patlen, whole ? "\\<%.*s\\>" : "%.*s", (int)len, ptr);
+ snprintf(pat, patsize, whole ? "\\<%.*s\\>" : "%.*s", (int)len, ptr);
// ignore case according to p_ic, p_scs and pat
regmatch.rm_ic = ignorecase(pat);
regmatch.regprog = vim_regcomp(pat, magic_isset() ? RE_MAGIC : 0);
@@ -3623,8 +3659,7 @@ void find_pattern_in_path(char *ptr, Direction dir, size_t len, bool whole, bool
incl_regmatch.rm_ic = false; // don't ignore case in incl. pat.
}
if (type == FIND_DEFINE && (*curbuf->b_p_def != NUL || *p_def != NUL)) {
- def_regmatch.regprog = vim_regcomp(*curbuf->b_p_def == NUL
- ? p_def : curbuf->b_p_def,
+ def_regmatch.regprog = vim_regcomp(*curbuf->b_p_def == NUL ? p_def : curbuf->b_p_def,
magic_isset() ? RE_MAGIC : 0);
if (def_regmatch.regprog == NULL) {
goto fpip_end;
@@ -4066,7 +4101,7 @@ exit_matched:
&& action == ACTION_EXPAND
&& !compl_status_sol()
&& *startp != NUL
- && *(p = startp + utfc_ptr2len(startp)) != NUL) {
+ && *(startp + utfc_ptr2len(startp)) != NUL) {
goto search_line;
}
}
@@ -4165,8 +4200,9 @@ static void show_pat_in_path(char *line, int type, bool did_show, int action, FI
if (got_int) { // 'q' typed at "--more--" message
return;
}
+ size_t linelen = strlen(line);
while (true) {
- char *p = line + strlen(line) - 1;
+ char *p = line + linelen - 1;
if (fp != NULL) {
// We used fgets(), so get rid of newline at end
if (p >= line && *p == '\n') {
@@ -4196,12 +4232,14 @@ static void show_pat_in_path(char *line, int type, bool did_show, int action, FI
if (vim_fgets(line, LSIZE, fp)) { // end of file
break;
}
+ linelen = strlen(line);
(*lnum)++;
} else {
if (++*lnum > curbuf->b_ml.ml_line_count) {
break;
}
line = ml_get(*lnum);
+ linelen = (size_t)ml_get_len(*lnum);
}
msg_putchar('\n');
}
diff --git a/src/nvim/search.h b/src/nvim/search.h
index 09af34d87e..783756b781 100644
--- a/src/nvim/search.h
+++ b/src/nvim/search.h
@@ -84,6 +84,7 @@ typedef struct {
/// Structure containing last search pattern and its attributes.
typedef struct {
char *pat; ///< The pattern (in allocated memory) or NULL.
+ size_t patlen; ///< The length of the patten (0 is pat is NULL).
bool magic; ///< Magicness of the pattern.
bool no_scs; ///< No smartcase for this pattern.
Timestamp timestamp; ///< Time of the last change.
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index 6f0c7bab8e..d7a6adef58 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -2665,16 +2665,16 @@ void ex_spellrepall(exarg_T *eap)
const size_t repl_to_len = strlen(repl_to);
const int addlen = (int)(repl_to_len - repl_from_len);
- const size_t frompatlen = repl_from_len + 7;
- char *frompat = xmalloc(frompatlen);
- snprintf(frompat, frompatlen, "\\V\\<%s\\>", repl_from);
+ const size_t frompatsize = repl_from_len + 7;
+ char *frompat = xmalloc(frompatsize);
+ size_t frompatlen = (size_t)snprintf(frompat, frompatsize, "\\V\\<%s\\>", repl_from);
p_ws = false;
sub_nsubs = 0;
sub_nlines = 0;
curwin->w_cursor.lnum = 0;
while (!got_int) {
- if (do_search(NULL, '/', '/', frompat, 1, SEARCH_KEEP, NULL) == 0
+ if (do_search(NULL, '/', '/', frompat, frompatlen, 1, SEARCH_KEEP, NULL) == 0
|| u_save_cursor() == FAIL) {
break;
}
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index 1c03731048..f322438485 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -2942,6 +2942,8 @@ static int jumpto_tag(const char *lbuf_arg, int forceit, bool keep_help)
str = skip_regexp(pbuf + 1, pbuf[0], false) + 1;
}
if (str > pbuf_end - 1) { // search command with nothing following
+ size_t pbuflen = (size_t)(pbuf_end - pbuf);
+
bool save_p_ws = p_ws;
int save_p_ic = p_ic;
int save_p_scs = p_scs;
@@ -2956,25 +2958,27 @@ static int jumpto_tag(const char *lbuf_arg, int forceit, bool keep_help)
// start search before first line
curwin->w_cursor.lnum = 0;
}
- if (do_search(NULL, pbuf[0], pbuf[0], pbuf + 1, 1, search_options, NULL)) {
+ if (do_search(NULL, pbuf[0], pbuf[0], pbuf + 1, pbuflen - 1, 1,
+ search_options, NULL)) {
retval = OK;
} else {
int found = 1;
// try again, ignore case now
p_ic = true;
- if (!do_search(NULL, pbuf[0], pbuf[0], pbuf + 1, 1, search_options, NULL)) {
+ if (!do_search(NULL, pbuf[0], pbuf[0], pbuf + 1, pbuflen - 1, 1,
+ search_options, NULL)) {
// Failed to find pattern, take a guess: "^func ("
found = 2;
test_for_static(&tagp);
char cc = *tagp.tagname_end;
*tagp.tagname_end = NUL;
- snprintf(pbuf, LSIZE, "^%s\\s\\*(", tagp.tagname);
- if (!do_search(NULL, '/', '/', pbuf, 1, search_options, NULL)) {
+ pbuflen = (size_t)snprintf(pbuf, LSIZE, "^%s\\s\\*(", tagp.tagname);
+ if (!do_search(NULL, '/', '/', pbuf, pbuflen, 1, search_options, NULL)) {
// Guess again: "^char * \<func ("
- snprintf(pbuf, LSIZE, "^\\[#a-zA-Z_]\\.\\*\\<%s\\s\\*(",
- tagp.tagname);
- if (!do_search(NULL, '/', '/', pbuf, 1, search_options, NULL)) {
+ pbuflen = (size_t)snprintf(pbuf, LSIZE, "^\\[#a-zA-Z_]\\.\\*\\<%s\\s\\*(",
+ tagp.tagname);
+ if (!do_search(NULL, '/', '/', pbuf, len, 1, search_options, NULL)) {
found = 0;
}
}