summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2011-10-12 19:53:52 +0200
committerBram Moolenaar <Bram@vim.org>2011-10-12 19:53:52 +0200
commite06461a82152710961eb7ca40041f3549fee57c9 (patch)
tree15d53357d54f7f517502255be359a3a4194711b1 /src
parent725a96219441136809d12202bba9c9c615efe68f (diff)
downloadvim-e06461a82152710961eb7ca40041f3549fee57c9.zip
updated for version 7.3.336
Problem: When a tags file specifies an encoding different from 'enc' it may hang and using a pattern doesn't work. Solution: Convert the whole line. Continue reading the header after the SORT tag. Add test83. (Yukihiro Nakadaira)
Diffstat (limited to 'src')
-rw-r--r--src/tag.c249
-rw-r--r--src/testdir/Make_amiga.mak3
-rw-r--r--src/testdir/Make_dos.mak2
-rw-r--r--src/testdir/Make_ming.mak2
-rw-r--r--src/testdir/Make_os2.mak2
-rw-r--r--src/testdir/Make_vms.mms2
-rw-r--r--src/testdir/Makefile4
-rw-r--r--src/testdir/test83-tags22
-rw-r--r--src/testdir/test83-tags3102
-rw-r--r--src/testdir/test83.in76
-rw-r--r--src/testdir/test83.ok4
-rw-r--r--src/version.c2
12 files changed, 309 insertions, 141 deletions
diff --git a/src/tag.c b/src/tag.c
index b38bff099..f06b02360 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -1277,6 +1277,7 @@ find_tags(pat, num_matches, matchesp, flags, mincount, buf_ffname)
{
FILE *fp;
char_u *lbuf; /* line buffer */
+ int lbuf_size = LSIZE; /* length of lbuf */
char_u *tag_fname; /* name of tag file */
tagname_T tn; /* info for get_tagfname() */
int first_file; /* trying first tag file */
@@ -1291,6 +1292,7 @@ find_tags(pat, num_matches, matchesp, flags, mincount, buf_ffname)
char_u *s;
int i;
#ifdef FEAT_TAG_BINS
+ int tag_file_sorted = NUL; /* !_TAG_FILE_SORTED value */
struct tag_search_info /* Binary search file offsets */
{
off_t low_offset; /* offset for first char of first line that
@@ -1360,13 +1362,8 @@ find_tags(pat, num_matches, matchesp, flags, mincount, buf_ffname)
char_u *saved_pat = NULL; /* copy of pat[] */
#endif
- /* Use two sets of variables for the pattern: "orgpat" holds the values
- * for the original pattern and "convpat" converted from 'encoding' to
- * encoding of the tags file. "pats" point to either one of these. */
- pat_T *pats;
pat_T orgpat; /* holds unconverted pattern info */
#ifdef FEAT_MBYTE
- pat_T convpat; /* holds converted pattern info */
vimconv_T vimconv;
#endif
@@ -1390,7 +1387,6 @@ find_tags(pat, num_matches, matchesp, flags, mincount, buf_ffname)
help_save = curbuf->b_help;
orgpat.pat = pat;
- pats = &orgpat;
#ifdef FEAT_MBYTE
vimconv.vc_type = CONV_NONE;
#endif
@@ -1398,7 +1394,7 @@ find_tags(pat, num_matches, matchesp, flags, mincount, buf_ffname)
/*
* Allocate memory for the buffers that are used
*/
- lbuf = alloc(LSIZE);
+ lbuf = alloc(lbuf_size);
tag_fname = alloc(MAXPATHL + 1);
#ifdef FEAT_EMACS_TAGS
ebuf = alloc(LSIZE);
@@ -1424,30 +1420,30 @@ find_tags(pat, num_matches, matchesp, flags, mincount, buf_ffname)
if (help_only) /* want tags from help file */
curbuf->b_help = TRUE; /* will be restored later */
- pats->len = (int)STRLEN(pat);
+ orgpat.len = (int)STRLEN(pat);
#ifdef FEAT_MULTI_LANG
if (curbuf->b_help)
{
/* When "@ab" is specified use only the "ab" language, otherwise
* search all languages. */
- if (pats->len > 3 && pat[pats->len - 3] == '@'
- && ASCII_ISALPHA(pat[pats->len - 2])
- && ASCII_ISALPHA(pat[pats->len - 1]))
+ if (orgpat.len > 3 && pat[orgpat.len - 3] == '@'
+ && ASCII_ISALPHA(pat[orgpat.len - 2])
+ && ASCII_ISALPHA(pat[orgpat.len - 1]))
{
- saved_pat = vim_strnsave(pat, pats->len - 3);
+ saved_pat = vim_strnsave(pat, orgpat.len - 3);
if (saved_pat != NULL)
{
- help_lang_find = &pat[pats->len - 2];
- pats->pat = saved_pat;
- pats->len -= 3;
+ help_lang_find = &pat[orgpat.len - 2];
+ orgpat.pat = saved_pat;
+ orgpat.len -= 3;
}
}
}
#endif
- if (p_tl != 0 && pats->len > p_tl) /* adjust for 'taglength' */
- pats->len = p_tl;
+ if (p_tl != 0 && orgpat.len > p_tl) /* adjust for 'taglength' */
+ orgpat.len = p_tl;
- prepare_pats(pats, has_re);
+ prepare_pats(&orgpat, has_re);
#ifdef FEAT_TAG_BINS
/* This is only to avoid a compiler warning for using search_info
@@ -1466,13 +1462,13 @@ find_tags(pat, num_matches, matchesp, flags, mincount, buf_ffname)
* Only ignore case when TAG_NOIC not used or 'ignorecase' set.
*/
#ifdef FEAT_TAG_BINS
- pats->regmatch.rm_ic = ((p_ic || !noic)
- && (findall || pats->headlen == 0 || !p_tbs));
+ orgpat.regmatch.rm_ic = ((p_ic || !noic)
+ && (findall || orgpat.headlen == 0 || !p_tbs));
for (round = 1; round <= 2; ++round)
{
- linear = (pats->headlen == 0 || !p_tbs || round == 2);
+ linear = (orgpat.headlen == 0 || !p_tbs || round == 2);
#else
- pats->regmatch.rm_ic = (p_ic || !noic);
+ orgpat.regmatch.rm_ic = (p_ic || !noic);
#endif
/*
@@ -1701,6 +1697,36 @@ find_tags(pat, num_matches, matchesp, flags, mincount, buf_ffname)
}
line_read_in:
+#ifdef FEAT_MBYTE
+ if (vimconv.vc_type != CONV_NONE)
+ {
+ char_u *conv_line;
+ int len;
+
+ /* Convert every line. Converting the pattern from 'enc' to
+ * the tags file encoding doesn't work, because characters are
+ * not recognized. */
+ conv_line = string_convert(&vimconv, lbuf, NULL);
+ if (conv_line != NULL)
+ {
+ /* Copy or swap lbuf and conv_line. */
+ len = (int)STRLEN(conv_line) + 1;
+ if (len > lbuf_size)
+ {
+ vim_free(lbuf);
+ lbuf = conv_line;
+ lbuf_size = len;
+ }
+ else
+ {
+ STRCPY(lbuf, conv_line);
+ vim_free(conv_line);
+ }
+ }
+ }
+#endif
+
+
#ifdef FEAT_EMACS_TAGS
/*
* Emacs tags line with CTRL-L: New file name on next line.
@@ -1770,6 +1796,33 @@ line_read_in:
*/
if (state == TS_START)
{
+ if (STRNCMP(lbuf, "!_TAG_", 6) <= 0)
+ {
+ /*
+ * Read header line.
+ */
+#ifdef FEAT_TAG_BINS
+ if (STRNCMP(lbuf, "!_TAG_FILE_SORTED\t", 18) == 0)
+ tag_file_sorted = lbuf[18];
+#endif
+#ifdef FEAT_MBYTE
+ if (STRNCMP(lbuf, "!_TAG_FILE_ENCODING\t", 20) == 0)
+ {
+ /* Prepare to convert every line from the specified
+ * encoding to 'encoding'. */
+ for (p = lbuf + 20; *p > ' ' && *p < 127; ++p)
+ ;
+ *p = NUL;
+ convert_setup(&vimconv, lbuf + 20, p_enc);
+ }
+#endif
+
+ /* Read the next line. Unrecognized flags are ignored. */
+ continue;
+ }
+
+ /* Headers ends. */
+
#ifdef FEAT_TAG_BINS
/*
* When there is no tag head, or ignoring case, need to do a
@@ -1786,24 +1839,20 @@ line_read_in:
if (linear)
# endif
state = TS_LINEAR;
- else if (STRNCMP(lbuf, "!_TAG_", 6) > 0)
+ else if (tag_file_sorted == NUL)
state = TS_BINARY;
- else if (STRNCMP(lbuf, "!_TAG_FILE_SORTED\t", 18) == 0)
- {
- /* Check sorted flag */
- if (lbuf[18] == '1')
- state = TS_BINARY;
- else if (lbuf[18] == '2')
- {
+ else if (tag_file_sorted == '1')
state = TS_BINARY;
- sortic = TRUE;
- pats->regmatch.rm_ic = (p_ic || !noic);
- }
- else
- state = TS_LINEAR;
+ else if (tag_file_sorted == '2')
+ {
+ state = TS_BINARY;
+ sortic = TRUE;
+ orgpat.regmatch.rm_ic = (p_ic || !noic);
}
+ else
+ state = TS_LINEAR;
- if (state == TS_BINARY && pats->regmatch.rm_ic && !sortic)
+ if (state == TS_BINARY && orgpat.regmatch.rm_ic && !sortic)
{
/* binary search won't work for ignoring case, use linear
* search. */
@@ -1843,40 +1892,12 @@ line_read_in:
#endif
}
-#ifdef FEAT_MBYTE
- if (lbuf[0] == '!' && pats == &orgpat
- && STRNCMP(lbuf, "!_TAG_FILE_ENCODING\t", 20) == 0)
- {
- /* Convert the search pattern from 'encoding' to the
- * specified encoding. */
- for (p = lbuf + 20; *p > ' ' && *p < 127; ++p)
- ;
- *p = NUL;
- convert_setup(&vimconv, p_enc, lbuf + 20);
- if (vimconv.vc_type != CONV_NONE)
- {
- convpat.pat = string_convert(&vimconv, pats->pat, NULL);
- if (convpat.pat != NULL)
- {
- pats = &convpat;
- pats->len = (int)STRLEN(pats->pat);
- prepare_pats(pats, has_re);
- pats->regmatch.rm_ic = orgpat.regmatch.rm_ic;
- }
- }
-
- /* Prepare for converting a match the other way around. */
- convert_setup(&vimconv, lbuf + 20, p_enc);
- continue;
- }
-#endif
-
/*
* Figure out where the different strings are in this line.
* For "normal" tags: Do a quick check if the tag matches.
* This speeds up tag searching a lot!
*/
- if (pats->headlen
+ if (orgpat.headlen
#ifdef FEAT_EMACS_TAGS
&& !is_etag
#endif
@@ -1933,9 +1954,9 @@ line_read_in:
cmplen = (int)(tagp.tagname_end - tagp.tagname);
if (p_tl != 0 && cmplen > p_tl) /* adjust for 'taglength' */
cmplen = p_tl;
- if (has_re && pats->headlen < cmplen)
- cmplen = pats->headlen;
- else if (state == TS_LINEAR && pats->headlen != cmplen)
+ if (has_re && orgpat.headlen < cmplen)
+ cmplen = orgpat.headlen;
+ else if (state == TS_LINEAR && orgpat.headlen != cmplen)
continue;
#ifdef FEAT_TAG_BINS
@@ -1954,10 +1975,10 @@ line_read_in:
* Compare the current tag with the searched tag.
*/
if (sortic)
- tagcmp = tag_strnicmp(tagp.tagname, pats->head,
+ tagcmp = tag_strnicmp(tagp.tagname, orgpat.head,
(size_t)cmplen);
else
- tagcmp = STRNCMP(tagp.tagname, pats->head, cmplen);
+ tagcmp = STRNCMP(tagp.tagname, orgpat.head, cmplen);
/*
* A match with a shorter tag means to search forward.
@@ -1965,9 +1986,9 @@ line_read_in:
*/
if (tagcmp == 0)
{
- if (cmplen < pats->headlen)
+ if (cmplen < orgpat.headlen)
tagcmp = -1;
- else if (cmplen > pats->headlen)
+ else if (cmplen > orgpat.headlen)
tagcmp = 1;
}
@@ -2011,7 +2032,7 @@ line_read_in:
}
else if (state == TS_SKIP_BACK)
{
- if (MB_STRNICMP(tagp.tagname, pats->head, cmplen) != 0)
+ if (MB_STRNICMP(tagp.tagname, orgpat.head, cmplen) != 0)
state = TS_STEP_FORWARD;
else
/* Have to skip back more. Restore the curr_offset
@@ -2021,7 +2042,7 @@ line_read_in:
}
else if (state == TS_STEP_FORWARD)
{
- if (MB_STRNICMP(tagp.tagname, pats->head, cmplen) != 0)
+ if (MB_STRNICMP(tagp.tagname, orgpat.head, cmplen) != 0)
{
if ((off_t)ftell(fp) > search_info.match_offset)
break; /* past last match */
@@ -2032,7 +2053,7 @@ line_read_in:
else
#endif
/* skip this match if it can't match */
- if (MB_STRNICMP(tagp.tagname, pats->head, cmplen) != 0)
+ if (MB_STRNICMP(tagp.tagname, orgpat.head, cmplen) != 0)
continue;
/*
@@ -2083,41 +2104,41 @@ line_read_in:
if (p_tl != 0 && cmplen > p_tl) /* adjust for 'taglength' */
cmplen = p_tl;
/* if tag length does not match, don't try comparing */
- if (pats->len != cmplen)
+ if (orgpat.len != cmplen)
match = FALSE;
else
{
- if (pats->regmatch.rm_ic)
+ if (orgpat.regmatch.rm_ic)
{
- match = (MB_STRNICMP(tagp.tagname, pats->pat, cmplen) == 0);
+ match = (MB_STRNICMP(tagp.tagname, orgpat.pat, cmplen) == 0);
if (match)
- match_no_ic = (STRNCMP(tagp.tagname, pats->pat,
+ match_no_ic = (STRNCMP(tagp.tagname, orgpat.pat,
cmplen) == 0);
}
else
- match = (STRNCMP(tagp.tagname, pats->pat, cmplen) == 0);
+ match = (STRNCMP(tagp.tagname, orgpat.pat, cmplen) == 0);
}
/*
* Has a regexp: Also find tags matching regexp.
*/
match_re = FALSE;
- if (!match && pats->regmatch.regprog != NULL)
+ if (!match && orgpat.regmatch.regprog != NULL)
{
int cc;
cc = *tagp.tagname_end;
*tagp.tagname_end = NUL;
- match = vim_regexec(&pats->regmatch, tagp.tagname, (colnr_T)0);
+ match = vim_regexec(&orgpat.regmatch, tagp.tagname, (colnr_T)0);
if (match)
{
- matchoff = (int)(pats->regmatch.startp[0] - tagp.tagname);
- if (pats->regmatch.rm_ic)
+ matchoff = (int)(orgpat.regmatch.startp[0] - tagp.tagname);
+ if (orgpat.regmatch.rm_ic)
{
- pats->regmatch.rm_ic = FALSE;
- match_no_ic = vim_regexec(&pats->regmatch, tagp.tagname,
+ orgpat.regmatch.rm_ic = FALSE;
+ match_no_ic = vim_regexec(&orgpat.regmatch, tagp.tagname,
(colnr_T)0);
- pats->regmatch.rm_ic = TRUE;
+ orgpat.regmatch.rm_ic = TRUE;
}
}
*tagp.tagname_end = cc;
@@ -2174,7 +2195,7 @@ line_read_in:
else
mtt = MT_GL_OTH;
}
- if (pats->regmatch.rm_ic && !match_no_ic)
+ if (orgpat.regmatch.rm_ic && !match_no_ic)
mtt += MT_IC_OFF;
if (match_re)
mtt += MT_RE_OFF;
@@ -2187,35 +2208,6 @@ line_read_in:
*/
if (ga_grow(&ga_match[mtt], 1) == OK)
{
-#ifdef FEAT_MBYTE
- char_u *conv_line = NULL;
- char_u *lbuf_line = lbuf;
-
- if (vimconv.vc_type != CONV_NONE)
- {
- /* Convert the tag line from the encoding of the tags
- * file to 'encoding'. Then parse the line again. */
- conv_line = string_convert(&vimconv, lbuf, NULL);
- if (conv_line != NULL)
- {
- if (parse_tag_line(conv_line,
-#ifdef FEAT_EMACS_TAGS
- is_etag,
-#endif
- &tagp) == OK)
- lbuf_line = conv_line;
- else
- /* doesn't work, go back to unconverted line. */
- (void)parse_tag_line(lbuf,
-#ifdef FEAT_EMACS_TAGS
- is_etag,
-#endif
- &tagp);
- }
- }
-#else
-# define lbuf_line lbuf
-#endif
if (help_only)
{
#ifdef FEAT_MULTI_LANG
@@ -2307,7 +2299,7 @@ line_read_in:
* without Emacs tags: <mtt><tag_fname><NUL><lbuf>
*/
len = (int)STRLEN(tag_fname)
- + (int)STRLEN(lbuf_line) + 3;
+ + (int)STRLEN(lbuf) + 3;
#ifdef FEAT_EMACS_TAGS
if (is_etag)
len += (int)STRLEN(ebuf) + 1;
@@ -2337,7 +2329,7 @@ line_read_in:
else
*s++ = NUL;
#endif
- STRCPY(s, lbuf_line);
+ STRCPY(s, lbuf);
}
}
@@ -2373,10 +2365,6 @@ line_read_in:
else
vim_free(mfp);
}
-#ifdef FEAT_MBYTE
- /* Note: this makes the values in "tagp" invalid! */
- vim_free(conv_line);
-#endif
}
else /* Out of memory! Just forget about the rest. */
{
@@ -2415,19 +2403,12 @@ line_read_in:
}
#endif
#ifdef FEAT_MBYTE
- if (pats == &convpat)
- {
- /* Go back from converted pattern to original pattern. */
- vim_free(pats->pat);
- vim_free(pats->regmatch.regprog);
- orgpat.regmatch.rm_ic = pats->regmatch.rm_ic;
- pats = &orgpat;
- }
if (vimconv.vc_type != CONV_NONE)
convert_setup(&vimconv, NULL, NULL);
#endif
#ifdef FEAT_TAG_BINS
+ tag_file_sorted = NUL;
if (sort_error)
{
EMSG2(_("E432: Tags file not sorted: %s"), tag_fname);
@@ -2461,13 +2442,13 @@ line_read_in:
#ifdef FEAT_TAG_BINS
/* stop searching when already did a linear search, or when TAG_NOIC
* used, and 'ignorecase' not set or already did case-ignore search */
- if (stop_searching || linear || (!p_ic && noic) || pats->regmatch.rm_ic)
+ if (stop_searching || linear || (!p_ic && noic) || orgpat.regmatch.rm_ic)
break;
# ifdef FEAT_CSCOPE
if (use_cscope)
break;
# endif
- pats->regmatch.rm_ic = TRUE; /* try another time while ignoring case */
+ orgpat.regmatch.rm_ic = TRUE; /* try another time while ignoring case */
}
#endif
@@ -2480,7 +2461,7 @@ line_read_in:
findtag_end:
vim_free(lbuf);
- vim_free(pats->regmatch.regprog);
+ vim_free(orgpat.regmatch.regprog);
vim_free(tag_fname);
#ifdef FEAT_EMACS_TAGS
vim_free(ebuf);
diff --git a/src/testdir/Make_amiga.mak b/src/testdir/Make_amiga.mak
index 55d13e48f..ba261ab6a 100644
--- a/src/testdir/Make_amiga.mak
+++ b/src/testdir/Make_amiga.mak
@@ -29,7 +29,7 @@ SCRIPTS = test1.out test3.out test4.out test5.out test6.out \
test66.out test67.out test68.out test69.out test70.out \
test71.out test72.out test73.out test74.out test75.out \
test76.out test77.out test78.out test79.out test80.out \
- test81.out test82.out
+ test81.out test82.out test83.out
.SUFFIXES: .in .out
@@ -131,3 +131,4 @@ test79.out: test79.in
test80.out: test80.in
test81.out: test81.in
test82.out: test82.in
+test83.out: test83.in
diff --git a/src/testdir/Make_dos.mak b/src/testdir/Make_dos.mak
index ba77d2268..9d0817354 100644
--- a/src/testdir/Make_dos.mak
+++ b/src/testdir/Make_dos.mak
@@ -29,7 +29,7 @@ SCRIPTS = test3.out test4.out test5.out test6.out test7.out \
test42.out test52.out test65.out test66.out test67.out \
test68.out test69.out test71.out test72.out test73.out \
test74.out test75.out test76.out test77.out test78.out \
- test79.out test80.out test81.out test82.out
+ test79.out test80.out test81.out test82.out test83.out
SCRIPTS32 = test50.out test70.out
diff --git a/src/testdir/Make_ming.mak b/src/testdir/Make_ming.mak
index d844c3926..5f9dbdd0d 100644
--- a/src/testdir/Make_ming.mak
+++ b/src/testdir/Make_ming.mak
@@ -49,7 +49,7 @@ SCRIPTS = test3.out test4.out test5.out test6.out test7.out \
test42.out test52.out test65.out test66.out test67.out \
test68.out test69.out test71.out test72.out test73.out \
test74.out test75.out test76.out test77.out test78.out \
- test79.out test80.out test81.out test82.out
+ test79.out test80.out test81.out test82.out test83.out
SCRIPTS32 = test50.out test70.out
diff --git a/src/testdir/Make_os2.mak b/src/testdir/Make_os2.mak
index bd11d7f26..363bede3c 100644
--- a/src/testdir/Make_os2.mak
+++ b/src/testdir/Make_os2.mak
@@ -29,7 +29,7 @@ SCRIPTS = test1.out test3.out test4.out test5.out test6.out \
test66.out test67.out test68.out test69.out test70.out \
test71.out test72.out test73.out test74.out test75.out \
test76.out test77.out test78.out test79.out test80.out \
- test81.out test82.out
+ test81.out test82.out test83.out
.SUFFIXES: .in .out
diff --git a/src/testdir/Make_vms.mms b/src/testdir/Make_vms.mms
index fe062c30a..4e6ae6370 100644
--- a/src/testdir/Make_vms.mms
+++ b/src/testdir/Make_vms.mms
@@ -76,7 +76,7 @@ SCRIPT = test1.out test2.out test3.out test4.out test5.out \
test66.out test67.out test68.out test69.out \
test71.out test72.out test74.out test75.out test76.out \
test77.out test78.out test79.out test80.out test81.out \
- test82.out
+ test82.out test83.out
# Known problems:
# Test 30: a problem around mac format - unknown reason
diff --git a/src/testdir/Makefile b/src/testdir/Makefile
index c776c15f9..a1cc22db7 100644
--- a/src/testdir/Makefile
+++ b/src/testdir/Makefile
@@ -26,7 +26,7 @@ SCRIPTS = test1.out test2.out test3.out test4.out test5.out test6.out \
test64.out test65.out test66.out test67.out test68.out \
test69.out test70.out test71.out test72.out test73.out \
test74.out test75.out test76.out test77.out test78.out \
- test79.out test80.out test81.out test82.out
+ test79.out test80.out test81.out test82.out test83.out
SCRIPTS_GUI = test16.out
@@ -72,7 +72,7 @@ test1.out: test1.in
fi \
else echo $* NO OUTPUT >>test.log; \
fi"
- -rm -rf X* test.ok viminfo
+# -rm -rf X* test.ok viminfo
test49.out: test49.vim
diff --git a/src/testdir/test83-tags2 b/src/testdir/test83-tags2
new file mode 100644
index 000000000..7f9f21b0e
--- /dev/null
+++ b/src/testdir/test83-tags2
@@ -0,0 +1,2 @@
+!_TAG_FILE_ENCODING cp932 //
+‚`‚a‚b Xtags2.txt /‚`‚a‚b
diff --git a/src/testdir/test83-tags3 b/src/testdir/test83-tags3
new file mode 100644
index 000000000..0cb659156
--- /dev/null
+++ b/src/testdir/test83-tags3
@@ -0,0 +1,102 @@
+!_TAG_FILE_SORTED 1 //
+!_TAG_FILE_ENCODING cp932 //
+abc1 Xtags3.txt /‚`‚a‚b
+abc2 Xtags3.txt /‚`‚a‚b
+abc3 Xtags3.txt /‚`‚a‚b
+abc4 Xtags3.txt /‚`‚a‚b
+abc5 Xtags3.txt /‚`‚a‚b
+abc6 Xtags3.txt /‚`‚a‚b
+abc7 Xtags3.txt /‚`‚a‚b
+abc8 Xtags3.txt /‚`‚a‚b
+abc9 Xtags3.txt /‚`‚a‚b
+abc10 Xtags3.txt /‚`‚a‚b
+abc11 Xtags3.txt /‚`‚a‚b
+abc12 Xtags3.txt /‚`‚a‚b
+abc13 Xtags3.txt /‚`‚a‚b
+abc14 Xtags3.txt /‚`‚a‚b
+abc15 Xtags3.txt /‚`‚a‚b
+abc16 Xtags3.txt /‚`‚a‚b
+abc17 Xtags3.txt /‚`‚a‚b
+abc18 Xtags3.txt /‚`‚a‚b
+abc19 Xtags3.txt /‚`‚a‚b
+abc20 Xtags3.txt /‚`‚a‚b
+abc21 Xtags3.txt /‚`‚a‚b
+abc22 Xtags3.txt /‚`‚a‚b
+abc23 Xtags3.txt /‚`‚a‚b
+abc24 Xtags3.txt /‚`‚a‚b
+abc25 Xtags3.txt /‚`‚a‚b
+abc26 Xtags3.txt /‚`‚a‚b
+abc27 Xtags3.txt /‚`‚a‚b
+abc28 Xtags3.txt /‚`‚a‚b
+abc29 Xtags3.txt /‚`‚a‚b
+abc30 Xtags3.txt /‚`‚a‚b
+abc31 Xtags3.txt /‚`‚a‚b
+abc32 Xtags3.txt /‚`‚a‚b
+abc33 Xtags3.txt /‚`‚a‚b
+abc34 Xtags3.txt /‚`‚a‚b
+abc35 Xtags3.txt /‚`‚a‚b
+abc36 Xtags3.txt /‚`‚a‚b
+abc37 Xtags3.txt /‚`‚a‚b
+abc38 Xtags3.txt /‚`‚a‚b
+abc39 Xtags3.txt /‚`‚a‚b
+abc40 Xtags3.txt /‚`‚a‚b
+abc41 Xtags3.txt /‚`‚a‚b
+abc42 Xtags3.txt /‚`‚a‚b
+abc43 Xtags3.txt /‚`‚a‚b
+abc44 Xtags3.txt /‚`‚a‚b
+abc45 Xtags3.txt /‚`‚a‚b
+abc46 Xtags3.txt /‚`‚a‚b
+abc47 Xtags3.txt /‚`‚a‚b
+abc48 Xtags3.txt /‚`‚a‚b
+abc49 Xtags3.txt /‚`‚a‚b
+abc50 Xtags3.txt /‚`‚a‚b
+abc51 Xtags3.txt /‚`‚a‚b
+abc52 Xtags3.txt /‚`‚a‚b
+abc53 Xtags3.txt /‚`‚a‚b
+abc54 Xtags3.txt /‚`‚a‚b
+abc55 Xtags3.txt /‚`‚a‚b
+abc56 Xtags3.txt /‚`‚a‚b
+abc57 Xtags3.txt /‚`‚a‚b
+abc58 Xtags3.txt /‚`‚a‚b
+abc59 Xtags3.txt /‚`‚a‚b
+abc60 Xtags3.txt /‚`‚a‚b
+abc61 Xtags3.txt /‚`‚a‚b
+abc62 Xtags3.txt /‚`‚a‚b
+abc63 Xtags3.txt /‚`‚a‚b
+abc64 Xtags3.txt /‚`‚a‚b
+abc65 Xtags3.txt /‚`‚a‚b
+abc66 Xtags3.txt /‚`‚a‚b
+abc67 Xtags3.txt /‚`‚a‚b
+abc68 Xtags3.txt /‚`‚a‚b
+abc69 Xtags3.txt /‚`‚a‚b
+abc70 Xtags3.txt /‚`‚a‚b
+abc71 Xtags3.txt /‚`‚a‚b
+abc72 Xtags3.txt /‚`‚a‚b
+abc73 Xtags3.txt /‚`‚a‚b
+abc74 Xtags3.txt /‚`‚a‚b
+abc75 Xtags3.txt /‚`‚a‚b
+abc76 Xtags3.txt /‚`‚a‚b
+abc77 Xtags3.txt /‚`‚a‚b
+abc78 Xtags3.txt /‚`‚a‚b
+abc79 Xtags3.txt /‚`‚a‚b
+abc80 Xtags3.txt /‚`‚a‚b
+abc81 Xtags3.txt /‚`‚a‚b
+abc82 Xtags3.txt /‚`‚a‚b
+abc83 Xtags3.txt /‚`‚a‚b
+abc84 Xtags3.txt /‚`‚a‚b
+abc85 Xtags3.txt /‚`‚a‚b
+abc86 Xtags3.txt /‚`‚a‚b
+abc87 Xtags3.txt /‚`‚a‚b
+abc88 Xtags3.txt /‚`‚a‚b
+abc89 Xtags3.txt /‚`‚a‚b
+abc90 Xtags3.txt /‚`‚a‚b
+abc91 Xtags3.txt /‚`‚a‚b
+abc92 Xtags3.txt /‚`‚a‚b
+abc93 Xtags3.txt /‚`‚a‚b
+abc94 Xtags3.txt /‚`‚a‚b
+abc95 Xtags3.txt /‚`‚a‚b
+abc96 Xtags3.txt /‚`‚a‚b
+abc97 Xtags3.txt /‚`‚a‚b
+abc98 Xtags3.txt /‚`‚a‚b
+abc99 Xtags3.txt /‚`‚a‚b
+abc100 Xtags3.txt /‚`‚a‚b
diff --git a/src/testdir/test83.in b/src/testdir/test83.in
new file mode 100644
index 000000000..300ddf1c7
--- /dev/null
+++ b/src/testdir/test83.in
@@ -0,0 +1,76 @@
+Tests for tag search with !_TAG_FILE_ENCODING.
+
+STARTTEST
+:so mbyte.vim
+:if !has('iconv')
+: e! test.ok
+: w! test.out
+: qa!
+:endif
+:set enc=utf8
+
+:/^text for tags1$/,/^text for tags1$/+1w! Xtags1.txt
+:/^text for tags2$/,/^text for tags2$/+1w! Xtags2.txt
+:/^text for tags3$/,/^text for tags3$/+1w! Xtags3.txt
+:/^tags1$/+1,/^tags1-end$/-1w! Xtags1
+
+ggdG
+
+:call setline('.', 'Results of test83')
+
+:" case1:
+:new
+:set tags=Xtags1
+:let v:errmsg = ''
+:tag abcdefghijklmnopqrs
+:if v:errmsg =~ 'E426:' || getline('.') != 'abcdefghijklmnopqrs'
+: close
+: put ='case1: failed'
+:else
+: close
+: put ='case1: ok'
+:endif
+
+:" case2:
+:new
+:set tags=test83-tags2
+:let v:errmsg = ''
+:tag /.BC
+:if v:errmsg =~ 'E426:' || getline('.') != 'ABC'
+: close
+: put ='case2: failed'
+:else
+: close
+: put ='case2: ok'
+:endif
+
+:" case3:
+:new
+:set tags=test83-tags3
+:let v:errmsg = ''
+:tag abc50
+:if v:errmsg =~ 'E426:' || getline('.') != 'ABC'
+: close
+: put ='case3: failed'
+:else
+: close
+: put ='case3: ok'
+:endif
+:close
+
+:wq! test.out
+ENDTEST
+
+text for tags1
+abcdefghijklmnopqrs
+
+text for tags2
+ABC
+
+text for tags3
+ABC
+
+tags1
+!_TAG_FILE_ENCODING utf-8 //
+abcdefghijklmnopqrs Xtags1.txt /abcdefghijklmnopqrs
+tags1-end
diff --git a/src/testdir/test83.ok b/src/testdir/test83.ok
new file mode 100644
index 000000000..61a1a04a1
--- /dev/null
+++ b/src/testdir/test83.ok
@@ -0,0 +1,4 @@
+Results of test83
+case1: ok
+case2: ok
+case3: ok
diff --git a/src/version.c b/src/version.c
index 15d461f4b..48d2d3967 100644
--- a/src/version.c
+++ b/src/version.c
@@ -710,6 +710,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 336,
+/**/
335,
/**/
334,