diff options
author | John Schmidt <john.schmidt.h@gmail.com> | 2014-03-30 22:25:59 +0200 |
---|---|---|
committer | Thiago de Arruda <tpadilha84@gmail.com> | 2014-04-01 08:08:07 -0300 |
commit | f5082d0a708d08a9d71fa0f067a4e551ad533f2e (patch) | |
tree | 8246f973554c60ae08bf118a811bed9ee2332f45 | |
parent | 7fd140b99ac1a3762f68f9d24360aecf1330e6e2 (diff) | |
download | rneovim-f5082d0a708d08a9d71fa0f067a4e551ad533f2e.tar.gz rneovim-f5082d0a708d08a9d71fa0f067a4e551ad533f2e.tar.bz2 rneovim-f5082d0a708d08a9d71fa0f067a4e551ad533f2e.zip |
Move simplify_filename from tag.c
-rw-r--r-- | src/path.c | 169 | ||||
-rw-r--r-- | src/path.h | 1 | ||||
-rw-r--r-- | src/tag.c | 169 | ||||
-rw-r--r-- | src/tag.h | 1 |
4 files changed, 170 insertions, 170 deletions
diff --git a/src/path.c b/src/path.c index d1b3dcc05c..517d0fa42a 100644 --- a/src/path.c +++ b/src/path.c @@ -1301,3 +1301,172 @@ addfile ( ((char_u **)gap->ga_data)[gap->ga_len++] = p; } #endif /* !NO_EXPANDPATH */ + +/* + * 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; + char_u *p, *tail, *start; + int stripping_disabled = FALSE; + int relative = TRUE; + + p = filename; +#ifdef BACKSLASH_IN_FILENAME + if (p[1] == ':') /* skip "x:" */ + p += 2; +#endif + + if (vim_ispathsep(*p)) { + relative = FALSE; + do + ++p; + while (vim_ispathsep(*p)); + } + 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. */ + if (vim_ispathsep(*p)) + STRMOVE(p, p + 1); /* remove duplicate "/" */ + else if (p[0] == '.' && (vim_ispathsep(p[1]) || p[1] == NUL)) { + 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 . */ + tail = p + 1; + if (p[1] != NUL) + while (vim_ispathsep(*tail)) + mb_ptr_adv(tail); + else if (p > start) + --p; /* strip preceding path separator */ + STRMOVE(p, tail); + } + } else if (p[0] == '.' && p[1] == '.' && + (vim_ispathsep(p[2]) || p[2] == NUL)) { + /* Skip to after ".." or "../" or "..///". */ + tail = p + 2; + while (vim_ispathsep(*tail)) + mb_ptr_adv(tail); + + if (components > 0) { /* strip one preceding component */ + int do_strip = FALSE; + char_u saved_char; + struct stat st; + + /* 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. */ + saved_char = p[-1]; + p[-1] = NUL; +#ifdef UNIX + if (mch_lstat((char *)filename, &st) < 0) +#else + if (mch_stat((char *)filename, &st) < 0) +#endif + do_strip = TRUE; + p[-1] = saved_char; + + --p; + /* Skip back to after previous '/'. */ + while (p > start && !after_pathsep(start, p)) + mb_ptr_back(start, p); + + 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. */ + saved_char = *tail; + *tail = NUL; + if (mch_stat((char *)filename, &st) >= 0) + do_strip = TRUE; + else + stripping_disabled = TRUE; + *tail = saved_char; +#ifdef UNIX + if (do_strip) { + struct stat new_st; + + /* On Unix, 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.) */ + if (p == start && relative) + (void)mch_stat(".", &new_st); + else { + saved_char = *p; + *p = NUL; + (void)mch_stat((char *)filename, &new_st); + *p = saved_char; + } + + if (new_st.st_ino != st.st_ino || + new_st.st_dev != st.st_dev) { + do_strip = FALSE; + /* We don't disable stripping of later + * components since the unstripped path name is + * still valid. */ + } + } +#endif + } + } + + if (!do_strip) { + /* 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. */ + if (p == start && relative && tail[-1] == '.') { + *p++ = '.'; + *p = NUL; + } else { + if (p > start && tail[-1] == '.') + --p; + STRMOVE(p, tail); /* strip previous component */ + } + + --components; + } + } else if (p == start && !relative) /* leading "/.." or "/../" */ + STRMOVE(p, tail); /* strip ".." or "../" */ + else { + if (p == start + 2 && p[-2] == '.') { /* leading "./../" */ + STRMOVE(p - 2, p); /* strip leading "./" */ + tail -= 2; + } + p = tail; /* skip to char after ".." or "../" */ + } + } else { + ++components; /* simple path component */ + p = getnextcomp(p); + } + } while (*p != NUL); +} diff --git a/src/path.h b/src/path.h index cf46b0f02f..a126d1a67e 100644 --- a/src/path.h +++ b/src/path.h @@ -22,4 +22,5 @@ char_u *get_past_head(char_u *path); char_u *concat_str(char_u *str1, char_u *str2); void add_pathsep(char_u *p); char_u *FullName_save(char_u *fname, int force); +void simplify_filename(char_u *filename); #endif @@ -2722,175 +2722,6 @@ static char_u *expand_tag_fname(char_u *fname, char_u *tag_fname, int expand) } /* - * 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; - char_u *p, *tail, *start; - int stripping_disabled = FALSE; - int relative = TRUE; - - p = filename; -#ifdef BACKSLASH_IN_FILENAME - if (p[1] == ':') /* skip "x:" */ - p += 2; -#endif - - if (vim_ispathsep(*p)) { - relative = FALSE; - do - ++p; - while (vim_ispathsep(*p)); - } - 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. */ - if (vim_ispathsep(*p)) - STRMOVE(p, p + 1); /* remove duplicate "/" */ - else if (p[0] == '.' && (vim_ispathsep(p[1]) || p[1] == NUL)) { - 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 . */ - tail = p + 1; - if (p[1] != NUL) - while (vim_ispathsep(*tail)) - mb_ptr_adv(tail); - else if (p > start) - --p; /* strip preceding path separator */ - STRMOVE(p, tail); - } - } else if (p[0] == '.' && p[1] == '.' && - (vim_ispathsep(p[2]) || p[2] == NUL)) { - /* Skip to after ".." or "../" or "..///". */ - tail = p + 2; - while (vim_ispathsep(*tail)) - mb_ptr_adv(tail); - - if (components > 0) { /* strip one preceding component */ - int do_strip = FALSE; - char_u saved_char; - struct stat st; - - /* 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. */ - saved_char = p[-1]; - p[-1] = NUL; -#ifdef UNIX - if (mch_lstat((char *)filename, &st) < 0) -#else - if (mch_stat((char *)filename, &st) < 0) -#endif - do_strip = TRUE; - p[-1] = saved_char; - - --p; - /* Skip back to after previous '/'. */ - while (p > start && !after_pathsep(start, p)) - mb_ptr_back(start, p); - - 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. */ - saved_char = *tail; - *tail = NUL; - if (mch_stat((char *)filename, &st) >= 0) - do_strip = TRUE; - else - stripping_disabled = TRUE; - *tail = saved_char; -#ifdef UNIX - if (do_strip) { - struct stat new_st; - - /* On Unix, 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.) */ - if (p == start && relative) - (void)mch_stat(".", &new_st); - else { - saved_char = *p; - *p = NUL; - (void)mch_stat((char *)filename, &new_st); - *p = saved_char; - } - - if (new_st.st_ino != st.st_ino || - new_st.st_dev != st.st_dev) { - do_strip = FALSE; - /* We don't disable stripping of later - * components since the unstripped path name is - * still valid. */ - } - } -#endif - } - } - - if (!do_strip) { - /* 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. */ - if (p == start && relative && tail[-1] == '.') { - *p++ = '.'; - *p = NUL; - } else { - if (p > start && tail[-1] == '.') - --p; - STRMOVE(p, tail); /* strip previous component */ - } - - --components; - } - } else if (p == start && !relative) /* leading "/.." or "/../" */ - STRMOVE(p, tail); /* strip ".." or "../" */ - else { - if (p == start + 2 && p[-2] == '.') { /* leading "./../" */ - STRMOVE(p - 2, p); /* strip leading "./" */ - tail -= 2; - } - p = tail; /* skip to char after ".." or "../" */ - } - } else { - ++components; /* simple path component */ - p = getnextcomp(p); - } - } while (*p != NUL); -} - -/* * Check if we have a tag for the buffer with name "buf_ffname". * This is a bit slow, because of the full path compare in fullpathcmp(). * Return TRUE if tag for file "fname" if tag file "tag_fname" is for current @@ -21,7 +21,6 @@ int find_tags(char_u *pat, int *num_matches, char_u ***matchesp, void free_tag_stuff(void); int get_tagfname(tagname_T *tnp, int first, char_u *buf); void tagname_free(tagname_T *tnp); -void simplify_filename(char_u *filename); int expand_tags(int tagnames, char_u *pat, int *num_file, char_u ***file); int get_tags(list_T *list, char_u *pat); |