269
269
bool dir_of_file_exists(char_u *fname)
275
p = path_tail_with_sep(fname);
271
char_u *p = path_tail_with_sep(fname);
280
retval = os_isdir(fname);
277
bool retval = os_isdir(fname);
539
536
size_t wildoff, int flags, bool didstar)
540
537
FUNC_ATTR_NONNULL_ALL
544
539
int start_len = gap->ga_len;
549
541
bool starstar = false;
550
static int stardepth = 0; /* depth for "**" expansion */
542
static int stardepth = 0; // depth for "**" expansion
552
544
/* Expanding "**" may take a long time, check for CTRL-C. */
553
545
if (stardepth > 0) {
559
/* make room for file name */
560
buf = xmalloc(STRLEN(path) + BASENAMELEN + 5);
551
// Make room for file name. When doing encoding conversion the actual
552
// length may be quite a bit longer, thus use the maximum possible length.
553
char_u *buf = xmalloc(MAXPATHL);
563
* Find the first part in the path name that contains a wildcard.
564
* When EW_ICASE is set every letter is considered to be a wildcard.
565
* Copy it into "buf", including the preceding characters.
555
// Find the first part in the path name that contains a wildcard.
556
// When EW_ICASE is set every letter is considered to be a wildcard.
557
// Copy it into "buf", including the preceding characters.
570
561
const char_u *path_end = path;
571
562
while (*path_end != NUL) {
572
563
/* May ignore a wildcard that has a backslash before it; it will
612
603
if (p[0] == '*' && p[1] == '*')
615
/* convert the file pattern to a regexp pattern */
616
starts_with_dot = (*s == '.');
617
pat = file_pat_to_reg_pat(s, e, NULL, FALSE);
606
// convert the file pattern to a regexp pattern
607
int starts_with_dot = (*s == '.');
608
char_u *pat = file_pat_to_reg_pat(s, e, NULL, false);
618
609
if (pat == NULL) {
645
636
if (!didstar && stardepth < 100 && starstar && e - s == 2
646
637
&& *path_end == '/') {
647
638
STRCPY(s, path_end + 1);
649
(void)do_path_expand(gap, buf, (int)(s - buf), flags, true);
640
(void)do_path_expand(gap, buf, (size_t)(s - buf), flags, true);
703
694
vim_regfree(regmatch.regprog);
705
matches = gap->ga_len - start_len;
696
size_t matches = (size_t)(gap->ga_len - start_len);
707
698
qsort(((char_u **)gap->ga_data) + start_len, matches,
708
sizeof(char_u *), pstrcmp);
699
sizeof(char_u *), pstrcmp);
736
728
static bool is_unique(char_u *maybe_unique, garray_T *gap, int i)
740
char_u **other_paths = (char_u **)gap->ga_data;
730
char_u **other_paths = (char_u **)gap->ga_data;
743
732
for (int j = 0; j < gap->ga_len; j++) {
745
continue; /* don't compare it with itself */
747
candidate_len = (int)STRLEN(maybe_unique);
748
other_path_len = (int)STRLEN(other_paths[j]);
749
if (other_path_len < candidate_len)
750
continue; /* it's different when it's shorter */
752
rival = other_paths[j] + other_path_len - candidate_len;
734
continue; // don't compare it with itself
736
size_t candidate_len = STRLEN(maybe_unique);
737
size_t other_path_len = STRLEN(other_paths[j]);
738
if (other_path_len < candidate_len) {
739
continue; // it's different when it's shorter
741
char_u *rival = other_paths[j] + other_path_len - candidate_len;
753
742
if (fnamecmp(maybe_unique, rival) == 0
754
&& (rival == other_paths[j] || vim_ispathsep(*(rival - 1))))
755
return false; /* match */
743
&& (rival == other_paths[j] || vim_ispathsep(*(rival - 1)))) {
744
return false; // match
758
return true; /* no match found */
747
return true; // no match found
770
759
static void expand_path_option(char_u *curdir, garray_T *gap)
772
char_u *path_option = *curbuf->b_p_path == NUL
773
? p_path : curbuf->b_p_path;
777
buf = xmalloc(MAXPATHL);
761
char_u *path_option = *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path;
762
char_u *buf = xmalloc(MAXPATHL);
779
764
while (*path_option != NUL) {
780
765
copy_option_part(&path_option, buf, MAXPATHL, " ,");
786
771
if (curbuf->b_ffname == NULL)
788
773
char_u *p = path_tail(curbuf->b_ffname);
789
len = (int)(p - curbuf->b_ffname);
790
if (len + (int)STRLEN(buf) >= MAXPATHL)
774
size_t len = (size_t)(p - curbuf->b_ffname);
775
if (len + STRLEN(buf) >= MAXPATHL) {
795
781
STRMOVE(buf + len, buf + 2);
796
783
memmove(buf, curbuf->b_ffname, len);
797
784
simplify_filename(buf);
798
} else if (buf[0] == NUL)
799
/* relative to current directory */
801
else if (path_with_url((char *)buf))
802
/* URL can't be used here */
804
else if (!path_is_absolute_path(buf)) {
805
/* Expand relative path to their full path equivalent */
806
len = (int)STRLEN(curdir);
807
if (len + (int)STRLEN(buf) + 3 > MAXPATHL)
785
} else if (buf[0] == NUL) {
786
STRCPY(buf, curdir); // relative to current directory
787
} else if (path_with_url((char *)buf)) {
788
continue; // URL can't be used here
789
} else if (!path_is_absolute_path(buf)) {
790
// Expand relative path to their full path equivalent
791
size_t len = STRLEN(curdir);
792
if (len + STRLEN(buf) + 3 > MAXPATHL) {
809
795
STRMOVE(buf + len + 1, buf);
810
796
STRCPY(buf, curdir);
811
797
buf[len] = PATHSEP;
860
846
static void uniquefy_paths(garray_T *gap, char_u *pattern)
863
char_u **fnames = (char_u **)gap->ga_data;
848
char_u **fnames = (char_u **)gap->ga_data;
864
849
bool sort_again = false;
866
char_u *file_pattern;
868
850
regmatch_T regmatch;
869
851
garray_T path_ga;
870
char_u **in_curdir = NULL;
852
char_u **in_curdir = NULL;
873
855
ga_remove_duplicate_strings(gap);
874
856
ga_init(&path_ga, (int)sizeof(char_u *), 1);
877
* We need to prepend a '*' at the beginning of file_pattern so that the
878
* regex matches anywhere in the path. FIXME: is this valid for all
881
len = (int)STRLEN(pattern);
882
file_pattern = xmalloc(len + 2);
858
// We need to prepend a '*' at the beginning of file_pattern so that the
859
// regex matches anywhere in the path. FIXME: is this valid for all
860
// possible patterns?
861
size_t len = STRLEN(pattern);
862
char_u *file_pattern = xmalloc(len + 2);
883
863
file_pattern[0] = '*';
884
864
file_pattern[1] = NUL;
885
865
STRCAT(file_pattern, pattern);
886
pat = file_pat_to_reg_pat(file_pattern, NULL, NULL, TRUE);
866
char_u *pat = file_pat_to_reg_pat(file_pattern, NULL, NULL, true);
887
867
xfree(file_pattern);
894
874
if (regmatch.regprog == NULL)
897
curdir = xmalloc(MAXPATHL);
877
char_u *curdir = xmalloc(MAXPATHL);
898
878
os_dirname(curdir, MAXPATHL);
899
879
expand_path_option(curdir, &path_ga);
901
in_curdir = xcalloc(gap->ga_len, sizeof(char_u *));
881
in_curdir = xcalloc((size_t)gap->ga_len, sizeof(char_u *));
903
883
for (int i = 0; i < gap->ga_len && !got_int; i++) {
904
884
char_u *path = fnames[i];
1112
1092
int gen_expand_wildcards(int num_pat, char_u **pat, int *num_file,
1113
1093
char_u ***file, int flags)
1118
1097
static bool recursive = false;
1120
1099
bool did_expand_in_path = false;
1139
1118
* avoids starting the shell for each argument separately.
1140
1119
* For `=expr` do use the internal function.
1142
for (i = 0; i < num_pat; i++) {
1121
for (int i = 0; i < num_pat; i++) {
1143
1122
if (has_special_wildchar(pat[i])
1144
&& !(vim_backtick(pat[i]) && pat[i][1] == '=')
1123
&& !(vim_backtick(pat[i]) && pat[i][1] == '=')) {
1146
1124
return mch_expand_wildcards(num_pat, pat, num_file, file, flags);
1155
1134
ga_init(&ga, (int)sizeof(char_u *), 30);
1157
for (i = 0; i < num_pat; ++i) {
1136
for (int i = 0; i < num_pat; ++i) {
1161
if (vim_backtick(p))
1140
if (vim_backtick(p)) {
1162
1141
add_pat = expand_backtick(&ga, p, flags);
1165
* First expand environment variables, "~/" and "~user/".
1142
if (add_pat == -1) {
1144
FreeWild(ga.ga_len, (char_u **)ga.ga_data);
1150
// First expand environment variables, "~/" and "~user/".
1167
1151
if (has_env_var(p) || *p == '~') {
1168
1152
p = expand_env_save_opt(p, true);
1206
1190
recursive = true;
1207
1191
did_expand_in_path = true;
1209
add_pat = path_expand(&ga, p, flags);
1193
size_t tmp_add_pat = path_expand(&ga, p, flags);
1194
assert(tmp_add_pat <= INT_MAX);
1195
add_pat = (int)tmp_add_pat;
1246
1232
return *p == '`' && *(p + 1) != NUL && *(p + STRLEN(p) - 1) == '`';
1250
* Expand an item in `backticks` by executing it as a command.
1251
* Currently only works when pat[] starts and ends with a `.
1252
* Returns number of file names found.
1235
// Expand an item in `backticks` by executing it as a command.
1236
// Currently only works when pat[] starts and ends with a `.
1237
// Returns number of file names found, -1 if an error is encountered.
1238
static int expand_backtick(
1258
1241
int flags /* EW_* flags */
1267
/* Create the command: lop off the backticks. */
1268
cmd = vim_strnsave(pat + 1, (int)STRLEN(pat) - 2);
1248
// Create the command: lop off the backticks.
1249
char_u *cmd = vim_strnsave(pat + 1, STRLEN(pat) - 2);
1270
1251
if (*cmd == '=') /* `={expr}`: Expand expression */
1271
1252
buffer = eval_to_string(cmd + 1, &p, TRUE);
1552
1533
if (options & FNAME_EXP) {
1553
file_name = find_file_in_path(ptr, len, options & ~FNAME_MESS,
1534
file_name = find_file_in_path(ptr, len, options & ~FNAME_MESS, true,
1557
1538
* If the file could not be found in a normal way, try applying
1627
1608
/// @param force is a flag to force expanding even if the path is absolute
1629
1610
/// @return FAIL for failure, OK otherwise
1630
int vim_FullName(const char *fname, char *buf, int len, bool force)
1611
int vim_FullName(const char *fname, char *buf, size_t len, bool force)
1631
1612
FUNC_ATTR_NONNULL_ARG(2)
1633
1614
int retval = OK;
1776
1757
int pathcmp(const char *p, const char *q, int maxlen)
1780
1761
const char *s = NULL;
1782
for (i = 0; maxlen < 0 || i < maxlen; i += MB_PTR2LEN((char_u *)p + i)) {
1763
for (i = 0, j = 0; maxlen < 0 || (i < maxlen && j < maxlen);) {
1783
1764
c1 = PTR2CHAR((char_u *)p + i);
1784
c2 = PTR2CHAR((char_u *)q + i);
1765
c2 = PTR2CHAR((char_u *)q + j);
1786
1767
/* End of "p": check if "q" also ends or just has a slash. */
1787
1768
if (c1 == NUL) {
1788
1769
if (c2 == NUL) /* full match */
1811
1793
return p_fic ? vim_toupper(c1) - vim_toupper(c2)
1812
1794
: c1 - c2; /* no match */
1797
i += MB_PTR2LEN((char_u *)p + i);
1798
j += MB_PTR2LEN((char_u *)q + j);
1815
if (s == NULL) /* "i" ran into "maxlen" */
1800
if (s == NULL) { // "i" or "j" ran into "maxlen"
1818
1804
c1 = PTR2CHAR((char_u *)s + i);
1819
1805
c2 = PTR2CHAR((char_u *)s + i + MB_PTR2LEN((char_u *)s + i));
2009
1995
int match_suffix(char_u *fname)
2011
int fnamelen, setsuflen;
2013
#define MAXSUFLEN 30 /* maximum length of a file suffix */
1997
#define MAXSUFLEN 30 // maximum length of a file suffix
2014
1998
char_u suf_buf[MAXSUFLEN];
2016
fnamelen = (int)STRLEN(fname);
2018
for (setsuf = p_su; *setsuf; ) {
2000
size_t fnamelen = STRLEN(fname);
2001
size_t setsuflen = 0;
2002
for (char_u *setsuf = p_su; *setsuf; ) {
2019
2003
setsuflen = copy_option_part(&setsuf, suf_buf, MAXSUFLEN, ".,");
2020
2004
if (setsuflen == 0) {
2021
2005
char_u *tail = path_tail(fname);
2029
if (fnamelen >= setsuflen
2030
&& fnamencmp(suf_buf, fname + fnamelen - setsuflen,
2031
(size_t)setsuflen) == 0)
2013
if (fnamelen >= setsuflen &&
2014
fnamencmp(suf_buf, fname + fnamelen - setsuflen, setsuflen) == 0) {
2041
2025
/// @param directory Directory name, relative to current directory.
2042
2026
/// @return `FAIL` for failure, `OK` for success.
2043
int path_full_dir_name(char *directory, char *buffer, int len)
2027
int path_full_dir_name(char *directory, char *buffer, size_t len)
2045
2029
int SUCCESS = 0;
2046
2030
int retval = OK;
2083
2067
// Append to_append to path with a slash in between.
2084
2068
// Append to_append to path with a slash in between.
2085
int append_path(char *path, const char *to_append, int max_len)
2069
int append_path(char *path, const char *to_append, size_t max_len)
2087
int current_length = STRLEN(path);
2088
int to_append_length = STRLEN(to_append);
2071
size_t current_length = strlen(path);
2072
size_t to_append_length = strlen(to_append);
2090
2074
// Do not append empty strings.
2091
2075
if (to_append_length == 0) {
2121
2105
/// Expand a given file to its absolute path.
2123
/// @param fname The filename which should be expanded.
2124
/// @param buf Buffer to store the absolute path of `fname`.
2125
/// @param len Length of `buf`.
2126
/// @param force Also expand when `fname` is already absolute.
2127
/// @return `FAIL` for failure, `OK` for success.
2128
static int path_get_absolute_path(const char_u *fname, char_u *buf, int len, int force)
2107
/// @param fname filename which should be expanded.
2108
/// @param buf buffer to store the absolute path of "fname".
2109
/// @param len length of "buf".
2110
/// @param force also expand when "fname" is already absolute.
2112
/// @return FAIL for failure, OK for success.
2113
static int path_get_absolute_path(const char_u *fname, char_u *buf,
2114
size_t len, int force)