diff options
Diffstat (limited to 'data/vim/patches/8.1.1099')
-rw-r--r-- | data/vim/patches/8.1.1099 | 1326 |
1 files changed, 1326 insertions, 0 deletions
diff --git a/data/vim/patches/8.1.1099 b/data/vim/patches/8.1.1099 new file mode 100644 index 000000000..9aa426928 --- /dev/null +++ b/data/vim/patches/8.1.1099 @@ -0,0 +1,1326 @@ +To: vim_dev@googlegroups.com +Subject: Patch 8.1.1099 +Fcc: outbox +From: Bram Moolenaar <Bram@moolenaar.net> +Mime-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +------------ + +Patch 8.1.1099 +Problem: The do_tag() function is too long. +Solution: Factor parts out to separate functions. Move simplify_filename() + to a file where it fits better. (Andy Massimino, closes #4195) +Files: src/tag.c, src/proto/tag.pro, src/findfile.c, + src/proto/findfile.pro + + +*** ../vim-8.1.1098/src/tag.c 2019-03-30 21:41:44.218279831 +0100 +--- src/tag.c 2019-03-31 19:14:18.988597395 +0200 +*************** +*** 74,79 **** +--- 74,83 ---- + static int test_for_current(char_u *, char_u *, char_u *, char_u *); + #endif + static int find_extra(char_u **pp); ++ static void print_tag_list(int new_tag, int use_tagstack, int num_matches, char_u **matches); ++ #if defined(FEAT_QUICKFIX) && defined(FEAT_EVAL) ++ static int add_llist_tags(char_u *tag, int num_matches, char_u **matches); ++ #endif + + static char_u *bottommsg = (char_u *)N_("E555: at bottom of tag stack"); + static char_u *topmsg = (char_u *)N_("E556: at top of tag stack"); +*************** +*** 125,149 **** + int prevtagstackidx = tagstackidx; + int prev_num_matches; + int new_tag = FALSE; +! int other_name; +! int i, j, k; +! int idx; + int ic; +- char_u *p; +- char_u *name; + int no_regexp = FALSE; + int error_cur_match = 0; +- char_u *command_end; + int save_pos = FALSE; + fmark_T saved_fmark; +- int taglen; + #ifdef FEAT_CSCOPE + int jumped_to_tag = FALSE; + #endif +- tagptrs_T tagp, tagp2; + int new_num_matches; + char_u **new_matches; +- int attr; + int use_tagstack; + int skip_msg = FALSE; + char_u *buf_ffname = curbuf->b_ffname; /* name to use for +--- 129,145 ---- + int prevtagstackidx = tagstackidx; + int prev_num_matches; + int new_tag = FALSE; +! int i; + int ic; + int no_regexp = FALSE; + int error_cur_match = 0; + int save_pos = FALSE; + fmark_T saved_fmark; + #ifdef FEAT_CSCOPE + int jumped_to_tag = FALSE; + #endif + int new_num_matches; + char_u **new_matches; + int use_tagstack; + int skip_msg = FALSE; + char_u *buf_ffname = curbuf->b_ffname; /* name to use for +*************** +*** 482,487 **** +--- 478,486 ---- + */ + for (;;) + { ++ int other_name; ++ char_u *name; ++ + /* + * When desired match not found yet, try to find it (and others). + */ +*************** +*** 541,549 **** + * ":tnext" and jumping to another file. */ + if (!new_tag && !other_name) + { + /* Find the position of each old match in the new list. Need + * to use parse_match() to find the tag line. */ +- idx = 0; + for (j = 0; j < num_matches; ++j) + { + parse_match(matches[j], &tagp); +--- 540,551 ---- + * ":tnext" and jumping to another file. */ + if (!new_tag && !other_name) + { ++ int j, k; ++ int idx = 0; ++ tagptrs_T tagp, tagp2; ++ + /* Find the position of each old match in the new list. Need + * to use parse_match() to find the tag line. */ + for (j = 0; j < num_matches; ++j) + { + parse_match(matches[j], &tagp); +*************** +*** 552,558 **** + parse_match(new_matches[i], &tagp2); + if (STRCMP(tagp.tagname, tagp2.tagname) == 0) + { +! p = new_matches[i]; + for (k = i; k > idx; --k) + new_matches[k] = new_matches[k - 1]; + new_matches[idx++] = p; +--- 554,560 ---- + parse_match(new_matches[i], &tagp2); + if (STRCMP(tagp.tagname, tagp2.tagname) == 0) + { +! char_u *p = new_matches[i]; + for (k = i; k > idx; --k) + new_matches[k] = new_matches[k - 1]; + new_matches[idx++] = p; +*************** +*** 587,927 **** + else + #endif + if (type == DT_TAG && *tag != NUL) +! /* +! * If a count is supplied to the ":tag <name>" command, then +! * jump to count'th matching tag. +! */ + cur_match = count > 0 ? count - 1 : 0; + else if (type == DT_SELECT || (type == DT_JUMP && num_matches > 1)) + { +! /* +! * List all the matching tags. +! * Assume that the first match indicates how long the tags can +! * be, and align the file names to that. +! */ +! parse_match(matches[0], &tagp); +! taglen = (int)(tagp.tagname_end - tagp.tagname + 2); +! if (taglen < 18) +! taglen = 18; +! if (taglen > Columns - 25) +! taglen = MAXCOL; +! if (msg_col == 0) +! msg_didout = FALSE; /* overwrite previous message */ +! msg_start(); +! msg_puts_attr(_(" # pri kind tag"), HL_ATTR(HLF_T)); +! msg_clr_eos(); +! taglen_advance(taglen); +! msg_puts_attr(_("file\n"), HL_ATTR(HLF_T)); +! +! for (i = 0; i < num_matches && !got_int; ++i) +! { +! parse_match(matches[i], &tagp); +! if (!new_tag && ( +! #if defined(FEAT_QUICKFIX) +! (g_do_tagpreview != 0 +! && i == ptag_entry.cur_match) || +! #endif +! (use_tagstack +! && i == tagstack[tagstackidx].cur_match))) +! *IObuff = '>'; +! else +! *IObuff = ' '; +! vim_snprintf((char *)IObuff + 1, IOSIZE - 1, +! "%2d %s ", i + 1, +! mt_names[matches[i][0] & MT_MASK]); +! msg_puts((char *)IObuff); +! if (tagp.tagkind != NULL) +! msg_outtrans_len(tagp.tagkind, +! (int)(tagp.tagkind_end - tagp.tagkind)); +! msg_advance(13); +! msg_outtrans_len_attr(tagp.tagname, +! (int)(tagp.tagname_end - tagp.tagname), +! HL_ATTR(HLF_T)); +! msg_putchar(' '); +! taglen_advance(taglen); +! +! /* Find out the actual file name. If it is long, truncate +! * it and put "..." in the middle */ +! p = tag_full_fname(&tagp); +! if (p != NULL) +! { +! msg_outtrans_long_attr(p, HL_ATTR(HLF_D)); +! vim_free(p); +! } +! if (msg_col > 0) +! msg_putchar('\n'); +! if (got_int) +! break; +! msg_advance(15); +! +! /* print any extra fields */ +! command_end = tagp.command_end; +! if (command_end != NULL) +! { +! p = command_end + 3; +! while (*p && *p != '\r' && *p != '\n') +! { +! while (*p == TAB) +! ++p; +! +! /* skip "file:" without a value (static tag) */ +! if (STRNCMP(p, "file:", 5) == 0 +! && vim_isspace(p[5])) +! { +! p += 5; +! continue; +! } +! /* skip "kind:<kind>" and "<kind>" */ +! if (p == tagp.tagkind +! || (p + 5 == tagp.tagkind +! && STRNCMP(p, "kind:", 5) == 0)) +! { +! p = tagp.tagkind_end; +! continue; +! } +! /* print all other extra fields */ +! attr = HL_ATTR(HLF_CM); +! while (*p && *p != '\r' && *p != '\n') +! { +! if (msg_col + ptr2cells(p) >= Columns) +! { +! msg_putchar('\n'); +! if (got_int) +! break; +! msg_advance(15); +! } +! p = msg_outtrans_one(p, attr); +! if (*p == TAB) +! { +! msg_puts_attr(" ", attr); +! break; +! } +! if (*p == ':') +! attr = 0; +! } +! } +! if (msg_col > 15) +! { +! msg_putchar('\n'); +! if (got_int) +! break; +! msg_advance(15); +! } +! } +! else +! { +! for (p = tagp.command; +! *p && *p != '\r' && *p != '\n'; ++p) +! ; +! command_end = p; +! } +! +! /* +! * Put the info (in several lines) at column 15. +! * Don't display "/^" and "?^". +! */ +! p = tagp.command; +! if (*p == '/' || *p == '?') +! { +! ++p; +! if (*p == '^') +! ++p; +! } +! /* Remove leading whitespace from pattern */ +! while (p != command_end && vim_isspace(*p)) +! ++p; +! +! while (p != command_end) +! { +! if (msg_col + (*p == TAB ? 1 : ptr2cells(p)) > Columns) +! msg_putchar('\n'); +! if (got_int) +! break; +! msg_advance(15); +! +! /* skip backslash used for escaping a command char or +! * a backslash */ +! if (*p == '\\' && (*(p + 1) == *tagp.command +! || *(p + 1) == '\\')) +! ++p; +! +! if (*p == TAB) +! { +! msg_putchar(' '); +! ++p; +! } +! else +! p = msg_outtrans_one(p, 0); +! +! /* don't display the "$/;\"" and "$?;\"" */ +! if (p == command_end - 2 && *p == '$' +! && *(p + 1) == *tagp.command) +! break; +! /* don't display matching '/' or '?' */ +! if (p == command_end - 1 && *p == *tagp.command +! && (*p == '/' || *p == '?')) +! break; +! } +! if (msg_col) +! msg_putchar('\n'); +! ui_breakcheck(); +! } +! if (got_int) +! got_int = FALSE; /* only stop the listing */ + ask_for_selection = TRUE; + } + #if defined(FEAT_QUICKFIX) && defined(FEAT_EVAL) + else if (type == DT_LTAG) + { +! list_T *list; +! char_u tag_name[128 + 1]; +! char_u *fname; +! char_u *cmd; +! +! /* +! * Add the matching tags to the location list for the current +! * window. +! */ +! +! fname = alloc(MAXPATHL + 1); +! cmd = alloc(CMDBUFFSIZE + 1); +! list = list_alloc(); +! if (list == NULL || fname == NULL || cmd == NULL) +! { +! vim_free(cmd); +! vim_free(fname); +! if (list != NULL) +! list_free(list); + goto end_do_tag; +- } +- +- for (i = 0; i < num_matches; ++i) +- { +- int len, cmd_len; +- long lnum; +- dict_T *dict; +- +- parse_match(matches[i], &tagp); +- +- /* Save the tag name */ +- len = (int)(tagp.tagname_end - tagp.tagname); +- if (len > 128) +- len = 128; +- vim_strncpy(tag_name, tagp.tagname, len); +- tag_name[len] = NUL; +- +- /* Save the tag file name */ +- p = tag_full_fname(&tagp); +- if (p == NULL) +- continue; +- vim_strncpy(fname, p, MAXPATHL); +- vim_free(p); +- +- /* +- * Get the line number or the search pattern used to locate +- * the tag. +- */ +- lnum = 0; +- if (isdigit(*tagp.command)) +- /* Line number is used to locate the tag */ +- lnum = atol((char *)tagp.command); +- else +- { +- char_u *cmd_start, *cmd_end; +- +- /* Search pattern is used to locate the tag */ +- +- /* Locate the end of the command */ +- cmd_start = tagp.command; +- cmd_end = tagp.command_end; +- if (cmd_end == NULL) +- { +- for (p = tagp.command; +- *p && *p != '\r' && *p != '\n'; ++p) +- ; +- cmd_end = p; +- } +- +- /* +- * Now, cmd_end points to the character after the +- * command. Adjust it to point to the last +- * character of the command. +- */ +- cmd_end--; +- +- /* +- * Skip the '/' and '?' characters at the +- * beginning and end of the search pattern. +- */ +- if (*cmd_start == '/' || *cmd_start == '?') +- cmd_start++; +- +- if (*cmd_end == '/' || *cmd_end == '?') +- cmd_end--; +- +- len = 0; +- cmd[0] = NUL; +- +- /* +- * If "^" is present in the tag search pattern, then +- * copy it first. +- */ +- if (*cmd_start == '^') +- { +- STRCPY(cmd, "^"); +- cmd_start++; +- len++; +- } +- +- /* +- * Precede the tag pattern with \V to make it very +- * nomagic. +- */ +- STRCAT(cmd, "\\V"); +- len += 2; +- +- cmd_len = (int)(cmd_end - cmd_start + 1); +- if (cmd_len > (CMDBUFFSIZE - 5)) +- cmd_len = CMDBUFFSIZE - 5; +- STRNCAT(cmd, cmd_start, cmd_len); +- len += cmd_len; +- +- if (cmd[len - 1] == '$') +- { +- /* +- * Replace '$' at the end of the search pattern +- * with '\$' +- */ +- cmd[len - 1] = '\\'; +- cmd[len] = '$'; +- len++; +- } +- +- cmd[len] = NUL; +- } +- +- if ((dict = dict_alloc()) == NULL) +- continue; +- if (list_append_dict(list, dict) == FAIL) +- { +- vim_free(dict); +- continue; +- } +- +- dict_add_string(dict, "text", tag_name); +- dict_add_string(dict, "filename", fname); +- dict_add_number(dict, "lnum", lnum); +- if (lnum == 0) +- dict_add_string(dict, "pattern", cmd); +- } +- +- vim_snprintf((char *)IObuff, IOSIZE, "ltag %s", tag); +- set_errorlist(curwin, list, ' ', IObuff, NULL); +- +- list_free(list); +- vim_free(fname); +- vim_free(cmd); +- + cur_match = 0; /* Jump to the first tag */ + } + #endif +--- 589,607 ---- + else + #endif + if (type == DT_TAG && *tag != NUL) +! // If a count is supplied to the ":tag <name>" command, then +! // jump to count'th matching tag. + cur_match = count > 0 ? count - 1 : 0; + else if (type == DT_SELECT || (type == DT_JUMP && num_matches > 1)) + { +! print_tag_list(new_tag, use_tagstack, num_matches, matches); + ask_for_selection = TRUE; + } + #if defined(FEAT_QUICKFIX) && defined(FEAT_EVAL) + else if (type == DT_LTAG) + { +! if (add_llist_tags(tag, num_matches, matches) == FAIL) + goto end_do_tag; + cur_match = 0; /* Jump to the first tag */ + } + #endif +*************** +*** 1089,1094 **** +--- 769,1116 ---- + } + + /* ++ * List all the matching tags. ++ */ ++ static void ++ print_tag_list( ++ int new_tag, ++ int use_tagstack, ++ int num_matches, ++ char_u **matches) ++ { ++ taggy_T *tagstack = curwin->w_tagstack; ++ int tagstackidx = curwin->w_tagstackidx; ++ int i; ++ char_u *p; ++ char_u *command_end; ++ tagptrs_T tagp; ++ int taglen; ++ int attr; ++ ++ /* ++ * Assume that the first match indicates how long the tags can ++ * be, and align the file names to that. ++ */ ++ parse_match(matches[0], &tagp); ++ taglen = (int)(tagp.tagname_end - tagp.tagname + 2); ++ if (taglen < 18) ++ taglen = 18; ++ if (taglen > Columns - 25) ++ taglen = MAXCOL; ++ if (msg_col == 0) ++ msg_didout = FALSE; // overwrite previous message ++ msg_start(); ++ msg_puts_attr(_(" # pri kind tag"), HL_ATTR(HLF_T)); ++ msg_clr_eos(); ++ taglen_advance(taglen); ++ msg_puts_attr(_("file\n"), HL_ATTR(HLF_T)); ++ ++ for (i = 0; i < num_matches && !got_int; ++i) ++ { ++ parse_match(matches[i], &tagp); ++ if (!new_tag && ( ++ #if defined(FEAT_QUICKFIX) ++ (g_do_tagpreview != 0 ++ && i == ptag_entry.cur_match) || ++ #endif ++ (use_tagstack ++ && i == tagstack[tagstackidx].cur_match))) ++ *IObuff = '>'; ++ else ++ *IObuff = ' '; ++ vim_snprintf((char *)IObuff + 1, IOSIZE - 1, ++ "%2d %s ", i + 1, ++ mt_names[matches[i][0] & MT_MASK]); ++ msg_puts((char *)IObuff); ++ if (tagp.tagkind != NULL) ++ msg_outtrans_len(tagp.tagkind, ++ (int)(tagp.tagkind_end - tagp.tagkind)); ++ msg_advance(13); ++ msg_outtrans_len_attr(tagp.tagname, ++ (int)(tagp.tagname_end - tagp.tagname), ++ HL_ATTR(HLF_T)); ++ msg_putchar(' '); ++ taglen_advance(taglen); ++ ++ // Find out the actual file name. If it is long, truncate ++ // it and put "..." in the middle ++ p = tag_full_fname(&tagp); ++ if (p != NULL) ++ { ++ msg_outtrans_long_attr(p, HL_ATTR(HLF_D)); ++ vim_free(p); ++ } ++ if (msg_col > 0) ++ msg_putchar('\n'); ++ if (got_int) ++ break; ++ msg_advance(15); ++ ++ // print any extra fields ++ command_end = tagp.command_end; ++ if (command_end != NULL) ++ { ++ p = command_end + 3; ++ while (*p && *p != '\r' && *p != '\n') ++ { ++ while (*p == TAB) ++ ++p; ++ ++ // skip "file:" without a value (static tag) ++ if (STRNCMP(p, "file:", 5) == 0 ++ && vim_isspace(p[5])) ++ { ++ p += 5; ++ continue; ++ } ++ // skip "kind:<kind>" and "<kind>" ++ if (p == tagp.tagkind ++ || (p + 5 == tagp.tagkind ++ && STRNCMP(p, "kind:", 5) == 0)) ++ { ++ p = tagp.tagkind_end; ++ continue; ++ } ++ // print all other extra fields ++ attr = HL_ATTR(HLF_CM); ++ while (*p && *p != '\r' && *p != '\n') ++ { ++ if (msg_col + ptr2cells(p) >= Columns) ++ { ++ msg_putchar('\n'); ++ if (got_int) ++ break; ++ msg_advance(15); ++ } ++ p = msg_outtrans_one(p, attr); ++ if (*p == TAB) ++ { ++ msg_puts_attr(" ", attr); ++ break; ++ } ++ if (*p == ':') ++ attr = 0; ++ } ++ } ++ if (msg_col > 15) ++ { ++ msg_putchar('\n'); ++ if (got_int) ++ break; ++ msg_advance(15); ++ } ++ } ++ else ++ { ++ for (p = tagp.command; ++ *p && *p != '\r' && *p != '\n'; ++p) ++ ; ++ command_end = p; ++ } ++ ++ // Put the info (in several lines) at column 15. ++ // Don't display "/^" and "?^". ++ p = tagp.command; ++ if (*p == '/' || *p == '?') ++ { ++ ++p; ++ if (*p == '^') ++ ++p; ++ } ++ // Remove leading whitespace from pattern ++ while (p != command_end && vim_isspace(*p)) ++ ++p; ++ ++ while (p != command_end) ++ { ++ if (msg_col + (*p == TAB ? 1 : ptr2cells(p)) > Columns) ++ msg_putchar('\n'); ++ if (got_int) ++ break; ++ msg_advance(15); ++ ++ // skip backslash used for escaping a command char or ++ // a backslash ++ if (*p == '\\' && (*(p + 1) == *tagp.command ++ || *(p + 1) == '\\')) ++ ++p; ++ ++ if (*p == TAB) ++ { ++ msg_putchar(' '); ++ ++p; ++ } ++ else ++ p = msg_outtrans_one(p, 0); ++ ++ // don't display the "$/;\"" and "$?;\"" ++ if (p == command_end - 2 && *p == '$' ++ && *(p + 1) == *tagp.command) ++ break; ++ // don't display matching '/' or '?' ++ if (p == command_end - 1 && *p == *tagp.command ++ && (*p == '/' || *p == '?')) ++ break; ++ } ++ if (msg_col) ++ msg_putchar('\n'); ++ ui_breakcheck(); ++ } ++ if (got_int) ++ got_int = FALSE; // only stop the listing ++ } ++ ++ #if defined(FEAT_QUICKFIX) && defined(FEAT_EVAL) ++ /* ++ * Add the matching tags to the location list for the current ++ * window. ++ */ ++ static int ++ add_llist_tags( ++ char_u *tag, ++ int num_matches, ++ char_u **matches) ++ { ++ list_T *list; ++ char_u tag_name[128 + 1]; ++ char_u *fname; ++ char_u *cmd; ++ int i; ++ char_u *p; ++ tagptrs_T tagp; ++ ++ fname = alloc(MAXPATHL + 1); ++ cmd = alloc(CMDBUFFSIZE + 1); ++ list = list_alloc(); ++ if (list == NULL || fname == NULL || cmd == NULL) ++ { ++ vim_free(cmd); ++ vim_free(fname); ++ if (list != NULL) ++ list_free(list); ++ return FAIL; ++ } ++ ++ for (i = 0; i < num_matches; ++i) ++ { ++ int len, cmd_len; ++ long lnum; ++ dict_T *dict; ++ ++ parse_match(matches[i], &tagp); ++ ++ /* Save the tag name */ ++ len = (int)(tagp.tagname_end - tagp.tagname); ++ if (len > 128) ++ len = 128; ++ vim_strncpy(tag_name, tagp.tagname, len); ++ tag_name[len] = NUL; ++ ++ // Save the tag file name ++ p = tag_full_fname(&tagp); ++ if (p == NULL) ++ continue; ++ vim_strncpy(fname, p, MAXPATHL); ++ vim_free(p); ++ ++ // Get the line number or the search pattern used to locate ++ // the tag. ++ lnum = 0; ++ if (isdigit(*tagp.command)) ++ // Line number is used to locate the tag ++ lnum = atol((char *)tagp.command); ++ else ++ { ++ char_u *cmd_start, *cmd_end; ++ ++ // Search pattern is used to locate the tag ++ ++ // Locate the end of the command ++ cmd_start = tagp.command; ++ cmd_end = tagp.command_end; ++ if (cmd_end == NULL) ++ { ++ for (p = tagp.command; ++ *p && *p != '\r' && *p != '\n'; ++p) ++ ; ++ cmd_end = p; ++ } ++ ++ // Now, cmd_end points to the character after the ++ // command. Adjust it to point to the last ++ // character of the command. ++ cmd_end--; ++ ++ // Skip the '/' and '?' characters at the ++ // beginning and end of the search pattern. ++ if (*cmd_start == '/' || *cmd_start == '?') ++ cmd_start++; ++ ++ if (*cmd_end == '/' || *cmd_end == '?') ++ cmd_end--; ++ ++ len = 0; ++ cmd[0] = NUL; ++ ++ // If "^" is present in the tag search pattern, then ++ // copy it first. ++ if (*cmd_start == '^') ++ { ++ STRCPY(cmd, "^"); ++ cmd_start++; ++ len++; ++ } ++ ++ // Precede the tag pattern with \V to make it very ++ // nomagic. ++ STRCAT(cmd, "\\V"); ++ len += 2; ++ ++ cmd_len = (int)(cmd_end - cmd_start + 1); ++ if (cmd_len > (CMDBUFFSIZE - 5)) ++ cmd_len = CMDBUFFSIZE - 5; ++ STRNCAT(cmd, cmd_start, cmd_len); ++ len += cmd_len; ++ ++ if (cmd[len - 1] == '$') ++ { ++ // Replace '$' at the end of the search pattern ++ // with '\$' ++ cmd[len - 1] = '\\'; ++ cmd[len] = '$'; ++ len++; ++ } ++ ++ cmd[len] = NUL; ++ } ++ ++ if ((dict = dict_alloc()) == NULL) ++ continue; ++ if (list_append_dict(list, dict) == FAIL) ++ { ++ vim_free(dict); ++ continue; ++ } ++ ++ dict_add_string(dict, "text", tag_name); ++ dict_add_string(dict, "filename", fname); ++ dict_add_number(dict, "lnum", lnum); ++ if (lnum == 0) ++ dict_add_string(dict, "pattern", cmd); ++ } ++ ++ vim_snprintf((char *)IObuff, IOSIZE, "ltag %s", tag); ++ set_errorlist(curwin, list, ' ', IObuff, NULL); ++ ++ list_free(list); ++ vim_free(fname); ++ vim_free(cmd); ++ ++ return OK; ++ } ++ #endif ++ ++ /* + * Free cached tags. + */ + void +*************** +*** 3431,3648 **** + } + + /* +- * 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) +- { +- #ifndef AMIGA /* Amiga doesn't have "..", it uses "/" */ +- 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. */ +- #ifdef VMS +- /* VMS allows device:[path] - don't strip the [ in directory */ +- if ((*p == '[' || *p == '<') && p > filename && p[-1] == ':') +- { +- /* :[ or :< composition: vms directory component */ +- ++components; +- p = getnextcomp(p + 1); +- } +- /* allow remote calls as host"user passwd"::device:[path] */ +- else if (p[0] == ':' && p[1] == ':' && p > filename && p[-1] == '"' ) +- { +- /* ":: composition: vms host/passwd component */ +- ++components; +- p = getnextcomp(p + 2); +- } +- else +- #endif +- 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; +- stat_T 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) +- { +- stat_T 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); +- #endif /* !AMIGA */ +- } +- +- /* + * 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 +--- 3453,3458 ---- +*** ../vim-8.1.1098/src/proto/tag.pro 2018-11-11 15:20:32.436704418 +0100 +--- src/proto/tag.pro 2019-03-31 19:09:23.798893253 +0200 +*************** +*** 6,12 **** + 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, char_u *buf_fname); + void get_tagstack(win_T *wp, dict_T *retdict); +--- 6,11 ---- +*** ../vim-8.1.1098/src/findfile.c 2019-03-09 12:32:50.673562149 +0100 +--- src/findfile.c 2019-03-31 19:09:15.586959263 +0200 +*************** +*** 2605,2607 **** +--- 2605,2819 ---- + } + + #endif // FEAT_SEARCHPATH ++ ++ /* ++ * 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) ++ { ++ #ifndef AMIGA // Amiga doesn't have "..", it uses "/" ++ 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. ++ # ifdef VMS ++ // VMS allows device:[path] - don't strip the [ in directory ++ if ((*p == '[' || *p == '<') && p > filename && p[-1] == ':') ++ { ++ // :[ or :< composition: vms directory component ++ ++components; ++ p = getnextcomp(p + 1); ++ } ++ // allow remote calls as host"user passwd"::device:[path] ++ else if (p[0] == ':' && p[1] == ':' && p > filename && p[-1] == '"' ) ++ { ++ // ":: composition: vms host/passwd component ++ ++components; ++ p = getnextcomp(p + 2); ++ } ++ else ++ # endif ++ 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; ++ stat_T 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) ++ { ++ stat_T 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); ++ #endif // !AMIGA ++ } +*** ../vim-8.1.1098/src/proto/findfile.pro 2019-02-13 22:45:21.512636158 +0100 +--- src/proto/findfile.pro 2019-03-31 19:09:20.870916772 +0200 +*************** +*** 15,18 **** +--- 15,19 ---- + int vim_ispathlistsep(int c); + void uniquefy_paths(garray_T *gap, char_u *pattern); + int expand_in_path(garray_T *gap, char_u *pattern, int flags); ++ void simplify_filename(char_u *filename); + /* vim: set ft=c : */ +*** ../vim-8.1.1098/src/version.c 2019-03-31 15:31:54.592053004 +0200 +--- src/version.c 2019-03-31 19:39:26.094371299 +0200 +*************** +*** 773,774 **** +--- 773,776 ---- + { /* Add new patch number below this line */ ++ /**/ ++ 1099, + /**/ + +-- +hundred-and-one symptoms of being an internet addict: +175. You send yourself e-mail before you go to bed to remind you + what to do when you wake up. + + /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ +/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ +\\\ an exciting new programming language -- http://www.Zimbu.org /// + \\\ help me help AIDS victims -- http://ICCF-Holland.org /// |