patch 9.2.0126: String handling can be improved
Commit:
https://github.com/vim/vim/commit/727f6e2686fb1d06b9591e6de689763a479cc664
Author: John Marriott <
basi...@internode.on.net>
Date: Mon Mar 9 18:17:22 2026 +0000
patch 9.2.0126: String handling can be improved
Problem: String handling can be improved
Solution: Pass string length where it is known to avoid strlen() calls,
do a few minor refactors (John Marriott).
This commit changes some calls to function `set_vim_var_string()` to pass
the string length where it is known or can be easily calculated.
In addition:
In `evalvars.c`:
* In function `set_reg_var()` turn variable `regname` into a C string
because that is how it used.
* Small cosmetics.
In `option.c`:
* Slightly refactor function `apply_optionset_autocmd()` to move some
variables closer to where they are used.
In `getchar.c`:
* Slightly refactor function `do_key_input_pre()`:
-> change call to `dict_add_string()` to `dict_add_string_len()` and
pass it the length of `buf`.
-> only call `get_vim_var_string()` once.
In `message.c`:
* Use a `string_T` to store local variable `p`.
In `normal.c`:
* Move some variables closer to where they are used.
closes: #19618
Signed-off-by: John Marriott <
basi...@internode.on.net>
Signed-off-by: Christian Brabandt <
c...@256bit.org>
diff --git a/src/evalvars.c b/src/evalvars.c
index 16dcb0282..9f0cc08c8 100644
--- a/src/evalvars.c
+++ b/src/evalvars.c
@@ -2845,16 +2845,19 @@ get_vim_var_dict(int idx)
void
set_vim_var_char(int c)
{
- char_u buf[MB_MAXBYTES + 1];
+ char_u buf[MB_MAXBYTES + 1];
+ size_t buflen;
if (has_mbyte)
- buf[(*mb_char2bytes)(c, buf)] = NUL;
+ buflen = (*mb_char2bytes)(c, buf);
else
{
buf[0] = c;
- buf[1] = NUL;
+ buflen = 1;
}
- set_vim_var_string(VV_CHAR, buf, -1);
+ buf[buflen] = NUL;
+
+ set_vim_var_string(VV_CHAR, buf, (int)buflen);
}
/*
@@ -2999,15 +3002,16 @@ reset_reg_var(void)
void
set_reg_var(int c)
{
- char_u regname;
+ char_u regname[2];
if (c == 0 || c == ' ')
- regname = '"';
+ regname[0] = '"';
else
- regname = c;
+ regname[0] = c;
+ regname[1] = NUL;
// Avoid free/alloc when the value is already right.
if (vimvars[VV_REG].vv_str == NULL || vimvars[VV_REG].vv_str[0] != c)
- set_vim_var_string(VV_REG, ®name, 1);
+ set_vim_var_string(VV_REG, regname, 1);
}
/*
@@ -4754,8 +4758,8 @@ setwinvar(typval_T *argvars, int off)
void
reset_v_option_vars(void)
{
- set_vim_var_string(VV_OPTION_NEW, NULL, -1);
- set_vim_var_string(VV_OPTION_OLD, NULL, -1);
+ set_vim_var_string(VV_OPTION_NEW, NULL, -1);
+ set_vim_var_string(VV_OPTION_OLD, NULL, -1);
set_vim_var_string(VV_OPTION_OLDLOCAL, NULL, -1);
set_vim_var_string(VV_OPTION_OLDGLOBAL, NULL, -1);
set_vim_var_string(VV_OPTION_TYPE, NULL, -1);
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
index 08ff73160..b131697f4 100644
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -2900,24 +2900,26 @@ do_ecmd(
if ((command != NULL || newlnum > (linenr_T)0)
&& *get_vim_var_str(VV_SWAPCOMMAND) == NUL)
{
- int len;
- char_u *p;
+ string_T val;
+ size_t valsize;
// Set v:swapcommand for the SwapExists autocommands.
if (command != NULL)
- len = (int)STRLEN(command) + 3;
+ valsize = (int)STRLEN(command) + 3;
else
- len = 30;
- p = alloc(len);
- if (p != NULL)
+ valsize = 30;
+ val.string = alloc(valsize);
+ if (val.string != NULL)
{
if (command != NULL)
- vim_snprintf((char *)p, len, ":%s
", command);
+ val.length = vim_snprintf_safelen((char *)val.string,
+ valsize, ":%s
", command);
else
- vim_snprintf((char *)p, len, "%ldG", (long)newlnum);
- set_vim_var_string(VV_SWAPCOMMAND, p, -1);
+ val.length = vim_snprintf_safelen((char *)val.string,
+ valsize, "%ldG", (long)newlnum);
+ set_vim_var_string(VV_SWAPCOMMAND, val.string, (int)val.length);
did_set_swapcommand = TRUE;
- vim_free(p);
+ vim_free(val.string);
}
}
#endif
diff --git a/src/ex_eval.c b/src/ex_eval.c
index 369314d22..00e4d5fcf 100644
--- a/src/ex_eval.c
+++ b/src/ex_eval.c
@@ -679,12 +679,14 @@ catch_exception(except_T *excp)
set_vim_var_list(VV_STACKTRACE, excp->stacktrace);
if (*excp->throw_name != NUL)
{
+ size_t IObufflen;
+
if (excp->throw_lnum != 0)
- vim_snprintf((char *)IObuff, IOSIZE, _("%s, line %ld"),
+ IObufflen = vim_snprintf_safelen((char *)IObuff, IOSIZE, _("%s, line %ld"),
excp->throw_name, (long)excp->throw_lnum);
else
- vim_snprintf((char *)IObuff, IOSIZE, "%s", excp->throw_name);
- set_vim_var_string(VV_THROWPOINT, IObuff, -1);
+ IObufflen = vim_snprintf_safelen((char *)IObuff, IOSIZE, "%s", excp->throw_name);
+ set_vim_var_string(VV_THROWPOINT, IObuff, (int)IObufflen);
}
else
// throw_name not set on an exception from a command that was typed.
@@ -730,14 +732,16 @@ finish_exception(except_T *excp)
set_vim_var_list(VV_STACKTRACE, caught_stack->stacktrace);
if (*caught_stack->throw_name != NUL)
{
+ size_t IObufflen;
+
if (caught_stack->throw_lnum != 0)
- vim_snprintf((char *)IObuff, IOSIZE,
+ IObufflen = vim_snprintf_safelen((char *)IObuff, IOSIZE,
_("%s, line %ld"), caught_stack->throw_name,
(long)caught_stack->throw_lnum);
else
- vim_snprintf((char *)IObuff, IOSIZE, "%s",
+ IObufflen = vim_snprintf_safelen((char *)IObuff, IOSIZE, "%s",
caught_stack->throw_name);
- set_vim_var_string(VV_THROWPOINT, IObuff, -1);
+ set_vim_var_string(VV_THROWPOINT, IObuff, (int)IObufflen);
}
else
// throw_name not set on an exception from a command that was
diff --git a/src/fold.c b/src/fold.c
index c6eb08a36..9618c21c6 100644
--- a/src/fold.c
+++ b/src/fold.c
@@ -1950,7 +1950,7 @@ get_foldtext(
level = (int)sizeof(dashes) - 1;
vim_memset(dashes, '-', (size_t)level);
dashes[level] = NUL;
- set_vim_var_string(VV_FOLDDASHES, dashes, -1);
+ set_vim_var_string(VV_FOLDDASHES, dashes, level);
set_vim_var_nr(VV_FOLDLEVEL, (long)level);
// skip evaluating 'foldtext' on errors
diff --git a/src/getchar.c b/src/getchar.c
index e825498c5..b4ef9ce82 100644
--- a/src/getchar.c
+++ b/src/getchar.c
@@ -2214,6 +2214,7 @@ do_key_input_pre(int c)
{
int res = c;
char_u buf[MB_MAXBYTES + 1];
+ size_t buflen;
char_u curr_mode[MODE_MAX_LENGTH];
int save_State = State;
save_v_event_T save_v_event;
@@ -2228,10 +2229,11 @@ do_key_input_pre(int c)
buf[0] = K_SPECIAL;
buf[1] = KEY2TERMCAP0(c);
buf[2] = KEY2TERMCAP1(c);
- buf[3] = NUL;
+ buflen = 3;
}
else
- buf[(*mb_char2bytes)(c, buf)] = NUL;
+ buflen = (*mb_char2bytes)(c, buf);
+ buf[buflen] = NUL;
typedchars[typedchars_pos] = NUL;
vim_unescape_csi(typedchars);
@@ -2240,29 +2242,29 @@ do_key_input_pre(int c)
// Lock the text to avoid weird things from happening.
++textlock;
- set_vim_var_string(VV_CHAR, buf, -1); // set v:char
+ set_vim_var_string(VV_CHAR, buf, (int)buflen); // set v:char
v_event = get_v_event(&save_v_event);
(void)dict_add_bool(v_event, "typed", KeyTyped);
- (void)dict_add_string(v_event, "typedchar", typedchars);
+ (void)dict_add_string_len(v_event, "typedchar", typedchars, typedchars_pos);
- if (apply_autocmds(EVENT_KEYINPUTPRE, curr_mode, curr_mode, FALSE, curbuf)
- && STRCMP(buf, get_vim_var_str(VV_CHAR)) != 0)
+ if (apply_autocmds(EVENT_KEYINPUTPRE, curr_mode, curr_mode, FALSE, curbuf))
{
+ string_T v_char;
+
// Get the value of v:char. It may be empty or more than one
// character. Only use it when changed, otherwise continue with the
// original character.
- char_u *v_char;
- size_t v_charlen;
-
- v_char = get_vim_var_str(VV_CHAR);
- v_charlen = STRLEN(v_char);
-
- // Convert special bytes when it is special string.
- if (v_charlen >= 3 && v_char[0] == K_SPECIAL)
- res = TERMCAP2KEY(v_char[1], v_char[2]);
- else if (v_charlen > 0)
- res = PTR2CHAR(v_char);
+ v_char.string = get_vim_var_str(VV_CHAR);
+ if (STRCMP(buf, v_char.string) != 0)
+ {
+ v_char.length = STRLEN(v_char.string);
+ // Convert special bytes when it is special string.
+ if (v_char.length >= 3 && v_char.string[0] == K_SPECIAL)
+ res = TERMCAP2KEY(v_char.string[1], v_char.string[2]);
+ else if (v_char.length > 0)
+ res = PTR2CHAR(v_char.string);
+ }
}
restore_v_event(v_event, &save_v_event);
diff --git a/src/if_xcmdsrv.c b/src/if_xcmdsrv.c
index dba97be2c..070e0db09 100644
--- a/src/if_xcmdsrv.c
+++ b/src/if_xcmdsrv.c
@@ -311,10 +311,13 @@ DoRegisterName(Display *dpy, char_u *name)
if (!got_x_error)
{
+ size_t namelen;
+
+ namelen = STRLEN(name);
# ifdef FEAT_EVAL
- set_vim_var_string(VV_SEND_SERVER, name, -1);
+ set_vim_var_string(VV_SEND_SERVER, name, (int)namelen);
# endif
- serverName = vim_strsave(name);
+ serverName = vim_strnsave(name, namelen);
need_maketitle = TRUE;
return 0;
}
diff --git a/src/main.c b/src/main.c
index ec046f3b2..10828933d 100644
--- a/src/main.c
+++ b/src/main.c
@@ -2849,11 +2849,14 @@ scripterror:
// one.
if (parmp->n_commands > 0)
{
- p = alloc(STRLEN(parmp->commands[0]) + 3);
+ size_t plen;
+
+ plen = STRLEN(parmp->commands[0]) + 2;
+ p = alloc(plen + 1);
if (p != NULL)
{
sprintf((char *)p, ":%s
", parmp->commands[0]);
- set_vim_var_string(VV_SWAPCOMMAND, p, -1);
+ set_vim_var_string(VV_SWAPCOMMAND, p, (int)plen);
vim_free(p);
}
}
diff --git a/src/message.c b/src/message.c
index 85beaa7c7..ac25fe322 100644
--- a/src/message.c
+++ b/src/message.c
@@ -2851,26 +2851,30 @@ inc_msg_scrolled(void)
#ifdef FEAT_EVAL
if (*get_vim_var_str(VV_SCROLLSTART) == NUL)
{
- char_u *p = SOURCING_NAME;
+ string_T p = {SOURCING_NAME, 0};
char_u *tofree = NULL;
- int len;
// v:scrollstart is empty, set it to the script/function name and line
// number
- if (p == NULL)
- p = (char_u *)_("Unknown");
+ if (p.string == NULL)
+ {
+ p.string = (char_u *)_("Unknown");
+ p.length = STRLEN(p.string);
+ }
else
{
- len = (int)STRLEN(p) + 40;
- tofree = alloc(len);
+ size_t tofreesize;
+
+ tofreesize = (int)STRLEN(p.string) + 40;
+ tofree = alloc(tofreesize);
if (tofree != NULL)
{
- vim_snprintf((char *)tofree, len, _("%s line %ld"),
- p, (long)SOURCING_LNUM);
- p = tofree;
+ p.length = vim_snprintf_safelen((char *)tofree, tofreesize,
+ _("%s line %ld"), p.string, (long)SOURCING_LNUM);
+ p.string = tofree;
}
}
- set_vim_var_string(VV_SCROLLSTART, p, -1);
+ set_vim_var_string(VV_SCROLLSTART, p.string, (int)p.length);
vim_free(tofree);
}
#endif
diff --git a/src/normal.c b/src/normal.c
index 42e9eafec..e6923c0bc 100644
--- a/src/normal.c
+++ b/src/normal.c
@@ -6492,16 +6492,16 @@ nv_operator(cmdarg_T *cap)
static void
set_op_var(int optype)
{
- char_u opchars[3];
-
if (optype == OP_NOP)
set_vim_var_string(VV_OP, NULL, 0);
else
{
+ char_u opchars[3];
+
opchars[0] = get_op_char(optype);
opchars[1] = get_extra_op_char(optype);
opchars[2] = NUL;
- set_vim_var_string(VV_OP, opchars, -1);
+ set_vim_var_string(VV_OP, opchars, 2);
}
}
#endif
diff --git a/src/option.c b/src/option.c
index a56dfa3ae..68de5b557 100644
--- a/src/option.c
+++ b/src/option.c
@@ -3258,41 +3258,49 @@ apply_optionset_autocmd(
long newval,
char *errmsg)
{
- char_u buf_old[12], buf_old_global[12], buf_new[12], buf_type[12];
+ char_u buf_old[12], buf_new[12], buf_type[12];
+ size_t buf_oldlen;
+ size_t len;
// Don't do this while starting up, failure or recursively.
if (starting || errmsg != NULL || *get_vim_var_str(VV_OPTION_TYPE) != NUL)
return;
- vim_snprintf((char *)buf_old, sizeof(buf_old), "%ld", oldval);
- vim_snprintf((char *)buf_old_global, sizeof(buf_old_global), "%ld",
- oldval_g);
- vim_snprintf((char *)buf_new, sizeof(buf_new), "%ld", newval);
- vim_snprintf((char *)buf_type, sizeof(buf_type), "%s",
+ len = vim_snprintf_safelen((char *)buf_new, sizeof(buf_new), "%ld", newval);
+ set_vim_var_string(VV_OPTION_NEW, buf_new, (int)len);
+ len = vim_snprintf_safelen((char *)buf_type, sizeof(buf_type), "%s",
(opt_flags & OPT_LOCAL) ? "local" : "global");
- set_vim_var_string(VV_OPTION_NEW, buf_new, -1);
- set_vim_var_string(VV_OPTION_OLD, buf_old, -1);
- set_vim_var_string(VV_OPTION_TYPE, buf_type, -1);
+ set_vim_var_string(VV_OPTION_TYPE, buf_type, (int)len);
+
+ buf_oldlen = vim_snprintf_safelen((char *)buf_old, sizeof(buf_old), "%ld", oldval);
+ set_vim_var_string(VV_OPTION_OLD, buf_old, (int)buf_oldlen);
+
if (opt_flags & OPT_LOCAL)
{
- set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setlocal", -1);
- set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
+ set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setlocal", STRLEN_LITERAL("setlocal"));
+ set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, (int)buf_oldlen);
}
if (opt_flags & OPT_GLOBAL)
{
- set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setglobal", -1);
- set_vim_var_string(VV_OPTION_OLDGLOBAL, buf_old, -1);
+ set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setglobal", STRLEN_LITERAL("setglobal"));
+ set_vim_var_string(VV_OPTION_OLDGLOBAL, buf_old, (int)buf_oldlen);
}
if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
{
- set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"set", -1);
- set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
- set_vim_var_string(VV_OPTION_OLDGLOBAL, buf_old_global, -1);
+ char_u buf_old_global[12];
+ size_t buf_old_globallen;
+
+ buf_old_globallen = vim_snprintf_safelen((char *)buf_old_global,
+ sizeof(buf_old_global), "%ld", oldval_g);
+
+ set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"set", STRLEN_LITERAL("set"));
+ set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, (int)buf_oldlen);
+ set_vim_var_string(VV_OPTION_OLDGLOBAL, buf_old_global, (int)buf_old_globallen);
}
if (opt_flags & OPT_MODELINE)
{
- set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"modeline", -1);
- set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, -1);
+ set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"modeline", STRLEN_LITERAL("modeline"));
+ set_vim_var_string(VV_OPTION_OLDLOCAL, buf_old, (int)buf_oldlen);
}
apply_autocmds(EVENT_OPTIONSET, (char_u *)options[opt_idx].fullname,
NULL, FALSE, NULL);
diff --git a/src/optionstr.c b/src/optionstr.c
index a34d86a01..b94824d45 100644
--- a/src/optionstr.c
+++ b/src/optionstr.c
@@ -221,32 +221,35 @@ trigger_optionset_string(
return;
char_u buf_type[7];
+ size_t buf_typelen;
+ size_t oldvallen;
- sprintf((char *)buf_type, "%s",
- (opt_flags & OPT_LOCAL) ? "local" : "global");
- set_vim_var_string(VV_OPTION_OLD, oldval, -1);
+ oldvallen = STRLEN(oldval);
+ set_vim_var_string(VV_OPTION_OLD, oldval, (int)oldvallen);
set_vim_var_string(VV_OPTION_NEW, newval, -1);
- set_vim_var_string(VV_OPTION_TYPE, buf_type, -1);
+ buf_typelen = vim_snprintf_safelen((char *)buf_type, sizeof(buf_type),
+ "%s", (opt_flags & OPT_LOCAL) ? "local" : "global");
+ set_vim_var_string(VV_OPTION_TYPE, buf_type, (int)buf_typelen);
if (opt_flags & OPT_LOCAL)
{
- set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setlocal", -1);
- set_vim_var_string(VV_OPTION_OLDLOCAL, oldval, -1);
+ set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setlocal", STRLEN_LITERAL("setlocal"));
+ set_vim_var_string(VV_OPTION_OLDLOCAL, oldval, (int)oldvallen);
}
if (opt_flags & OPT_GLOBAL)
{
- set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setglobal", -1);
- set_vim_var_string(VV_OPTION_OLDGLOBAL, oldval, -1);
+ set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"setglobal", STRLEN_LITERAL("setglobal"));
+ set_vim_var_string(VV_OPTION_OLDGLOBAL, oldval, (int)oldvallen);
}
if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
{
- set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"set", -1);
+ set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"set", STRLEN_LITERAL("set"));
set_vim_var_string(VV_OPTION_OLDLOCAL, oldval_l, -1);
set_vim_var_string(VV_OPTION_OLDGLOBAL, oldval_g, -1);
}
if (opt_flags & OPT_MODELINE)
{
- set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"modeline", -1);
- set_vim_var_string(VV_OPTION_OLDLOCAL, oldval, -1);
+ set_vim_var_string(VV_OPTION_COMMAND, (char_u *)"modeline", STRLEN_LITERAL("modeline"));
+ set_vim_var_string(VV_OPTION_OLDLOCAL, oldval, (int)oldvallen);
}
apply_autocmds(EVENT_OPTIONSET,
get_option_fullname(opt_idx), NULL, FALSE,
diff --git a/src/tag.c b/src/tag.c
index be64ea5ff..d3e27e602 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -745,6 +745,9 @@ do_tag(
else
{
int ask_for_selection = FALSE;
+#if defined(FEAT_EVAL)
+ size_t IObufflen;
+#endif
#ifdef FEAT_CSCOPE
if (type == DT_CSCOPE && num_matches > 1)
@@ -880,8 +883,8 @@ do_tag(
#if defined(FEAT_EVAL)
// Let the SwapExists event know what tag we are jumping to.
- vim_snprintf((char *)IObuff, IOSIZE, ":ta %s
", name);
- set_vim_var_string(VV_SWAPCOMMAND, IObuff, -1);
+ IObufflen = vim_snprintf_safelen((char *)IObuff, IOSIZE, ":ta %s
", name);
+ set_vim_var_string(VV_SWAPCOMMAND, IObuff, (int)IObufflen);
#endif
/*
diff --git a/src/version.c b/src/version.c
index f745f3a7d..ff021ff19 100644
--- a/src/version.c
+++ b/src/version.c
@@ -734,6 +734,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 126,
/**/
125,
/**/