Skip to content

Commit cb51add

Browse files
John Marriottchrisbra
andcommitted
patch 9.2.0291: too many strlen() calls
Problem: too many strlen() calls Solution: refactor concat_fname() and remove calls to strlen() (John Marriott) Function `concat_fnames()` can make up to 5 calls to `STRLEN()` (either directly or indirectly via `STRCAT()`). In many cases the lengths of arguments `fname1` and/or `fname2` are either known or can simply be calculated. This Commit refactors this function to accept the lengths of arguments `fname1` and `fname2` as arguments. It also adds new argument `ret` to return the resulting string as a `string_T`. Additionally: - function `add_pack_dir_to_rtp()` in `scriptfile.c`: Use a `string_T` to store local variables `new_rtp` and `afterdir`. Replace calls to `STRCAT()` with calls to `STRCPY()`. Change type of variable `keep` to `size_t` for consistency with other lengths. - function `qf_get_fnum()` in `quickfix.c`: Use a `string_T` to store local variables `ptr` and `bufname` - function `qf_push_dir()` in `quickfix.c`: Use a `string_T` to store local variable `dirname`. Replace call to `vim_strsave()` with `vim_strnsave()`. - function `qf_guess_filepath()` in `quickfix.c`: Use a `string_T` to store local variable `fullname`. - function `make_percent_swname()` in `memline.c`: Rename some variables to better reflect their use. Use a `string_T` to store local variables `d` and `fixed_name`. Slightly refactor to remove need to create an extra string. - function `get_file_in_dir()` in `memline.c`: Use a `string_T` to store local variables `tail` and `retval`. Move some variables closer to where they are used. - function `cs_resolve_file()` in `if_cscope.c`: Use a `string_T` to store local variable `csdir`. Remove one call to `STRLEN()`. - function `add_pathsep()` in `filepath.c`: Refactor and remove 1 call to `STRLEN()` - function `set_init_xdg_rtp()` in `option.c`: Use a `string_T` to store local variable `vimrc_xdg`. closes: #19854 Co-authored-by: Christian Brabandt <[email protected]> Signed-off-by: John Marriott <[email protected]> Signed-off-by: Christian Brabandt <[email protected]>
1 parent b7205b6 commit cb51add

12 files changed

Lines changed: 280 additions & 181 deletions

File tree

src/filepath.c

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3178,19 +3178,25 @@ vim_fnamencmp(char_u *x, char_u *y, size_t len)
31783178
* Only add a '/' or '\\' when 'sep' is TRUE and it is necessary.
31793179
*/
31803180
char_u *
3181-
concat_fnames(char_u *fname1, char_u *fname2, int sep)
3181+
concat_fnames(char_u *fname1, size_t fname1len, char_u *fname2, size_t fname2len, int sep, string_T *ret)
31823182
{
3183-
char_u *dest;
3184-
3185-
dest = alloc(STRLEN(fname1) + STRLEN(fname2) + 3);
3186-
if (dest == NULL)
3187-
return NULL;
3183+
ret->string = alloc(fname1len + (sep ? STRLEN_LITERAL(PATHSEPSTR) : 0) + fname2len + 1);
3184+
if (ret->string == NULL)
3185+
ret->length = 0;
3186+
else
3187+
{
3188+
STRCPY(ret->string, fname1);
3189+
ret->length = fname1len;
3190+
if (sep && *ret->string != NUL && !after_pathsep(ret->string, ret->string + ret->length))
3191+
{
3192+
STRCPY(ret->string + ret->length, PATHSEPSTR);
3193+
ret->length += STRLEN_LITERAL(PATHSEPSTR);
3194+
}
3195+
STRCPY(ret->string + ret->length, fname2);
3196+
ret->length += fname2len;
3197+
}
31883198

3189-
STRCPY(dest, fname1);
3190-
if (sep)
3191-
add_pathsep(dest);
3192-
STRCAT(dest, fname2);
3193-
return dest;
3199+
return ret->string;
31943200
}
31953201

31963202
/*
@@ -3200,8 +3206,14 @@ concat_fnames(char_u *fname1, char_u *fname2, int sep)
32003206
void
32013207
add_pathsep(char_u *p)
32023208
{
3203-
if (*p != NUL && !after_pathsep(p, p + STRLEN(p)))
3204-
STRCAT(p, PATHSEPSTR);
3209+
size_t plen;
3210+
3211+
if (*p == NUL)
3212+
return;
3213+
3214+
plen = STRLEN(p);
3215+
if (!after_pathsep(p, p + plen))
3216+
STRCPY(p + plen, PATHSEPSTR);
32053217
}
32063218

32073219
/*

src/if_cscope.c

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2413,36 +2413,43 @@ cs_reset(exarg_T *eap UNUSED)
24132413
cs_resolve_file(int i, char *name)
24142414
{
24152415
char *fullname;
2416+
string_T csdir = {NULL, 0};
2417+
size_t namelen;
2418+
size_t ppathlen = 0;
24162419
int len;
2417-
char_u *csdir = NULL;
24182420

24192421
/*
24202422
* Ppath is freed when we destroy the cscope connection.
24212423
* Fullname is freed after cs_make_vim_style_matches, after it's been
24222424
* copied into the tag buffer used by Vim.
24232425
*/
2424-
len = (int)(strlen(name) + 2);
2426+
namelen = STRLEN(name);
2427+
len = (int)namelen + 2;
24252428
if (csinfo[i].ppath != NULL)
2426-
len += (int)strlen(csinfo[i].ppath);
2429+
{
2430+
ppathlen = STRLEN(csinfo[i].ppath);
2431+
len += (int)ppathlen;
2432+
}
24272433
else if (p_csre && csinfo[i].fname != NULL)
24282434
{
24292435
// If 'cscoperelative' is set and ppath is not set, use cscope.out
24302436
// path in path resolution.
2431-
csdir = alloc(MAXPATHL);
2432-
if (csdir != NULL)
2437+
csdir.string = alloc(MAXPATHL);
2438+
if (csdir.string != NULL)
24332439
{
2434-
vim_strncpy(csdir, (char_u *)csinfo[i].fname,
2440+
vim_strncpy(csdir.string, (char_u *)csinfo[i].fname,
24352441
gettail((char_u *)csinfo[i].fname)
24362442
- (char_u *)csinfo[i].fname);
2437-
len += (int)STRLEN(csdir);
2443+
csdir.length = STRLEN(csdir.string);
2444+
len += (int)csdir.length;
24382445
}
24392446
}
24402447

24412448
// Note/example: this won't work if the cscope output already starts
24422449
// "../.." and the prefix path is also "../..". if something like this
24432450
// happens, you are screwed up and need to fix how you're using cscope.
24442451
if (csinfo[i].ppath != NULL
2445-
&& (strncmp(name, csinfo[i].ppath, strlen(csinfo[i].ppath)) != 0)
2452+
&& (strncmp(name, csinfo[i].ppath, ppathlen) != 0)
24462453
&& (name[0] != '/')
24472454
# ifdef MSWIN
24482455
&& name[0] != '\\' && name[1] != ':'
@@ -2452,18 +2459,20 @@ cs_resolve_file(int i, char *name)
24522459
if ((fullname = alloc(len)) != NULL)
24532460
(void)sprintf(fullname, "%s/%s", csinfo[i].ppath, name);
24542461
}
2455-
else if (csdir != NULL && csinfo[i].fname != NULL && *csdir != NUL)
2462+
else if (csdir.string != NULL && csinfo[i].fname != NULL && *csdir.string != NUL)
24562463
{
2464+
string_T ret;
2465+
24572466
// Check for csdir to be non empty to avoid empty path concatenated to
24582467
// cscope output.
2459-
fullname = (char *)concat_fnames(csdir, (char_u *)name, TRUE);
2468+
fullname = (char *)concat_fnames(csdir.string, csdir.length, (char_u *)name, namelen, TRUE, &ret);
24602469
}
24612470
else
24622471
{
2463-
fullname = (char *)vim_strsave((char_u *)name);
2472+
fullname = (char *)vim_strnsave((char_u *)name, namelen);
24642473
}
24652474

2466-
vim_free(csdir);
2475+
vim_free(csdir.string);
24672476
return fullname;
24682477
}
24692478

src/main.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2771,13 +2771,15 @@ command_line_scan(mparm_T *parmp)
27712771
if (parmp->diff_mode && mch_isdir(p) && GARGCOUNT > 0
27722772
&& !mch_isdir(alist_name(&GARGLIST[0])))
27732773
{
2774-
char_u *r;
2774+
char_u *tail;
2775+
string_T ret;
27752776

2776-
r = concat_fnames(p, gettail(alist_name(&GARGLIST[0])), TRUE);
2777-
if (r != NULL)
2777+
tail = gettail(alist_name(&GARGLIST[0]));
2778+
concat_fnames(p, STRLEN(p), tail, STRLEN(tail), TRUE, &ret);
2779+
if (ret.string != NULL)
27782780
{
27792781
vim_free(p);
2780-
p = r;
2782+
p = ret.string;
27812783
}
27822784
}
27832785
# endif

src/memline.c

Lines changed: 86 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1892,7 +1892,6 @@ recover_names(
18921892
{
18931893
int num_names;
18941894
char_u *(names[6]);
1895-
char_u *tail;
18961895
char_u *p;
18971896
int num_files;
18981897
int file_count = 0;
@@ -1969,20 +1968,27 @@ recover_names(
19691968
{
19701969
if (fname == NULL)
19711970
{
1971+
string_T ret;
1972+
19721973
#ifdef VMS
1973-
names[0] = concat_fnames(dir_name.string, (char_u *)"*_sw%", TRUE);
1974+
names[0] = concat_fnames(dir_name.string, dir_name.length,
1975+
(char_u *)"*_sw%", STRLEN_LITERAL("*_sw%"), TRUE, &ret);
19741976
#else
1975-
names[0] = concat_fnames(dir_name.string, (char_u *)"*.sw?", TRUE);
1977+
names[0] = concat_fnames(dir_name.string, dir_name.length,
1978+
(char_u *)"*.sw?", STRLEN_LITERAL("*.sw?"), TRUE, &ret);
19761979
#endif
19771980
#if defined(UNIX) || defined(MSWIN)
19781981
// For Unix names starting with a dot are special. MS-Windows
19791982
// supports this too, on some file systems.
1980-
names[1] = concat_fnames(dir_name.string, (char_u *)".*.sw?", TRUE);
1981-
names[2] = concat_fnames(dir_name.string, (char_u *)".sw?", TRUE);
1983+
names[1] = concat_fnames(dir_name.string, dir_name.length,
1984+
(char_u *)".*.sw?", STRLEN_LITERAL(".*.sw?"), TRUE, &ret);
1985+
names[2] = concat_fnames(dir_name.string, dir_name.length,
1986+
(char_u *)".sw?", STRLEN_LITERAL(".sw?"), TRUE, &ret);
19821987
num_names = 3;
19831988
#else
19841989
# ifdef VMS
1985-
names[1] = concat_fnames(dir_name.string, (char_u *)".*_sw%", TRUE);
1990+
names[1] = concat_fnames(dir_name.string, dir_name.length,
1991+
(char_u *)".*_sw%", STRLEN_LITERAL(".*_sw%"), TRUE, &ret);
19861992
num_names = 2;
19871993
# else
19881994
num_names = 1;
@@ -1991,6 +1997,8 @@ recover_names(
19911997
}
19921998
else
19931999
{
2000+
char_u *tail;
2001+
19942002
#if defined(UNIX) || defined(MSWIN)
19952003
p = dir_name.string + dir_name.length;
19962004
if (after_pathsep(dir_name.string, p) && dir_name.length > 1 && p[-1] == p[-2])
@@ -2001,8 +2009,11 @@ recover_names(
20012009
else
20022010
#endif
20032011
{
2012+
string_T ret;
2013+
20042014
tail = gettail(fname_res);
2005-
tail = concat_fnames(dir_name.string, tail, TRUE);
2015+
tail = concat_fnames(dir_name.string, dir_name.length,
2016+
tail, STRLEN(tail), TRUE, &ret);
20062017
}
20072018
if (tail == NULL)
20082019
num_names = 0;
@@ -2132,13 +2143,16 @@ recover_names(
21322143
#ifdef FEAT_EVAL
21332144
else if (ret_list != NULL)
21342145
{
2146+
string_T name;
2147+
21352148
for (int i = 0; i < num_files; ++i)
21362149
{
2137-
char_u *name = concat_fnames(dir_name.string, files[i], TRUE);
2138-
if (name != NULL)
2150+
concat_fnames(dir_name.string, dir_name.length,
2151+
files[i], STRLEN(files[i]), TRUE, &name);
2152+
if (name.string != NULL)
21392153
{
2140-
list_append_string(ret_list, name, -1);
2141-
vim_free(name);
2154+
list_append_string(ret_list, name.string, (int)name.length);
2155+
vim_free(name.string);
21422156
}
21432157
}
21442158
}
@@ -2166,26 +2180,26 @@ recover_names(
21662180
char_u *
21672181
make_percent_swname(char_u *dir, char_u *dir_end, char_u *name)
21682182
{
2169-
char_u *d = NULL, *s, *f;
2183+
string_T d = {NULL, 0};
2184+
string_T fixed_fname;
2185+
char_u *p;
21702186

2171-
f = fix_fname(name != NULL ? name : (char_u *)"");
2172-
if (f == NULL)
2187+
fixed_fname.string = fix_fname(name != NULL ? name : (char_u *)"");
2188+
if (fixed_fname.string == NULL)
21732189
return NULL;
21742190

2175-
s = alloc(STRLEN(f) + 1);
2176-
if (s != NULL)
2177-
{
2178-
STRCPY(s, f);
2179-
for (d = s; *d != NUL; MB_PTR_ADV(d))
2180-
if (vim_ispathsep(*d))
2181-
*d = '%';
2182-
2183-
dir_end[-1] = NUL; // remove one trailing slash
2184-
d = concat_fnames(dir, s, TRUE);
2185-
vim_free(s);
2186-
}
2187-
vim_free(f);
2188-
return d;
2191+
for (p = fixed_fname.string; *p != NUL; MB_PTR_ADV(p))
2192+
if (vim_ispathsep(*p))
2193+
*p = '%';
2194+
fixed_fname.length = (size_t)(p - fixed_fname.string);
2195+
2196+
// remove one trailing slash
2197+
p = &dir_end[-1];
2198+
*p = NUL;
2199+
concat_fnames(dir, (size_t)(p - dir), fixed_fname.string, fixed_fname.length, TRUE, &d);
2200+
vim_free(fixed_fname.string);
2201+
2202+
return d.string;
21892203
}
21902204
#endif
21912205

@@ -2432,6 +2446,7 @@ recov_file_names(char_u **names, char_u *path, int prepend_dot)
24322446

24332447
curbuf->b_shortname = FALSE;
24342448
#endif
2449+
string_T ret;
24352450

24362451
num_names = 0;
24372452

@@ -2451,9 +2466,11 @@ recov_file_names(char_u **names, char_u *path, int prepend_dot)
24512466
* Form the normal swap file name pattern by appending ".sw?".
24522467
*/
24532468
#ifdef VMS
2454-
names[num_names] = concat_fnames(path, (char_u *)"_sw%", FALSE);
2469+
names[num_names] = concat_fnames(path, STRLEN(path),
2470+
(char_u *)"_sw%", STRLEN_LITERAL("_sw%"), FALSE, &ret);
24552471
#else
2456-
names[num_names] = concat_fnames(path, (char_u *)".sw?", FALSE);
2472+
names[num_names] = concat_fnames(path, STRLEN(path),
2473+
(char_u *)".sw?", STRLEN_LITERAL(".sw?"), FALSE, &ret);
24572474
#endif
24582475
if (names[num_names] == NULL)
24592476
goto end;
@@ -4746,45 +4763,61 @@ get_file_in_dir(
47464763
char_u *fname,
47474764
char_u *dname) // don't use "dirname", it is a global for Alpha
47484765
{
4749-
char_u *t;
4750-
char_u *tail;
4751-
char_u *retval;
4752-
int save_char;
4766+
string_T tail;
4767+
string_T retval;
47534768

4754-
tail = gettail(fname);
4769+
tail.string = gettail(fname);
4770+
tail.length = STRLEN(tail.string);
47554771

47564772
if (dname[0] == '.' && dname[1] == NUL)
4757-
retval = vim_strsave(fname);
4758-
else if (dname[0] == '.' && vim_ispathsep(dname[1]))
4773+
retval.string =
4774+
vim_strnsave(fname, (size_t)(tail.string - fname) + tail.length);
4775+
else
47594776
{
4760-
if (tail == fname) // no path before file name
4761-
retval = concat_fnames(dname + 2, tail, TRUE);
4762-
else
4777+
size_t dname_len = STRLEN(dname);
4778+
4779+
if (dname[0] == '.' && vim_ispathsep(dname[1]))
47634780
{
4764-
save_char = *tail;
4765-
*tail = NUL;
4766-
t = concat_fnames(fname, dname + 2, TRUE);
4767-
*tail = save_char;
4768-
if (t == NULL) // out of memory
4769-
retval = NULL;
4781+
if (tail.string == fname) // no path before file name
4782+
concat_fnames(dname + 2, dname_len - 2,
4783+
tail.string, tail.length, TRUE, &retval);
47704784
else
47714785
{
4772-
retval = concat_fnames(t, tail, TRUE);
4773-
vim_free(t);
4786+
int save_char;
4787+
string_T tmp;
4788+
4789+
save_char = *tail.string;
4790+
*tail.string = NUL;
4791+
concat_fnames(fname, (size_t)(tail.string - fname),
4792+
dname + 2, dname_len - 2, TRUE, &tmp);
4793+
*tail.string = save_char;
4794+
if (tmp.string == NULL) // out of memory
4795+
retval.string = NULL;
4796+
else
4797+
{
4798+
concat_fnames(tmp.string, tmp.length,
4799+
tail.string, tail.length, TRUE, &retval);
4800+
vim_free(tmp.string);
4801+
}
47744802
}
47754803
}
4804+
else
4805+
concat_fnames(dname, dname_len, tail.string, tail.length,
4806+
TRUE, &retval);
47764807
}
4777-
else
4778-
retval = concat_fnames(dname, tail, TRUE);
47794808

47804809
#ifdef MSWIN
4781-
if (retval != NULL)
4782-
for (t = gettail(retval); *t != NUL; MB_PTR_ADV(t))
4810+
if (retval.string != NULL)
4811+
{
4812+
char_u *t;
4813+
4814+
for (t = gettail(retval.string); *t != NUL; MB_PTR_ADV(t))
47834815
if (*t == ':')
47844816
*t = '%';
4817+
}
47854818
#endif
47864819

4787-
return retval;
4820+
return retval.string;
47884821
}
47894822

47904823
/*

0 commit comments

Comments
 (0)