From 4c48f19e51635b5b67dd2bb97e9240e9cc369540 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 19 Mar 2026 18:31:11 +0800 Subject: [PATCH] vim-patch:partial:9.2.0193: using copy_option_part() can be improved (#38369) Problem: using copy_option_part() can be improved Solution: Refactor and use the return value of copy_option_part() to avoid strlen() calls (John Marriott). In addition, this commit includes the following changes: memline.c: - In recover_names(): - Replace calls to vim_strsave() with vim_strnsave() for the literal strings - Use a string_T to store local variable dir_name. bufwrite.c: - In buf_write() - move variable wp to where it is used. help.c: - In fix_help_buffer(): - replace call to add_pathsep() with after_pathsep() optionstr.c: - In export_myvimdir(): - use a string_T to store local variable buf - replace call to add_pathsep() with after_pathsep() scriptfile.c: - In do_in_path(): - use a string_T to store local variable buf - measure the lengths of prefix and name once before the while loop - replace call to add_pathsep() with after_pathsep() - move some variables closer to where they are used spellfile.c: - In init_spellfile(): - use a string_T to store local variable buf closes: vim/vim#19725 https://github.com/vim/vim/commit/a74e5fc5b9cc3c1596f34df9d45e33f049162cfe Co-authored-by: John Marriott --- src/nvim/change.c | 5 +++-- src/nvim/indent_c.c | 11 ++++++----- src/nvim/memline.c | 36 ++++++++++++++++++------------------ src/nvim/runtime.c | 14 ++++++-------- src/nvim/spell.c | 7 +++---- 5 files changed, 36 insertions(+), 37 deletions(-) diff --git a/src/nvim/change.c b/src/nvim/change.c index 8f4fd4b864..8d905c368d 100644 --- a/src/nvim/change.c +++ b/src/nvim/change.c @@ -1242,6 +1242,7 @@ bool open_line(int dir, int flags, int second_line_indent, bool *did_do_comment) char *lead_repl = NULL; // replaces comment leader int lead_repl_len = 0; // length of *lead_repl char lead_middle[COM_MAX_LEN]; // middle-comment string + int lead_middle_len; // length of the lead_middle char lead_end[COM_MAX_LEN]; // end-comment string char *comment_end = NULL; // where lead_end has been found int extra_space = false; // append extra space @@ -1276,7 +1277,7 @@ bool open_line(int dir, int flags, int second_line_indent, bool *did_do_comment) } p++; } - copy_option_part(&p, lead_middle, COM_MAX_LEN, ","); + lead_middle_len = (int)copy_option_part(&p, lead_middle, COM_MAX_LEN, ","); while (*p && p[-1] != ':') { // find end of end flags // Check whether we allow automatic ending of comments @@ -1307,7 +1308,7 @@ bool open_line(int dir, int flags, int second_line_indent, bool *did_do_comment) if (lead_len > 0) { if (current_flag == COM_START) { lead_repl = lead_middle; - lead_repl_len = (int)strlen(lead_middle); + lead_repl_len = lead_middle_len; } // If we have hit RETURN immediately after the start diff --git a/src/nvim/indent_c.c b/src/nvim/indent_c.c index 40e22f8c9a..e989d01073 100644 --- a/src/nvim/indent_c.c +++ b/src/nvim/indent_c.c @@ -2057,6 +2057,7 @@ int get_c_indent(void) char lead_start[COM_MAX_LEN]; // start-comment string char lead_middle[COM_MAX_LEN]; // middle-comment string char lead_end[COM_MAX_LEN]; // end-comment string + int lead_end_len; char *p; int start_align = 0; int start_off = 0; @@ -2089,20 +2090,20 @@ int get_c_indent(void) if (*p == ':') { p++; } - (void)copy_option_part(&p, lead_end, COM_MAX_LEN, ","); + lead_end_len = (int)copy_option_part(&p, lead_end, COM_MAX_LEN, ","); if (what == COM_START) { STRCPY(lead_start, lead_end); - lead_start_len = (int)strlen(lead_start); + lead_start_len = lead_end_len; start_off = off; start_align = align; } else if (what == COM_MIDDLE) { STRCPY(lead_middle, lead_end); - lead_middle_len = (int)strlen(lead_middle); + lead_middle_len = lead_end_len; } else if (what == COM_END) { // If our line starts with the middle comment string, line it // up with the comment opener per the 'comments' option. if (strncmp(theline, lead_middle, (size_t)lead_middle_len) == 0 - && strncmp(theline, lead_end, strlen(lead_end)) != 0) { + && strncmp(theline, lead_end, (size_t)lead_end_len) != 0) { done = true; if (curwin->w_cursor.lnum > 1) { // If the start comment string matches in the previous @@ -2133,7 +2134,7 @@ int get_c_indent(void) // If our line starts with the end comment string, line it up // with the middle comment if (strncmp(theline, lead_middle, (size_t)lead_middle_len) != 0 - && strncmp(theline, lead_end, strlen(lead_end)) == 0) { + && strncmp(theline, lead_end, (size_t)lead_end_len) == 0) { amount = get_indent_lnum(curwin->w_cursor.lnum - 1); // XXX if (off != 0) { diff --git a/src/nvim/memline.c b/src/nvim/memline.c index f16514e169..a6bc0dd543 100644 --- a/src/nvim/memline.c +++ b/src/nvim/memline.c @@ -1305,42 +1305,42 @@ int recover_names(char *fname, bool do_list, list_T *ret_list, int nr, char **fn // Do the loop for every directory in 'directory'. // First allocate some memory to put the directory name in. - char *dir_name = xmalloc(strlen(p_dir) + 1); + String dir_name; + dir_name.data = xmalloc(strlen(p_dir) + 1); char *dirp = p_dir; while (*dirp) { // Isolate a directory name from *dirp and put it in dir_name (we know // it is large enough, so use 31000 for length). // Advance dirp to next directory name. - copy_option_part(&dirp, dir_name, 31000, ","); + dir_name.size = copy_option_part(&dirp, dir_name.data, 31000, ","); - if (dir_name[0] == '.' && dir_name[1] == NUL) { // check current dir + if (dir_name.data[0] == '.' && dir_name.data[1] == NUL) { // check current dir if (fname == NULL) { - names[0] = xstrdup("*.sw?"); + names[0] = xmemdupz(S_LEN("*.sw?")); // For Unix names starting with a dot are special. MS-Windows // supports this too, on some file systems. - names[1] = xstrdup(".*.sw?"); - names[2] = xstrdup(".sw?"); + names[1] = xmemdupz(S_LEN(".*.sw?")); + names[2] = xmemdupz(S_LEN(".sw?")); num_names = 3; } else { num_names = recov_file_names(names, fname_res, true); } } else { // check directory dir_name if (fname == NULL) { - names[0] = concat_fnames(dir_name, "*.sw?", true); + names[0] = concat_fnames(dir_name.data, "*.sw?", true); // For Unix names starting with a dot are special. MS-Windows // supports this too, on some file systems. - names[1] = concat_fnames(dir_name, ".*.sw?", true); - names[2] = concat_fnames(dir_name, ".sw?", true); + names[1] = concat_fnames(dir_name.data, ".*.sw?", true); + names[2] = concat_fnames(dir_name.data, ".sw?", true); num_names = 3; } else { - int len = (int)strlen(dir_name); - p = dir_name + len; - if (after_pathsep(dir_name, p) && len > 1 && p[-1] == p[-2]) { + p = dir_name.data + dir_name.size; + if (after_pathsep(dir_name.data, p) && dir_name.size > 1 && p[-1] == p[-2]) { // Ends with '//', Use Full path for swap name - tail = make_percent_swname(dir_name, p, fname_res); + tail = make_percent_swname(dir_name.data, p, fname_res); } else { tail = path_tail(fname_res); - tail = concat_fnames(dir_name, tail, true); + tail = concat_fnames(dir_name.data, tail, true); } num_names = recov_file_names(names, tail, false); xfree(tail); @@ -1401,7 +1401,7 @@ int recover_names(char *fname, bool do_list, list_T *ret_list, int nr, char **fn dirp = ""; // stop searching } } else if (do_list) { - if (dir_name[0] == '.' && dir_name[1] == NUL) { + if (dir_name.data[0] == '.' && dir_name.data[1] == NUL) { if (fname == NULL) { msg_puts(_(" In current directory:\n")); } else { @@ -1409,7 +1409,7 @@ int recover_names(char *fname, bool do_list, list_T *ret_list, int nr, char **fn } } else { msg_puts(_(" In directory ")); - msg_home_replace(dir_name); + msg_home_replace(dir_name.data); msg_puts(":\n"); } @@ -1433,7 +1433,7 @@ int recover_names(char *fname, bool do_list, list_T *ret_list, int nr, char **fn ui_flush(); } else if (ret_list != NULL) { for (int i = 0; i < num_files; i++) { - char *name = concat_fnames(dir_name, files[i], true); + char *name = concat_fnames(dir_name.data, files[i], true); tv_list_append_allocated_string(ret_list, name); } } else { @@ -1447,7 +1447,7 @@ int recover_names(char *fname, bool do_list, list_T *ret_list, int nr, char **fn FreeWild(num_files, files); } } - xfree(dir_name); + xfree(dir_name.data); return file_count; } diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c index bf244f26d7..35b48b3ada 100644 --- a/src/nvim/runtime.c +++ b/src/nvim/runtime.c @@ -455,8 +455,7 @@ int do_in_path(const char *path, const char *prefix, char *name, int flags, char *rtp = rtp_copy; while (*rtp != NUL && (do_all || !did_one)) { // Copy the path from 'runtimepath' to buf[]. - copy_option_part(&rtp, buf, MAXPATHL, ","); - size_t buflen = strlen(buf); + size_t buflen = copy_option_part(&rtp, buf, MAXPATHL, ","); // Skip after or non-after directories. if (flags & (DIP_NOAFTER | DIP_AFTER)) { @@ -840,9 +839,9 @@ static RuntimeSearchPath runtime_search_path_build(void) static char buf[MAXPATHL]; for (char *entry = p_pp; *entry != NUL;) { char *cur_entry = entry; - copy_option_part(&entry, buf, MAXPATHL, ","); + size_t buflen = copy_option_part(&entry, buf, MAXPATHL, ","); - String the_entry = { .data = cur_entry, .size = strlen(buf) }; + String the_entry = { .data = cur_entry, .size = buflen }; kv_push(pack_entries, the_entry); map_put(String, int)(&pack_used, the_entry, 0); @@ -851,8 +850,7 @@ static RuntimeSearchPath runtime_search_path_build(void) char *rtp_entry; for (rtp_entry = p_rtp; *rtp_entry != NUL;) { char *cur_entry = rtp_entry; - copy_option_part(&rtp_entry, buf, MAXPATHL, ","); - size_t buflen = strlen(buf); + size_t buflen = copy_option_part(&rtp_entry, buf, MAXPATHL, ","); if (path_is_after(buf, buflen)) { rtp_entry = cur_entry; @@ -895,9 +893,9 @@ static RuntimeSearchPath runtime_search_path_build(void) // "after" dirs in rtp for (; *rtp_entry != NUL;) { char *cur_entry = rtp_entry; - copy_option_part(&rtp_entry, buf, MAXPATHL, ","); + size_t buflen = copy_option_part(&rtp_entry, buf, MAXPATHL, ","); size_t pos_in_rtp = (size_t)(cur_entry - p_rtp); - expand_rtp_entry(&search_path, &rtp_used, buf, path_is_after(buf, strlen(buf)), pos_in_rtp); + expand_rtp_entry(&search_path, &rtp_used, buf, path_is_after(buf, buflen), pos_in_rtp); } // strings are not owned diff --git a/src/nvim/spell.c b/src/nvim/spell.c index b4b602ebda..cb3d9a8638 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -1955,9 +1955,8 @@ char *parse_spelllang(win_T *wp) // Loop over comma separated language names. for (char *splp = spl_copy; *splp != NUL;) { // Get one language name. - copy_option_part(&splp, lang, MAXWLEN, ","); + int len = (int)copy_option_part(&splp, lang, MAXWLEN, ","); char *region = NULL; - int len = (int)strlen(lang); if (!valid_spelllang(lang)) { continue; @@ -2089,8 +2088,8 @@ char *parse_spelllang(win_T *wp) int_wordlist_spl(spf_name); } else { // One entry in 'spellfile'. - copy_option_part(&spf, spf_name, MAXPATHL - 4, ","); - strcat(spf_name, ".spl"); + int len = (int)copy_option_part(&spf, spf_name, MAXPATHL - 4, ","); + STRCPY(spf_name + len, ".spl"); int c; // If it was already found above then skip it.