aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/path.c
diff options
context:
space:
mode:
authorJosh Rahm <rahm@google.com>2022-10-11 19:00:52 +0000
committerJosh Rahm <rahm@google.com>2022-10-11 19:00:52 +0000
commit21e2e46242033c7aaa6ccfb23e256680816c063c (patch)
treef089522cfb145d6e9c8a86a01d8e454ce5501e20 /src/nvim/path.c
parent179d3ed87b17988f5fe00d8b99f2611a28212be7 (diff)
parent760b399f6c0c6470daa0663752bd22886997f9e6 (diff)
downloadrneovim-floattitle.tar.gz
rneovim-floattitle.tar.bz2
rneovim-floattitle.zip
Merge remote-tracking branch 'upstream/master' into floattitlefloattitle
Diffstat (limited to 'src/nvim/path.c')
-rw-r--r--src/nvim/path.c677
1 files changed, 334 insertions, 343 deletions
diff --git a/src/nvim/path.c b/src/nvim/path.c
index 1500254de5..9295905415 100644
--- a/src/nvim/path.c
+++ b/src/nvim/path.c
@@ -33,7 +33,7 @@
#include "nvim/vim.h"
#include "nvim/window.h"
-#define URL_SLASH 1 // path_is_url() has found "://"
+#define URL_SLASH 1 // path_is_url() has found ":/"
#define URL_BACKSLASH 2 // path_is_url() has found ":\\"
#ifdef gen_expand_wildcards
@@ -62,7 +62,7 @@ FileComparison path_full_compare(char *const s1, char *const s2, const bool chec
FileID file_id_1, file_id_2;
if (expandenv) {
- expand_env((char_u *)s1, (char_u *)exp1, MAXPATHL);
+ expand_env(s1, exp1, MAXPATHL);
} else {
STRLCPY(exp1, s1, MAXPATHL);
}
@@ -73,7 +73,7 @@ FileComparison path_full_compare(char *const s1, char *const s2, const bool chec
if (checkname) {
vim_FullName(exp1, full1, MAXPATHL, false);
vim_FullName(s2, full2, MAXPATHL, false);
- if (FNAMECMP(full1, full2) == 0) {
+ if (path_fnamecmp(full1, full2) == 0) {
return kEqualFileNames;
}
}
@@ -104,7 +104,7 @@ char *path_tail(const char *fname)
return "";
}
- const char *tail = (char *)get_past_head((char_u *)fname);
+ const char *tail = get_past_head(fname);
const char *p = tail;
// Find last part of path.
while (*p != NUL) {
@@ -130,7 +130,7 @@ char *path_tail_with_sep(char *fname)
assert(fname != NULL);
// Don't remove the '/' from "c:/file".
- char *past_head = (char *)get_past_head((char_u *)fname);
+ char *past_head = get_past_head(fname);
char *tail = path_tail(fname);
while (tail > past_head && after_pathsep(fname, tail)) {
tail--;
@@ -150,7 +150,7 @@ char *path_tail_with_sep(char *fname)
const char_u *invocation_path_tail(const char_u *invocation, size_t *len)
FUNC_ATTR_NONNULL_RET FUNC_ATTR_NONNULL_ARG(1)
{
- const char_u *tail = get_past_head((char_u *)invocation);
+ const char_u *tail = (char_u *)get_past_head((char *)invocation);
const char_u *p = tail;
while (*p != NUL && *p != ' ') {
bool was_sep = vim_ispathsep_nocolon(*p);
@@ -190,7 +190,7 @@ const char *path_next_component(const char *fname)
/// - 1 otherwise
int path_head_length(void)
{
-#ifdef WIN32
+#ifdef MSWIN
return 3;
#else
return 1;
@@ -205,7 +205,7 @@ int path_head_length(void)
/// - False otherwise
bool is_path_head(const char_u *path)
{
-#ifdef WIN32
+#ifdef MSWIN
return isalpha(path[0]) && path[1] == ':';
#else
return vim_ispathsep(*path);
@@ -215,13 +215,13 @@ bool is_path_head(const char_u *path)
/// Get a pointer to one character past the head of a path name.
/// Unix: after "/"; Win: after "c:\"
/// If there is no head, path is returned.
-char_u *get_past_head(const char_u *path)
+char *get_past_head(const char *path)
{
- const char_u *retval = path;
+ const char *retval = path;
-#ifdef WIN32
+#ifdef MSWIN
// May skip "c:"
- if (is_path_head(path)) {
+ if (is_path_head((char_u *)path)) {
retval = path + 2;
}
#endif
@@ -230,13 +230,11 @@ char_u *get_past_head(const char_u *path)
retval++;
}
- return (char_u *)retval;
+ return (char *)retval;
}
-/*
- * Return TRUE if 'c' is a path separator.
- * Note that for MS-Windows this includes the colon.
- */
+/// Return true if 'c' is a path separator.
+/// Note that for MS-Windows this includes the colon.
int vim_ispathsep(int c)
{
#ifdef UNIX
@@ -250,9 +248,7 @@ int vim_ispathsep(int c)
#endif
}
-/*
- * Like vim_ispathsep(c), but exclude the colon for MS-Windows.
- */
+// Like vim_ispathsep(c), but exclude the colon for MS-Windows.
int vim_ispathsep_nocolon(int c)
{
return vim_ispathsep(c)
@@ -262,9 +258,7 @@ int vim_ispathsep_nocolon(int c)
;
}
-/*
- * return TRUE if 'c' is a path list separator.
- */
+/// return true if 'c' is a path list separator.
int vim_ispathlistsep(int c)
{
#ifdef UNIX
@@ -314,16 +308,14 @@ void shorten_dir_len(char_u *str, int trim_len)
/// Shorten the path of a file from "~/foo/../.bar/fname" to "~/f/../.b/fname"
/// It's done in-place.
-void shorten_dir(char_u *str)
+void shorten_dir(char *str)
{
- shorten_dir_len(str, 1);
+ shorten_dir_len((char_u *)str, 1);
}
-/*
- * Return TRUE if the directory of "fname" exists, FALSE otherwise.
- * Also returns TRUE if there is no directory name.
- * "fname" must be writable!.
- */
+/// Return true if the directory of "fname" exists, false otherwise.
+/// Also returns true if there is no directory name.
+/// "fname" must be writable!.
bool dir_of_file_exists(char_u *fname)
{
char *p = path_tail_with_sep((char *)fname);
@@ -332,13 +324,19 @@ bool dir_of_file_exists(char_u *fname)
}
char c = *p;
*p = NUL;
- bool retval = os_isdir(fname);
+ bool retval = os_isdir((char *)fname);
*p = c;
return retval;
}
/// Compare two file names
///
+/// On some systems case in a file name does not matter, on others it does.
+///
+/// @note Does not account for maximum name lengths and things like "../dir",
+/// thus it is not 100% accurate. OS may also use different algorithm for
+/// case-insensitive comparison.
+///
/// Handles '/' and '\\' correctly and deals with &fileignorecase option.
///
/// @param[in] fname1 First file name.
@@ -376,21 +374,21 @@ int path_fnamencmp(const char *const fname1, const char *const fname2, size_t le
const char *p1 = fname1;
const char *p2 = fname2;
while (len > 0) {
- c1 = utf_ptr2char((const char_u *)p1);
- c2 = utf_ptr2char((const char_u *)p2);
+ c1 = utf_ptr2char(p1);
+ c2 = utf_ptr2char(p2);
if ((c1 == NUL || c2 == NUL
|| (!((c1 == '/' || c1 == '\\') && (c2 == '\\' || c2 == '/'))))
&& (p_fic ? (c1 != c2 && CH_FOLD(c1) != CH_FOLD(c2)) : c1 != c2)) {
break;
}
- len -= (size_t)utfc_ptr2len((const char_u *)p1);
- p1 += utfc_ptr2len((const char_u *)p1);
- p2 += utfc_ptr2len((const char_u *)p2);
+ len -= (size_t)utfc_ptr2len(p1);
+ p1 += utfc_ptr2len(p1);
+ p2 += utfc_ptr2len(p2);
}
return p_fic ? CH_FOLD(c1) - CH_FOLD(c2) : c1 - c2;
#else
if (p_fic) {
- return mb_strnicmp((const char_u *)fname1, (const char_u *)fname2, len);
+ return mb_strnicmp(fname1, fname2, len);
}
return strncmp(fname1, fname2, len);
#endif
@@ -515,7 +513,7 @@ char *save_abs_path(const char *name)
/// @param p The path to expand.
/// @returns Unix: True if it contains one of "?[{`'$".
/// @returns Windows: True if it contains one of "*?$[".
-bool path_has_wildcard(const char_u *p)
+bool path_has_wildcard(const char *p)
FUNC_ATTR_NONNULL_ALL
{
for (; *p; MB_PTR_ADV(p)) {
@@ -538,9 +536,7 @@ bool path_has_wildcard(const char_u *p)
return false;
}
-/*
- * Unix style wildcard expansion code.
- */
+// Unix style wildcard expansion code.
static int pstrcmp(const void *a, const void *b)
{
return pathcmp(*(char **)a, *(char **)b, -1);
@@ -579,13 +575,13 @@ bool path_has_exp_wildcard(const char_u *p)
/// @param path The path to search.
/// @param flags Flags for regexp expansion.
/// - EW_ICASE: Ignore case.
-/// - EW_NOERROR: Silence error messeges.
+/// - EW_NOERROR: Silence error messages.
/// - EW_NOTWILD: Add matches literally.
/// @returns the number of matches found.
static size_t path_expand(garray_T *gap, const char_u *path, int flags)
FUNC_ATTR_NONNULL_ALL
{
- return do_path_expand(gap, path, 0, flags, false);
+ return do_path_expand(gap, (char *)path, 0, flags, false);
}
static const char *scandir_next_with_dots(Directory *dir)
@@ -606,7 +602,7 @@ static const char *scandir_next_with_dots(Directory *dir)
/// Implementation of path_expand().
///
/// Chars before `path + wildoff` do not get expanded.
-static size_t do_path_expand(garray_T *gap, const char_u *path, size_t wildoff, int flags,
+static size_t do_path_expand(garray_T *gap, const char *path, size_t wildoff, int flags,
bool didstar)
FUNC_ATTR_NONNULL_ALL
{
@@ -633,20 +629,20 @@ static size_t do_path_expand(garray_T *gap, const char_u *path, size_t wildoff,
char_u *p = buf;
char_u *s = buf;
char_u *e = NULL;
- const char_u *path_end = path;
+ const char_u *path_end = (char_u *)path;
while (*path_end != NUL) {
- /* May ignore a wildcard that has a backslash before it; it will
- * be removed by rem_backslash() or file_pat_to_reg_pat() below. */
- if (path_end >= path + wildoff && rem_backslash(path_end)) {
+ // May ignore a wildcard that has a backslash before it; it will
+ // be removed by rem_backslash() or file_pat_to_reg_pat() below.
+ if (path_end >= (char_u *)path + wildoff && rem_backslash((char *)path_end)) {
*p++ = *path_end++;
} else if (vim_ispathsep_nocolon(*path_end)) {
if (e != NULL) {
break;
}
s = p + 1;
- } else if (path_end >= path + wildoff
+ } else if (path_end >= (char_u *)path + wildoff
&& (vim_strchr("*?[{~$", *path_end) != NULL
-#ifndef WIN32
+#ifndef MSWIN
|| (!p_fic && (flags & EW_ICASE) && mb_isalpha(utf_ptr2char((char *)path_end)))
#endif
)) {
@@ -661,10 +657,10 @@ static size_t do_path_expand(garray_T *gap, const char_u *path, size_t wildoff,
*e = NUL;
// Now we have one wildcard component between "s" and "e".
- /* Remove backslashes between "wildoff" and the start of the wildcard
- * component. */
- for (p = buf + wildoff; p < s; ++p) {
- if (rem_backslash(p)) {
+ // Remove backslashes between "wildoff" and the start of the wildcard
+ // component.
+ for (p = buf + wildoff; p < s; p++) {
+ if (rem_backslash((char *)p)) {
STRMOVE(p, p + 1);
e--;
s--;
@@ -672,7 +668,7 @@ static size_t do_path_expand(garray_T *gap, const char_u *path, size_t wildoff,
}
// Check for "**" between "s" and "e".
- for (p = s; p < e; ++p) {
+ for (p = s; p < e; p++) {
if (p[0] == '*' && p[1] == '*') {
starstar = true;
}
@@ -708,13 +704,13 @@ static size_t do_path_expand(garray_T *gap, const char_u *path, size_t wildoff,
return 0;
}
- /* If "**" is by itself, this is the first time we encounter it and more
- * is following then find matches without any directory. */
+ // If "**" is by itself, this is the first time we encounter it and more
+ // is following then find matches without any directory.
if (!didstar && stardepth < 100 && starstar && e - s == 2
&& *path_end == '/') {
STRCPY(s, path_end + 1);
stardepth++;
- (void)do_path_expand(gap, buf, (size_t)(s - buf), flags, true);
+ (void)do_path_expand(gap, (char *)buf, (size_t)(s - buf), flags, true);
stardepth--;
}
*s = NUL;
@@ -723,27 +719,27 @@ static size_t do_path_expand(garray_T *gap, const char_u *path, size_t wildoff,
char *dirpath = (*buf == NUL ? "." : (char *)buf);
if (os_file_is_readable(dirpath) && os_scandir(&dir, dirpath)) {
// Find all matching entries.
- char_u *name;
+ char *name;
scandir_next_with_dots(NULL); // initialize
- while (!got_int && (name = (char_u *)scandir_next_with_dots(&dir)) != NULL) {
+ while (!got_int && (name = (char *)scandir_next_with_dots(&dir)) != NULL) {
if ((name[0] != '.'
|| starts_with_dot
|| ((flags & EW_DODOT)
&& name[1] != NUL
&& (name[1] != '.' || name[2] != NUL))) // -V557
- && ((regmatch.regprog != NULL && vim_regexec(&regmatch, (char *)name, 0))
+ && ((regmatch.regprog != NULL && vim_regexec(&regmatch, name, 0))
|| ((flags & EW_NOTWILD)
- && FNAMENCMP(path + (s - buf), name, e - s) == 0))) {
+ && path_fnamencmp(path + (s - buf), name, (size_t)(e - s)) == 0))) {
STRCPY(s, name);
len = STRLEN(buf);
if (starstar && stardepth < 100) {
- /* For "**" in the pattern first go deeper in the tree to
- * find matches. */
- STRCPY(buf + len, "/**");
+ // For "**" in the pattern first go deeper in the tree to
+ // find matches.
+ STRCPY(buf + len, "/**"); // NOLINT
STRCPY(buf + len + 3, path_end);
stardepth++;
- (void)do_path_expand(gap, buf, len + 1, flags, true);
+ (void)do_path_expand(gap, (char *)buf, len + 1, flags, true);
stardepth--;
}
@@ -751,18 +747,19 @@ static size_t do_path_expand(garray_T *gap, const char_u *path, size_t wildoff,
if (path_has_exp_wildcard(path_end)) { // handle more wildcards
// need to expand another component of the path
// remove backslashes for the remaining components only
- (void)do_path_expand(gap, buf, len + 1, flags, false);
+ (void)do_path_expand(gap, (char *)buf, len + 1, flags, false);
} else {
FileInfo file_info;
// no more wildcards, check if there is a match
// remove backslashes for the remaining components only
if (*path_end != NUL) {
- backslash_halve(buf + len + 1);
+ backslash_halve((char *)buf + len + 1);
}
// add existing file or symbolic link
- if ((flags & EW_ALLLINKS) ? os_fileinfo_link((char *)buf, &file_info)
- : os_path_exists(buf)) {
+ if ((flags & EW_ALLLINKS)
+ ? os_fileinfo_link((char *)buf, &file_info)
+ : os_path_exists((char *)buf)) {
addfile(gap, buf, flags);
}
}
@@ -784,10 +781,8 @@ static size_t do_path_expand(garray_T *gap, const char_u *path, size_t wildoff,
return matches;
}
-/*
- * Moves "*psep" back to the previous path separator in "path".
- * Returns FAIL is "*psep" ends up at the beginning of "path".
- */
+// Moves "*psep" back to the previous path separator in "path".
+// Returns FAIL is "*psep" ends up at the beginning of "path".
static int find_previous_pathsep(char_u *path, char_u **psep)
{
// skip the current separator
@@ -806,25 +801,23 @@ static int find_previous_pathsep(char_u *path, char_u **psep)
return FAIL;
}
-/*
- * Returns TRUE if "maybe_unique" is unique wrt other_paths in "gap".
- * "maybe_unique" is the end portion of "((char_u **)gap->ga_data)[i]".
- */
-static bool is_unique(char_u *maybe_unique, garray_T *gap, int i)
+/// Returns true if "maybe_unique" is unique wrt other_paths in "gap".
+/// "maybe_unique" is the end portion of "((char_u **)gap->ga_data)[i]".
+static bool is_unique(char *maybe_unique, garray_T *gap, int i)
{
- char_u **other_paths = (char_u **)gap->ga_data;
+ char **other_paths = gap->ga_data;
for (int j = 0; j < gap->ga_len; j++) {
if (j == i) {
continue; // don't compare it with itself
}
- size_t candidate_len = STRLEN(maybe_unique);
- size_t other_path_len = STRLEN(other_paths[j]);
+ size_t candidate_len = strlen(maybe_unique);
+ size_t other_path_len = strlen(other_paths[j]);
if (other_path_len < candidate_len) {
continue; // it's different when it's shorter
}
- char_u *rival = other_paths[j] + other_path_len - candidate_len;
- if (FNAMECMP(maybe_unique, rival) == 0
+ char *rival = other_paths[j] + other_path_len - candidate_len;
+ if (path_fnamecmp(maybe_unique, rival) == 0
&& (rival == other_paths[j] || vim_ispathsep(*(rival - 1)))) {
return false; // match
}
@@ -832,33 +825,31 @@ static bool is_unique(char_u *maybe_unique, garray_T *gap, int i)
return true; // no match found
}
-/*
- * Split the 'path' option into an array of strings in garray_T. Relative
- * paths are expanded to their equivalent fullpath. This includes the "."
- * (relative to current buffer directory) and empty path (relative to current
- * directory) notations.
- *
- * TODO: handle upward search (;) and path limiter (**N) notations by
- * expanding each into their equivalent path(s).
- */
+// Split the 'path' option into an array of strings in garray_T. Relative
+// paths are expanded to their equivalent fullpath. This includes the "."
+// (relative to current buffer directory) and empty path (relative to current
+// directory) notations.
+//
+// TODO(vim): handle upward search (;) and path limiter (**N) notations by
+// expanding each into their equivalent path(s).
static void expand_path_option(char_u *curdir, garray_T *gap)
{
- char_u *path_option = *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path;
- char_u *buf = xmalloc(MAXPATHL);
+ char_u *path_option = *curbuf->b_p_path == NUL ? p_path : (char_u *)curbuf->b_p_path;
+ char *buf = xmalloc(MAXPATHL);
while (*path_option != NUL) {
- copy_option_part((char **)&path_option, (char *)buf, MAXPATHL, " ,");
+ copy_option_part((char **)&path_option, buf, MAXPATHL, " ,");
if (buf[0] == '.' && (buf[1] == NUL || vim_ispathsep(buf[1]))) {
- /* Relative to current buffer:
- * "/path/file" + "." -> "/path/"
- * "/path/file" + "./subdir" -> "/path/subdir" */
+ // Relative to current buffer:
+ // "/path/file" + "." -> "/path/"
+ // "/path/file" + "./subdir" -> "/path/subdir"
if (curbuf->b_ffname == NULL) {
continue;
}
char_u *p = (char_u *)path_tail(curbuf->b_ffname);
size_t len = (size_t)(p - (char_u *)curbuf->b_ffname);
- if (len + STRLEN(buf) >= MAXPATHL) {
+ if (len + strlen(buf) >= MAXPATHL) {
continue;
}
if (buf[1] == NUL) {
@@ -867,37 +858,35 @@ static void expand_path_option(char_u *curdir, garray_T *gap)
STRMOVE(buf + len, buf + 2);
}
memmove(buf, curbuf->b_ffname, len);
- simplify_filename(buf);
+ simplify_filename((char_u *)buf);
} else if (buf[0] == NUL) {
STRCPY(buf, curdir); // relative to current directory
- } else if (path_with_url((char *)buf)) {
+ } else if (path_with_url(buf)) {
continue; // URL can't be used here
- } else if (!path_is_absolute(buf)) {
+ } else if (!path_is_absolute((char_u *)buf)) {
// Expand relative path to their full path equivalent
size_t len = STRLEN(curdir);
- if (len + STRLEN(buf) + 3 > MAXPATHL) {
+ if (len + strlen(buf) + 3 > MAXPATHL) {
continue;
}
STRMOVE(buf + len + 1, buf);
STRCPY(buf, curdir);
buf[len] = (char_u)PATHSEP;
- simplify_filename(buf);
+ simplify_filename((char_u *)buf);
}
- GA_APPEND(char_u *, gap, vim_strsave(buf));
+ GA_APPEND(char *, gap, xstrdup(buf));
}
xfree(buf);
}
-/*
- * Returns a pointer to the file or directory name in "fname" that matches the
- * longest path in "ga"p, or NULL if there is no match. For example:
- *
- * path: /foo/bar/baz
- * fname: /foo/bar/baz/quux.txt
- * returns: ^this
- */
+// Returns a pointer to the file or directory name in "fname" that matches the
+// longest path in "ga"p, or NULL if there is no match. For example:
+//
+// path: /foo/bar/baz
+// fname: /foo/bar/baz/quux.txt
+// returns: ^this
static char_u *get_path_cutoff(char_u *fname, garray_T *gap)
{
int maxlen = 0;
@@ -908,7 +897,7 @@ static char_u *get_path_cutoff(char_u *fname, garray_T *gap)
int j = 0;
while ((fname[j] == path_part[i][j]
-#ifdef WIN32
+#ifdef MSWIN
|| (vim_ispathsep(fname[j]) && vim_ispathsep(path_part[i][j]))
#endif
) // NOLINT(whitespace/parens)
@@ -931,19 +920,17 @@ static char_u *get_path_cutoff(char_u *fname, garray_T *gap)
return cutoff;
}
-/*
- * Sorts, removes duplicates and modifies all the fullpath names in "gap" so
- * that they are unique with respect to each other while conserving the part
- * that matches the pattern. Beware, this is at least O(n^2) wrt "gap->ga_len".
- */
+// Sorts, removes duplicates and modifies all the fullpath names in "gap" so
+// that they are unique with respect to each other while conserving the part
+// that matches the pattern. Beware, this is at least O(n^2) wrt "gap->ga_len".
static void uniquefy_paths(garray_T *gap, char_u *pattern)
{
- char_u **fnames = (char_u **)gap->ga_data;
+ char **fnames = gap->ga_data;
bool sort_again = false;
regmatch_T regmatch;
garray_T path_ga;
- char_u **in_curdir = NULL;
- char_u *short_name;
+ char **in_curdir = NULL;
+ char *short_name;
ga_remove_duplicate_strings(gap);
ga_init(&path_ga, (int)sizeof(char_u *), 1);
@@ -952,11 +939,11 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern)
// regex matches anywhere in the path. FIXME: is this valid for all
// possible patterns?
size_t len = STRLEN(pattern);
- char_u *file_pattern = xmalloc(len + 2);
+ char *file_pattern = xmalloc(len + 2);
file_pattern[0] = '*';
file_pattern[1] = NUL;
STRCAT(file_pattern, pattern);
- char *pat = file_pat_to_reg_pat((char *)file_pattern, NULL, NULL, true);
+ char *pat = file_pat_to_reg_pat(file_pattern, NULL, NULL, true);
xfree(file_pattern);
if (pat == NULL) {
return;
@@ -969,28 +956,28 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern)
return;
}
- char_u *curdir = xmalloc(MAXPATHL);
- os_dirname(curdir, MAXPATHL);
- expand_path_option(curdir, &path_ga);
+ char *curdir = xmalloc(MAXPATHL);
+ os_dirname((char_u *)curdir, MAXPATHL);
+ expand_path_option((char_u *)curdir, &path_ga);
in_curdir = xcalloc((size_t)gap->ga_len, sizeof(char_u *));
for (int i = 0; i < gap->ga_len && !got_int; i++) {
- char_u *path = fnames[i];
+ char *path = fnames[i];
int is_in_curdir;
- char_u *dir_end = (char_u *)gettail_dir((const char *)path);
- char_u *pathsep_p;
- char_u *path_cutoff;
+ char *dir_end = (char *)gettail_dir((const char *)path);
+ char *pathsep_p;
+ char *path_cutoff;
len = STRLEN(path);
- is_in_curdir = FNAMENCMP(curdir, path, dir_end - path) == 0
+ is_in_curdir = path_fnamencmp(curdir, path, (size_t)(dir_end - path)) == 0
&& curdir[dir_end - path] == NUL;
if (is_in_curdir) {
- in_curdir[i] = vim_strsave(path);
+ in_curdir[i] = xstrdup(path);
}
// Shorten the filename while maintaining its uniqueness
- path_cutoff = get_path_cutoff(path, &path_ga);
+ path_cutoff = (char *)get_path_cutoff((char_u *)path, &path_ga);
// Don't assume all files can be reached without path when search
// pattern starts with **/, so only remove path_cutoff
@@ -998,26 +985,26 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern)
if (pattern[0] == '*' && pattern[1] == '*'
&& vim_ispathsep_nocolon(pattern[2])
&& path_cutoff != NULL
- && vim_regexec(&regmatch, (char *)path_cutoff, (colnr_T)0)
+ && vim_regexec(&regmatch, path_cutoff, (colnr_T)0)
&& is_unique(path_cutoff, gap, i)) {
sort_again = true;
- memmove(path, path_cutoff, STRLEN(path_cutoff) + 1);
+ memmove(path, path_cutoff, strlen(path_cutoff) + 1);
} else {
// Here all files can be reached without path, so get shortest
// unique path. We start at the end of the path. */
pathsep_p = path + len - 1;
- while (find_previous_pathsep(path, &pathsep_p)) {
- if (vim_regexec(&regmatch, (char *)pathsep_p + 1, (colnr_T)0)
+ while (find_previous_pathsep((char_u *)path, (char_u **)&pathsep_p)) {
+ if (vim_regexec(&regmatch, pathsep_p + 1, (colnr_T)0)
&& is_unique(pathsep_p + 1, gap, i)
&& path_cutoff != NULL && pathsep_p + 1 >= path_cutoff) {
sort_again = true;
- memmove(path, pathsep_p + 1, STRLEN(pathsep_p));
+ memmove(path, pathsep_p + 1, strlen(pathsep_p));
break;
}
}
}
- if (path_is_absolute(path)) {
+ if (path_is_absolute((char_u *)path)) {
// Last resort: shorten relative to curdir if possible.
// 'possible' means:
// 1. It is under the current directory.
@@ -1031,7 +1018,7 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern)
short_name = path_shorten_fname(path, curdir);
if (short_name != NULL && short_name > path + 1) {
STRCPY(path, ".");
- add_pathsep((char *)path);
+ add_pathsep(path);
STRMOVE(path + STRLEN(path), short_name);
}
}
@@ -1040,15 +1027,15 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern)
// Shorten filenames in /in/current/directory/{filename}
for (int i = 0; i < gap->ga_len && !got_int; i++) {
- char_u *rel_path;
- char_u *path = in_curdir[i];
+ char *rel_path;
+ char *path = in_curdir[i];
if (path == NULL) {
continue;
}
- /* If the {filename} is not unique, change it to ./{filename}.
- * Else reduce it to {filename} */
+ // If the {filename} is not unique, change it to ./{filename}.
+ // Else reduce it to {filename}
short_name = path_shorten_fname(path, curdir);
if (short_name == NULL) {
short_name = path;
@@ -1058,9 +1045,9 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern)
continue;
}
- rel_path = xmalloc(STRLEN(short_name) + STRLEN(PATHSEPSTR) + 2);
+ rel_path = xmalloc(strlen(short_name) + strlen(PATHSEPSTR) + 2);
STRCPY(rel_path, ".");
- add_pathsep((char *)rel_path);
+ add_pathsep(rel_path);
STRCAT(rel_path, short_name);
xfree(fnames[i]);
@@ -1143,16 +1130,14 @@ static int expand_in_path(garray_T *const gap, char_u *const pattern, const int
if (flags & EW_ADDSLASH) {
glob_flags |= WILD_ADD_SLASH;
}
- globpath((char *)paths, pattern, gap, glob_flags);
+ globpath((char *)paths, (char *)pattern, gap, glob_flags);
xfree(paths);
return gap->ga_len;
}
-/*
- * Return TRUE if "p" contains what looks like an environment variable.
- * Allowing for escaping.
- */
+/// Return true if "p" contains what looks like an environment variable.
+/// Allowing for escaping.
static bool has_env_var(char_u *p)
{
for (; *p; MB_PTR_ADV(p)) {
@@ -1167,7 +1152,7 @@ static bool has_env_var(char_u *p)
#ifdef SPECIAL_WILDCHAR
-// Return TRUE if "p" contains a special wildcard character, one that Vim
+// Return true if "p" contains a special wildcard character, one that Vim
// cannot expand, requires using a shell.
static bool has_special_wildchar(char_u *p)
{
@@ -1221,26 +1206,23 @@ int gen_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, i
int add_pat;
bool did_expand_in_path = false;
- /*
- * expand_env() is called to expand things like "~user". If this fails,
- * it calls ExpandOne(), which brings us back here. In this case, always
- * call the machine specific expansion function, if possible. Otherwise,
- * return FAIL.
- */
- if (recursive)
+ // expand_env() is called to expand things like "~user". If this fails,
+ // it calls ExpandOne(), which brings us back here. In this case, always
+ // call the machine specific expansion function, if possible. Otherwise,
+ // return FAIL.
+ if (recursive) {
#ifdef SPECIAL_WILDCHAR
- { return os_expand_wildcards(num_pat, pat, num_file, file, flags); }
+ return os_expand_wildcards(num_pat, pat, num_file, file, flags);
#else
- { return FAIL; }
+ return FAIL;
#endif
+ }
#ifdef SPECIAL_WILDCHAR
- /*
- * If there are any special wildcard characters which we cannot handle
- * here, call machine specific function for all the expansion. This
- * avoids starting the shell for each argument separately.
- * For `=expr` do use the internal function.
- */
+ // If there are any special wildcard characters which we cannot handle
+ // here, call machine specific function for all the expansion. This
+ // avoids starting the shell for each argument separately.
+ // For `=expr` do use the internal function.
for (int i = 0; i < num_pat; i++) {
if (has_special_wildchar((char_u *)pat[i])
&& !(vim_backtick((char_u *)pat[i]) && pat[i][1] == '=')) {
@@ -1251,9 +1233,7 @@ int gen_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, i
recursive = true;
- /*
- * The matching file names are stored in a growarray. Init it empty.
- */
+ // The matching file names are stored in a growarray. Init it empty.
ga_init(&ga, (int)sizeof(char_u *), 30);
for (int i = 0; i < num_pat && !got_int; i++) {
@@ -1261,7 +1241,7 @@ int gen_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, i
p = (char_u *)pat[i];
if (vim_backtick(p)) {
- add_pat = expand_backtick(&ga, p, flags);
+ add_pat = expand_backtick(&ga, (char *)p, flags);
if (add_pat == -1) {
recursive = false;
FreeWild(ga.ga_len, ga.ga_data);
@@ -1275,40 +1255,37 @@ int gen_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, i
p = expand_env_save_opt(p, true);
if (p == NULL) {
p = (char_u *)pat[i];
- }
+ } else {
#ifdef UNIX
- /*
- * On Unix, if expand_env() can't expand an environment
- * variable, use the shell to do that. Discard previously
- * found file names and start all over again.
- */
- else if (has_env_var(p) || *p == '~') {
- xfree(p);
- ga_clear_strings(&ga);
- i = os_expand_wildcards(num_pat, pat, num_file, file,
- flags | EW_KEEPDOLLAR);
- recursive = false;
- return i;
- }
+ // On Unix, if expand_env() can't expand an environment
+ // variable, use the shell to do that. Discard previously
+ // found file names and start all over again.
+ if (has_env_var(p) || *p == '~') {
+ xfree(p);
+ ga_clear_strings(&ga);
+ i = os_expand_wildcards(num_pat, pat, num_file, file,
+ flags | EW_KEEPDOLLAR);
+ recursive = false;
+ return i;
+ }
#endif
+ }
}
- /*
- * If there are wildcards: Expand file names and add each match to
- * the list. If there is no match, and EW_NOTFOUND is given, add
- * the pattern.
- * If there are no wildcards: Add the file name if it exists or
- * when EW_NOTFOUND is given.
- */
- if (path_has_exp_wildcard(p)) {
+ // If there are wildcards or case-insensitive expansion is
+ // required: Expand file names and add each match to the list. If
+ // there is no match, and EW_NOTFOUND is given, add the pattern.
+ // Otherwise: Add the file name if it exists or when EW_NOTFOUND is
+ // given.
+ if (path_has_exp_wildcard(p) || (flags & EW_ICASE)) {
if ((flags & EW_PATH)
&& !path_is_absolute(p)
&& !(p[0] == '.'
&& (vim_ispathsep(p[1])
|| (p[1] == '.'
&& vim_ispathsep(p[2]))))) {
- /* :find completion where 'path' is used.
- * Recursiveness is OK here. */
+ // :find completion where 'path' is used.
+ // Recursiveness is OK here.
recursive = false;
add_pat = expand_in_path(&ga, p, flags);
recursive = true;
@@ -1322,10 +1299,10 @@ int gen_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, i
}
if (add_pat == -1 || (add_pat == 0 && (flags & EW_NOTFOUND))) {
- char_u *t = backslash_halve_save(p);
+ char_u *t = (char_u *)backslash_halve_save((char *)p);
- /* When EW_NOTFOUND is used, always add files and dirs. Makes
- * "vim c:/" work. */
+ // When EW_NOTFOUND is used, always add files and dirs. Makes
+ // "vim c:/" work.
if (flags & EW_NOTFOUND) {
addfile(&ga, t, flags | EW_DIR | EW_FILE);
} else {
@@ -1365,9 +1342,7 @@ void FreeWild(int count, char **files)
xfree(files);
}
-/*
- * Return TRUE if we can expand this backtick thing here.
- */
+/// Return true if we can expand this backtick thing here.
static int vim_backtick(char_u *p)
{
return *p == '`' && *(p + 1) != NUL && *(p + STRLEN(p) - 1) == '`';
@@ -1378,14 +1353,14 @@ static int vim_backtick(char_u *p)
/// Returns number of file names found, -1 if an error is encountered.
///
/// @param flags EW_* flags
-static int expand_backtick(garray_T *gap, char_u *pat, int flags)
+static int expand_backtick(garray_T *gap, char *pat, int flags)
{
char *p;
char *buffer;
int cnt = 0;
// Create the command: lop off the backticks.
- char *cmd = (char *)vim_strnsave(pat + 1, STRLEN(pat) - 2);
+ char *cmd = xstrnsave(pat + 1, strlen(pat) - 2);
if (*cmd == '=') { // `={expr}`: Expand expression
buffer = eval_to_string(cmd + 1, &p, true);
@@ -1440,7 +1415,7 @@ void slash_adjust(char_u *p)
if (*p == '`') {
// don't replace backslash in backtick quoted strings
- const size_t len = STRLEN(p);
+ const size_t len = strlen(p);
if (len > 2 && *(p + len - 1) == '`') {
return;
}
@@ -1473,7 +1448,7 @@ void addfile(garray_T *gap, char_u *f, int flags)
if (!(flags & EW_NOTFOUND)
&& ((flags & EW_ALLLINKS)
? !os_fileinfo_link((char *)f, &file_info)
- : !os_path_exists(f))) {
+ : !os_path_exists((char *)f))) {
return;
}
@@ -1484,7 +1459,7 @@ void addfile(garray_T *gap, char_u *f, int flags)
}
#endif
- isdir = os_isdir(f);
+ isdir = os_isdir((char *)f);
if ((isdir && !(flags & EW_DIR)) || (!isdir && !(flags & EW_FILE))) {
return;
}
@@ -1502,21 +1477,17 @@ void addfile(garray_T *gap, char_u *f, int flags)
#ifdef BACKSLASH_IN_FILENAME
slash_adjust(p);
#endif
- /*
- * Append a slash or backslash after directory names if none is present.
- */
+ // Append a slash or backslash after directory names if none is present.
if (isdir && (flags & EW_ADDSLASH)) {
add_pathsep((char *)p);
}
GA_APPEND(char_u *, gap, p);
}
-/*
- * Converts a file name into a canonical form. It simplifies a file name into
- * its simplest form by stripping out unneeded components, if any. The
- * resulting file name is simplified in place and will either be the same
- * length as that supplied, or shorter.
- */
+// Converts a file name into a canonical form. It simplifies a file name into
+// its simplest form by stripping out unneeded components, if any. The
+// resulting file name is simplified in place and will either be the same
+// length as that supplied, or shorter.
void simplify_filename(char_u *filename)
{
int components = 0;
@@ -1540,8 +1511,8 @@ void simplify_filename(char_u *filename)
start = p; // remember start after "c:/" or "/" or "///"
do {
- /* At this point "p" is pointing to the char following a single "/"
- * or "p" is at the "start" of the (absolute or relative) path name. */
+ // At this point "p" is pointing to the char following a single "/"
+ // or "p" is at the "start" of the (absolute or relative) path name.
if (vim_ispathsep(*p)) {
STRMOVE(p, p + 1); // remove duplicate "/"
} else if (p[0] == '.'
@@ -1549,10 +1520,10 @@ void simplify_filename(char_u *filename)
if (p == start && relative) {
p += 1 + (p[1] != NUL); // keep single "." or leading "./"
} else {
- /* Strip "./" or ".///". If we are at the end of the file name
- * and there is no trailing path separator, either strip "/." if
- * we are after "start", or strip "." if we are at the beginning
- * of an absolute path name . */
+ // Strip "./" or ".///". If we are at the end of the file name
+ // and there is no trailing path separator, either strip "/." if
+ // we are after "start", or strip "." if we are at the beginning
+ // of an absolute path name.
tail = p + 1;
if (p[1] != NUL) {
while (vim_ispathsep(*tail)) {
@@ -1577,9 +1548,9 @@ void simplify_filename(char_u *filename)
// Don't strip for an erroneous file name.
if (!stripping_disabled) {
- /* If the preceding component does not exist in the file
- * system, we strip it. On Unix, we don't accept a symbolic
- * link that refers to a non-existent file. */
+ // If the preceding component does not exist in the file
+ // system, we strip it. On Unix, we don't accept a symbolic
+ // link that refers to a non-existent file.
saved_char = p[-1];
p[-1] = NUL;
FileInfo file_info;
@@ -1595,16 +1566,16 @@ void simplify_filename(char_u *filename)
}
if (!do_strip) {
- /* If the component exists in the file system, check
- * that stripping it won't change the meaning of the
- * file name. First get information about the
- * unstripped file name. This may fail if the component
- * to strip is not a searchable directory (but a regular
- * file, for instance), since the trailing "/.." cannot
- * be applied then. We don't strip it then since we
- * don't want to replace an erroneous file name by
- * a valid one, and we disable stripping of later
- * components. */
+ // If the component exists in the file system, check
+ // that stripping it won't change the meaning of the
+ // file name. First get information about the
+ // unstripped file name. This may fail if the component
+ // to strip is not a searchable directory (but a regular
+ // file, for instance), since the trailing "/.." cannot
+ // be applied then. We don't strip it then since we
+ // don't want to replace an erroneous file name by
+ // a valid one, and we disable stripping of later
+ // components.
saved_char = *tail;
*tail = NUL;
if (os_fileinfo((char *)filename, &file_info)) {
@@ -1614,13 +1585,13 @@ void simplify_filename(char_u *filename)
}
*tail = saved_char;
if (do_strip) {
- /* The check for the unstripped file name
- * above works also for a symbolic link pointing to
- * a searchable directory. But then the parent of
- * the directory pointed to by the link must be the
- * same as the stripped file name. (The latter
- * exists in the file system since it is the
- * component's parent directory.) */
+ // The check for the unstripped file name
+ // above works also for a symbolic link pointing to
+ // a searchable directory. But then the parent of
+ // the directory pointed to by the link must be the
+ // same as the stripped file name. (The latter
+ // exists in the file system since it is the
+ // component's parent directory.)
FileInfo new_file_info;
if (p == start && relative) {
os_fileinfo(".", &new_file_info);
@@ -1633,26 +1604,26 @@ void simplify_filename(char_u *filename)
if (!os_fileinfo_id_equal(&file_info, &new_file_info)) {
do_strip = false;
- /* We don't disable stripping of later
- * components since the unstripped path name is
- * still valid. */
+ // We don't disable stripping of later
+ // components since the unstripped path name is
+ // still valid.
}
}
}
}
if (!do_strip) {
- /* Skip the ".." or "../" and reset the counter for the
- * components that might be stripped later on. */
+ // Skip the ".." or "../" and reset the counter for the
+ // components that might be stripped later on.
p = tail;
components = 0;
} else {
- /* Strip previous component. If the result would get empty
- * and there is no trailing path separator, leave a single
- * "." instead. If we are at the end of the file name and
- * there is no trailing path separator and a preceding
- * component is left after stripping, strip its trailing
- * path separator as well. */
+ // Strip previous component. If the result would get empty
+ // and there is no trailing path separator, leave a single
+ // "." instead. If we are at the end of the file name and
+ // there is no trailing path separator and a preceding
+ // component is left after stripping, strip its trailing
+ // path separator as well.
if (p == start && relative && tail[-1] == '.') {
*p++ = '.';
*p = NUL;
@@ -1684,7 +1655,7 @@ void simplify_filename(char_u *filename)
static char *eval_includeexpr(const char *const ptr, const size_t len)
{
set_vim_var_string(VV_FNAME, ptr, (ptrdiff_t)len);
- char *res = eval_to_string_safe((char *)curbuf->b_p_inex, NULL,
+ char *res = eval_to_string_safe(curbuf->b_p_inex, NULL,
was_set_insecurely(curwin, "includeexpr", OPT_LOCAL));
set_vim_var_string(VV_FNAME, NULL, 0);
return res;
@@ -1694,56 +1665,55 @@ static char *eval_includeexpr(const char *const ptr, const size_t len)
/// Otherwise like file_name_at_cursor().
///
/// @param rel_fname file we are searching relative to
-char_u *find_file_name_in_path(char_u *ptr, size_t len, int options, long count, char_u *rel_fname)
+char *find_file_name_in_path(char *ptr, size_t len, int options, long count, char *rel_fname)
{
- char_u *file_name;
- char_u *tofree = NULL;
+ char *file_name;
+ char *tofree = NULL;
if (len == 0) {
return NULL;
}
if ((options & FNAME_INCL) && *curbuf->b_p_inex != NUL) {
- tofree = (char_u *)eval_includeexpr((char *)ptr, len);
+ tofree = eval_includeexpr(ptr, len);
if (tofree != NULL) {
ptr = tofree;
- len = STRLEN(ptr);
+ len = strlen(ptr);
}
}
if (options & FNAME_EXP) {
- file_name = find_file_in_path(ptr, len, options & ~FNAME_MESS, true,
- rel_fname);
+ file_name = (char *)find_file_in_path((char_u *)ptr, len, options & ~FNAME_MESS, true,
+ (char_u *)rel_fname);
- /*
- * If the file could not be found in a normal way, try applying
- * 'includeexpr' (unless done already).
- */
+ // If the file could not be found in a normal way, try applying
+ // 'includeexpr' (unless done already).
if (file_name == NULL
&& !(options & FNAME_INCL) && *curbuf->b_p_inex != NUL) {
- tofree = (char_u *)eval_includeexpr((char *)ptr, len);
+ tofree = eval_includeexpr(ptr, len);
if (tofree != NULL) {
ptr = tofree;
- len = STRLEN(ptr);
- file_name = find_file_in_path(ptr, len, options & ~FNAME_MESS,
- TRUE, rel_fname);
+ len = strlen(ptr);
+ file_name = (char *)find_file_in_path((char_u *)ptr, len, options & ~FNAME_MESS,
+ true, (char_u *)rel_fname);
}
}
if (file_name == NULL && (options & FNAME_MESS)) {
- char_u c = ptr[len];
+ char c = ptr[len];
ptr[len] = NUL;
semsg(_("E447: Can't find file \"%s\" in path"), ptr);
ptr[len] = c;
}
- /* Repeat finding the file "count" times. This matters when it
- * appears several times in the path. */
+ // Repeat finding the file "count" times. This matters when it
+ // appears several times in the path.
while (file_name != NULL && --count > 0) {
xfree(file_name);
- file_name = find_file_in_path(ptr, len, options, FALSE, rel_fname);
+ file_name =
+ (char *)find_file_in_path((char_u *)ptr, len, options, false, (char_u *)rel_fname);
}
} else {
- file_name = vim_strnsave(ptr, len);
+ file_name = xstrnsave(ptr, len);
}
xfree(tofree);
@@ -1751,12 +1721,26 @@ char_u *find_file_name_in_path(char_u *ptr, size_t len, int options, long count,
return file_name;
}
-// Check if the "://" of a URL is at the pointer, return URL_SLASH.
+/// Checks for a Windows drive letter ("C:/") at the start of the path.
+///
+/// @see https://url.spec.whatwg.org/#start-with-a-windows-drive-letter
+bool path_has_drive_letter(const char *p)
+ FUNC_ATTR_NONNULL_ALL
+{
+ return strlen(p) >= 2
+ && ASCII_ISALPHA(p[0])
+ && (p[1] == ':' || p[1] == '|')
+ && (strlen(p) == 2 || ((p[2] == '/') | (p[2] == '\\') | (p[2] == '?') | (p[2] == '#')));
+}
+
+// Check if the ":/" of a URL is at the pointer, return URL_SLASH.
// Also check for ":\\", which MS Internet Explorer accepts, return
// URL_BACKSLASH.
int path_is_url(const char *p)
{
- if (strncmp(p, "://", 3) == 0) {
+ // In the spec ':' is enough to recognize a scheme
+ // https://url.spec.whatwg.org/#scheme-state
+ if (strncmp(p, ":/", 2) == 0) {
return URL_SLASH;
} else if (strncmp(p, ":\\\\", 3) == 0) {
return URL_BACKSLASH;
@@ -1781,6 +1765,10 @@ int path_with_url(const char *fname)
return 0;
}
+ if (path_has_drive_letter(fname)) {
+ return 0;
+ }
+
// check body: alpha or dash
for (p = fname + 1; (isalpha(*p) || (*p == '-')); p++) {}
@@ -1789,7 +1777,7 @@ int path_with_url(const char *fname)
return 0;
}
- // "://" or ":\\" must follow
+ // ":/" or ":\\" must follow
return path_is_url(p);
}
@@ -1802,9 +1790,7 @@ bool path_with_extension(const char *path, const char *extension)
return strcmp(last_dot + 1, extension) == 0;
}
-/*
- * Return TRUE if "name" is a full (absolute) path name or URL.
- */
+/// Return true if "name" is a full (absolute) path name or URL.
bool vim_isAbsName(char_u *name)
{
return path_with_url((char *)name) != 0 || path_is_absolute(name);
@@ -1830,7 +1816,7 @@ int vim_FullName(const char *fname, char *buf, size_t len, bool force)
if (strlen(fname) > (len - 1)) {
xstrlcpy(buf, fname, len); // truncate
-#ifdef WIN32
+#ifdef MSWIN
slash_adjust((char_u *)buf);
#endif
return FAIL;
@@ -1841,11 +1827,11 @@ int vim_FullName(const char *fname, char *buf, size_t len, bool force)
return OK;
}
- int rv = path_to_absolute((char_u *)fname, (char_u *)buf, len, force);
+ int rv = path_to_absolute(fname, buf, len, force);
if (rv == FAIL) {
xstrlcpy(buf, fname, len); // something failed; use the filename
}
-#ifdef WIN32
+#ifdef MSWIN
slash_adjust((char_u *)buf);
#endif
return rv;
@@ -1900,7 +1886,7 @@ void path_fix_case(char *name)
}
// Open the directory where the file is located.
- char *slash = (char *)STRRCHR(name, '/');
+ char *slash = strrchr(name, '/');
char *tail;
Directory dir;
bool ok;
@@ -1922,7 +1908,7 @@ void path_fix_case(char *name)
while ((entry = (char *)os_scandir_next(&dir))) {
// Only accept names that differ in case and are the same byte
// length. TODO: accept different length name.
- if (STRICMP(tail, entry) == 0 && STRLEN(tail) == STRLEN(entry)) {
+ if (STRICMP(tail, entry) == 0 && strlen(tail) == strlen(entry)) {
char_u newname[MAXPATHL + 1];
// Verify the inode is equal.
@@ -1941,21 +1927,17 @@ void path_fix_case(char *name)
os_closedir(&dir);
}
-/*
- * Return TRUE if "p" points to just after a path separator.
- * Takes care of multi-byte characters.
- * "b" must point to the start of the file name
- */
+/// Return true if "p" points to just after a path separator.
+/// Takes care of multi-byte characters.
+/// "b" must point to the start of the file name
int after_pathsep(const char *b, const char *p)
{
return p > b && vim_ispathsep(p[-1])
- && utf_head_off((char_u *)b, (char_u *)p - 1) == 0;
+ && utf_head_off(b, p - 1) == 0;
}
-/*
- * Return TRUE if file names "f1" and "f2" are in the same directory.
- * "f1" may be a short name, "f2" must be a full path.
- */
+/// Return true if file names "f1" and "f2" are in the same directory.
+/// "f1" may be a short name, "f2" must be a full path.
bool same_directory(char_u *f1, char_u *f2)
{
char ffname[MAXPATHL];
@@ -1967,18 +1949,16 @@ bool same_directory(char_u *f1, char_u *f2)
return false;
}
- (void)vim_FullName((char *)f1, (char *)ffname, MAXPATHL, FALSE);
+ (void)vim_FullName((char *)f1, (char *)ffname, MAXPATHL, false);
t1 = path_tail_with_sep(ffname);
t2 = path_tail_with_sep((char *)f2);
return t1 - ffname == (char_u *)t2 - f2
&& pathcmp((char *)ffname, (char *)f2, (int)(t1 - ffname)) == 0;
}
-/*
- * Compare path "p[]" to "q[]".
- * If "maxlen" >= 0 compare "p[maxlen]" to "q[maxlen]"
- * Return value like strcmp(p, q), but consider path separators.
- */
+// Compare path "p[]" to "q[]".
+// If "maxlen" >= 0 compare "p[maxlen]" to "q[maxlen]"
+// Return value like strcmp(p, q), but consider path separators.
int pathcmp(const char *p, const char *q, int maxlen)
{
int i, j;
@@ -2063,7 +2043,7 @@ char_u *path_try_shorten_fname(char_u *full_path)
char_u *p = full_path;
if (os_dirname(dirname, MAXPATHL) == OK) {
- p = path_shorten_fname(full_path, dirname);
+ p = (char_u *)path_shorten_fname((char *)full_path, (char *)dirname);
if (p == NULL || *p == NUL) {
p = full_path;
}
@@ -2079,27 +2059,27 @@ char_u *path_try_shorten_fname(char_u *full_path)
/// @return
/// - Pointer into `full_path` if shortened.
/// - NULL if no shorter name is possible.
-char_u *path_shorten_fname(char_u *full_path, char_u *dir_name)
+char *path_shorten_fname(char *full_path, char *dir_name)
{
if (full_path == NULL) {
return NULL;
}
assert(dir_name != NULL);
- size_t len = STRLEN(dir_name);
+ size_t len = strlen(dir_name);
// If dir_name is a path head, full_path can always be made relative.
- if (len == (size_t)path_head_length() && is_path_head(dir_name)) {
+ if (len == (size_t)path_head_length() && is_path_head((char_u *)dir_name)) {
return full_path + len;
}
// If full_path and dir_name do not match, it's impossible to make one
// relative to the other.
- if (FNAMENCMP(dir_name, full_path, len) != 0) {
+ if (path_fnamencmp(dir_name, full_path, len) != 0) {
return NULL;
}
- char_u *p = full_path + len;
+ char_u *p = (char_u *)full_path + len;
// If *p is not pointing to a path separator, this means that full_path's
// last directory name is longer than *dir_name's last directory, so they
@@ -2108,7 +2088,7 @@ char_u *path_shorten_fname(char_u *full_path, char_u *dir_name)
return NULL;
}
- return p + 1;
+ return (char *)p + 1;
}
/// Invoke expand_wildcards() for one pattern
@@ -2125,20 +2105,25 @@ char_u *path_shorten_fname(char_u *full_path, char_u *dir_name)
/// If FAIL is returned, *num_file and *file are either
/// unchanged or *num_file is set to 0 and *file is set
/// to NULL or points to "".
-int expand_wildcards_eval(char_u **pat, int *num_file, char ***file, int flags)
+int expand_wildcards_eval(char **pat, int *num_file, char ***file, int flags)
{
int ret = FAIL;
- char_u *eval_pat = NULL;
- char *exp_pat = (char *)(*pat);
+ char *eval_pat = NULL;
+ char *exp_pat = *pat;
char *ignored_msg;
size_t usedlen;
+ const bool is_cur_alt_file = *exp_pat == '%' || *exp_pat == '#';
+ bool star_follows = false;
- if (*exp_pat == '%' || *exp_pat == '#' || *exp_pat == '<') {
+ if (is_cur_alt_file || *exp_pat == '<') {
emsg_off++;
- eval_pat = eval_vars((char_u *)exp_pat, (char_u *)exp_pat, &usedlen, NULL, &ignored_msg, NULL);
+ eval_pat = (char *)eval_vars((char_u *)exp_pat, (char_u *)exp_pat, &usedlen, NULL, &ignored_msg,
+ NULL,
+ true);
emsg_off--;
if (eval_pat != NULL) {
- exp_pat = (char *)concat_str(eval_pat, (char_u *)exp_pat + usedlen);
+ star_follows = strcmp(exp_pat + usedlen, "*") == 0;
+ exp_pat = concat_str(eval_pat, exp_pat + usedlen);
}
}
@@ -2147,6 +2132,16 @@ int expand_wildcards_eval(char_u **pat, int *num_file, char ***file, int flags)
}
if (eval_pat != NULL) {
+ if (*num_file == 0 && is_cur_alt_file && star_follows) {
+ // Expanding "%" or "#" and the file does not exist: Add the
+ // pattern anyway (without the star) so that this works for remote
+ // files and non-file buffer names.
+ *file = xmalloc(sizeof(char *));
+ **file = eval_pat;
+ eval_pat = NULL;
+ *num_file = 1;
+ ret = OK;
+ }
xfree(exp_pat);
xfree(eval_pat);
}
@@ -2182,9 +2177,7 @@ int expand_wildcards(int num_pat, char **pat, int *num_files, char ***files, int
return retval;
}
- /*
- * Remove names that match 'wildignore'.
- */
+ // Remove names that match 'wildignore'.
if (*p_wig) {
char_u *ffname;
@@ -2194,7 +2187,7 @@ int expand_wildcards(int num_pat, char **pat, int *num_files, char ***files, int
ffname = (char_u *)FullName_save((*files)[i], false);
assert((*files)[i] != NULL);
assert(ffname != NULL);
- if (match_file_list(p_wig, (char_u *)(*files)[i], ffname)) {
+ if (match_file_list((char_u *)p_wig, (char_u *)(*files)[i], ffname)) {
// remove this matching file from the list
xfree((*files)[i]);
for (j = i; j + 1 < *num_files; j++) {
@@ -2213,7 +2206,7 @@ int expand_wildcards(int num_pat, char **pat, int *num_files, char ***files, int
if (*num_files > 1 && !got_int) {
non_suf_match = 0;
for (i = 0; i < *num_files; i++) {
- if (!match_suffix((char_u *)(*files)[i])) {
+ if (!match_suffix((*files)[i])) {
// Move the name without matching suffix to the front of the list.
p = (char_u *)(*files)[i];
for (j = i; j > non_suf_match; j--) {
@@ -2233,29 +2226,27 @@ int expand_wildcards(int num_pat, char **pat, int *num_files, char ***files, int
return retval;
}
-/*
- * Return TRUE if "fname" matches with an entry in 'suffixes'.
- */
-int match_suffix(char_u *fname)
+/// @return true if "fname" matches with an entry in 'suffixes'.
+int match_suffix(char *fname)
{
#define MAXSUFLEN 30 // maximum length of a file suffix
- char_u suf_buf[MAXSUFLEN];
+ char suf_buf[MAXSUFLEN];
- size_t fnamelen = STRLEN(fname);
+ size_t fnamelen = strlen(fname);
size_t setsuflen = 0;
for (char_u *setsuf = p_su; *setsuf;) {
setsuflen = copy_option_part((char **)&setsuf, (char *)suf_buf, MAXSUFLEN, ".,");
if (setsuflen == 0) {
- char_u *tail = (char_u *)path_tail((char *)fname);
+ char *tail = path_tail(fname);
// empty entry: match name without a '.'
- if (vim_strchr((char *)tail, '.') == NULL) {
+ if (vim_strchr(tail, '.') == NULL) {
setsuflen = 1;
break;
}
} else {
if (fnamelen >= setsuflen
- && FNAMENCMP(suf_buf, fname + fnamelen - setsuflen, setsuflen) == 0) {
+ && path_fnamencmp(suf_buf, fname + fnamelen - setsuflen, setsuflen) == 0) {
break;
}
setsuflen = 0;
@@ -2273,7 +2264,7 @@ int path_full_dir_name(char *directory, char *buffer, size_t len)
int SUCCESS = 0;
int retval = OK;
- if (STRLEN(directory) == 0) {
+ if (strlen(directory) == 0) {
return os_dirname((char_u *)buffer, len);
}
@@ -2354,20 +2345,20 @@ int append_path(char *path, const char *to_append, size_t max_len)
/// @param force also expand when "fname" is already absolute.
///
/// @return FAIL for failure, OK for success.
-static int path_to_absolute(const char_u *fname, char_u *buf, size_t len, int force)
+static int path_to_absolute(const char *fname, char *buf, size_t len, int force)
{
- char_u *p;
+ char *p;
*buf = NUL;
char *relative_directory = xmalloc(len);
char *end_of_path = (char *)fname;
// expand it if forced or not an absolute path
- if (force || !path_is_absolute(fname)) {
- p = STRRCHR(fname, '/');
-#ifdef WIN32
+ if (force || !path_is_absolute((char_u *)fname)) {
+ p = strrchr(fname, '/');
+#ifdef MSWIN
if (p == NULL) {
- p = STRRCHR(fname, '\\');
+ p = strrchr(fname, '\\');
}
#endif
if (p != NULL) {
@@ -2381,27 +2372,27 @@ static int path_to_absolute(const char_u *fname, char_u *buf, size_t len, int fo
memcpy(relative_directory, fname, (size_t)(p - fname));
relative_directory[p - fname] = NUL;
}
- end_of_path = (char *)(p + 1);
+ end_of_path = p + 1;
} else {
relative_directory[0] = NUL;
end_of_path = (char *)fname;
}
- if (FAIL == path_full_dir_name(relative_directory, (char *)buf, len)) {
+ if (FAIL == path_full_dir_name(relative_directory, buf, len)) {
xfree(relative_directory);
return FAIL;
}
}
xfree(relative_directory);
- return append_path((char *)buf, end_of_path, len);
+ return append_path(buf, end_of_path, len);
}
/// Check if file `fname` is a full (absolute) path.
///
-/// @return `TRUE` if "fname" is absolute.
+/// @return `true` if "fname" is absolute.
int path_is_absolute(const char_u *fname)
{
-#ifdef WIN32
+#ifdef MSWIN
if (*fname == NUL) {
return false;
}
@@ -2449,8 +2440,8 @@ void path_guess_exepath(const char *argv0, char *buf, size_t bufsize)
continue;
}
STRLCPY(NameBuff, dir, dir_len + 1);
- STRLCAT(NameBuff, PATHSEPSTR, sizeof(NameBuff));
- STRLCAT(NameBuff, argv0, sizeof(NameBuff));
+ xstrlcat(NameBuff, PATHSEPSTR, sizeof(NameBuff));
+ xstrlcat(NameBuff, argv0, sizeof(NameBuff));
if (os_can_exe((char *)NameBuff, NULL, false)) {
xstrlcpy(buf, (char *)NameBuff, bufsize);
return;