Mercurial > vim
comparison src/tag.c @ 3131:52526aec4afb v7.3.336
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)
author | Bram Moolenaar <bram@vim.org> |
---|---|
date | Wed, 12 Oct 2011 19:53:52 +0200 |
parents | 25672ad7f377 |
children | 436b42f3cba1 |
comparison
equal
deleted
inserted
replaced
3130:91b43bbb3701 | 3131:52526aec4afb |
---|---|
1275 other: minimal number of matches */ | 1275 other: minimal number of matches */ |
1276 char_u *buf_ffname; /* name of buffer for priority */ | 1276 char_u *buf_ffname; /* name of buffer for priority */ |
1277 { | 1277 { |
1278 FILE *fp; | 1278 FILE *fp; |
1279 char_u *lbuf; /* line buffer */ | 1279 char_u *lbuf; /* line buffer */ |
1280 int lbuf_size = LSIZE; /* length of lbuf */ | |
1280 char_u *tag_fname; /* name of tag file */ | 1281 char_u *tag_fname; /* name of tag file */ |
1281 tagname_T tn; /* info for get_tagfname() */ | 1282 tagname_T tn; /* info for get_tagfname() */ |
1282 int first_file; /* trying first tag file */ | 1283 int first_file; /* trying first tag file */ |
1283 tagptrs_T tagp; | 1284 tagptrs_T tagp; |
1284 int did_open = FALSE; /* did open a tag file */ | 1285 int did_open = FALSE; /* did open a tag file */ |
1289 int eof = FALSE; /* found end-of-file */ | 1290 int eof = FALSE; /* found end-of-file */ |
1290 char_u *p; | 1291 char_u *p; |
1291 char_u *s; | 1292 char_u *s; |
1292 int i; | 1293 int i; |
1293 #ifdef FEAT_TAG_BINS | 1294 #ifdef FEAT_TAG_BINS |
1295 int tag_file_sorted = NUL; /* !_TAG_FILE_SORTED value */ | |
1294 struct tag_search_info /* Binary search file offsets */ | 1296 struct tag_search_info /* Binary search file offsets */ |
1295 { | 1297 { |
1296 off_t low_offset; /* offset for first char of first line that | 1298 off_t low_offset; /* offset for first char of first line that |
1297 could match */ | 1299 could match */ |
1298 off_t high_offset; /* offset of char after last line that could | 1300 off_t high_offset; /* offset of char after last line that could |
1358 char_u *help_lang_find = NULL; /* lang to be found */ | 1360 char_u *help_lang_find = NULL; /* lang to be found */ |
1359 char_u help_lang[3]; /* lang of current tags file */ | 1361 char_u help_lang[3]; /* lang of current tags file */ |
1360 char_u *saved_pat = NULL; /* copy of pat[] */ | 1362 char_u *saved_pat = NULL; /* copy of pat[] */ |
1361 #endif | 1363 #endif |
1362 | 1364 |
1363 /* Use two sets of variables for the pattern: "orgpat" holds the values | |
1364 * for the original pattern and "convpat" converted from 'encoding' to | |
1365 * encoding of the tags file. "pats" point to either one of these. */ | |
1366 pat_T *pats; | |
1367 pat_T orgpat; /* holds unconverted pattern info */ | 1365 pat_T orgpat; /* holds unconverted pattern info */ |
1368 #ifdef FEAT_MBYTE | 1366 #ifdef FEAT_MBYTE |
1369 pat_T convpat; /* holds converted pattern info */ | |
1370 vimconv_T vimconv; | 1367 vimconv_T vimconv; |
1371 #endif | 1368 #endif |
1372 | 1369 |
1373 #ifdef FEAT_TAG_BINS | 1370 #ifdef FEAT_TAG_BINS |
1374 int findall = (mincount == MAXCOL || mincount == TAG_MANY); | 1371 int findall = (mincount == MAXCOL || mincount == TAG_MANY); |
1388 #endif | 1385 #endif |
1389 int verbose = (flags & TAG_VERBOSE); | 1386 int verbose = (flags & TAG_VERBOSE); |
1390 | 1387 |
1391 help_save = curbuf->b_help; | 1388 help_save = curbuf->b_help; |
1392 orgpat.pat = pat; | 1389 orgpat.pat = pat; |
1393 pats = &orgpat; | |
1394 #ifdef FEAT_MBYTE | 1390 #ifdef FEAT_MBYTE |
1395 vimconv.vc_type = CONV_NONE; | 1391 vimconv.vc_type = CONV_NONE; |
1396 #endif | 1392 #endif |
1397 | 1393 |
1398 /* | 1394 /* |
1399 * Allocate memory for the buffers that are used | 1395 * Allocate memory for the buffers that are used |
1400 */ | 1396 */ |
1401 lbuf = alloc(LSIZE); | 1397 lbuf = alloc(lbuf_size); |
1402 tag_fname = alloc(MAXPATHL + 1); | 1398 tag_fname = alloc(MAXPATHL + 1); |
1403 #ifdef FEAT_EMACS_TAGS | 1399 #ifdef FEAT_EMACS_TAGS |
1404 ebuf = alloc(LSIZE); | 1400 ebuf = alloc(LSIZE); |
1405 #endif | 1401 #endif |
1406 for (mtt = 0; mtt < MT_COUNT; ++mtt) | 1402 for (mtt = 0; mtt < MT_COUNT; ++mtt) |
1422 * Initialize a few variables | 1418 * Initialize a few variables |
1423 */ | 1419 */ |
1424 if (help_only) /* want tags from help file */ | 1420 if (help_only) /* want tags from help file */ |
1425 curbuf->b_help = TRUE; /* will be restored later */ | 1421 curbuf->b_help = TRUE; /* will be restored later */ |
1426 | 1422 |
1427 pats->len = (int)STRLEN(pat); | 1423 orgpat.len = (int)STRLEN(pat); |
1428 #ifdef FEAT_MULTI_LANG | 1424 #ifdef FEAT_MULTI_LANG |
1429 if (curbuf->b_help) | 1425 if (curbuf->b_help) |
1430 { | 1426 { |
1431 /* When "@ab" is specified use only the "ab" language, otherwise | 1427 /* When "@ab" is specified use only the "ab" language, otherwise |
1432 * search all languages. */ | 1428 * search all languages. */ |
1433 if (pats->len > 3 && pat[pats->len - 3] == '@' | 1429 if (orgpat.len > 3 && pat[orgpat.len - 3] == '@' |
1434 && ASCII_ISALPHA(pat[pats->len - 2]) | 1430 && ASCII_ISALPHA(pat[orgpat.len - 2]) |
1435 && ASCII_ISALPHA(pat[pats->len - 1])) | 1431 && ASCII_ISALPHA(pat[orgpat.len - 1])) |
1436 { | 1432 { |
1437 saved_pat = vim_strnsave(pat, pats->len - 3); | 1433 saved_pat = vim_strnsave(pat, orgpat.len - 3); |
1438 if (saved_pat != NULL) | 1434 if (saved_pat != NULL) |
1439 { | 1435 { |
1440 help_lang_find = &pat[pats->len - 2]; | 1436 help_lang_find = &pat[orgpat.len - 2]; |
1441 pats->pat = saved_pat; | 1437 orgpat.pat = saved_pat; |
1442 pats->len -= 3; | 1438 orgpat.len -= 3; |
1443 } | 1439 } |
1444 } | 1440 } |
1445 } | 1441 } |
1446 #endif | 1442 #endif |
1447 if (p_tl != 0 && pats->len > p_tl) /* adjust for 'taglength' */ | 1443 if (p_tl != 0 && orgpat.len > p_tl) /* adjust for 'taglength' */ |
1448 pats->len = p_tl; | 1444 orgpat.len = p_tl; |
1449 | 1445 |
1450 prepare_pats(pats, has_re); | 1446 prepare_pats(&orgpat, has_re); |
1451 | 1447 |
1452 #ifdef FEAT_TAG_BINS | 1448 #ifdef FEAT_TAG_BINS |
1453 /* This is only to avoid a compiler warning for using search_info | 1449 /* This is only to avoid a compiler warning for using search_info |
1454 * uninitialised. */ | 1450 * uninitialised. */ |
1455 vim_memset(&search_info, 0, (size_t)1); | 1451 vim_memset(&search_info, 0, (size_t)1); |
1464 * tags files twice. | 1460 * tags files twice. |
1465 * When the tag file is case-fold sorted, it is either one or the other. | 1461 * When the tag file is case-fold sorted, it is either one or the other. |
1466 * Only ignore case when TAG_NOIC not used or 'ignorecase' set. | 1462 * Only ignore case when TAG_NOIC not used or 'ignorecase' set. |
1467 */ | 1463 */ |
1468 #ifdef FEAT_TAG_BINS | 1464 #ifdef FEAT_TAG_BINS |
1469 pats->regmatch.rm_ic = ((p_ic || !noic) | 1465 orgpat.regmatch.rm_ic = ((p_ic || !noic) |
1470 && (findall || pats->headlen == 0 || !p_tbs)); | 1466 && (findall || orgpat.headlen == 0 || !p_tbs)); |
1471 for (round = 1; round <= 2; ++round) | 1467 for (round = 1; round <= 2; ++round) |
1472 { | 1468 { |
1473 linear = (pats->headlen == 0 || !p_tbs || round == 2); | 1469 linear = (orgpat.headlen == 0 || !p_tbs || round == 2); |
1474 #else | 1470 #else |
1475 pats->regmatch.rm_ic = (p_ic || !noic); | 1471 orgpat.regmatch.rm_ic = (p_ic || !noic); |
1476 #endif | 1472 #endif |
1477 | 1473 |
1478 /* | 1474 /* |
1479 * Try tag file names from tags option one by one. | 1475 * Try tag file names from tags option one by one. |
1480 */ | 1476 */ |
1698 #endif | 1694 #endif |
1699 break; /* end of file */ | 1695 break; /* end of file */ |
1700 } | 1696 } |
1701 } | 1697 } |
1702 line_read_in: | 1698 line_read_in: |
1699 | |
1700 #ifdef FEAT_MBYTE | |
1701 if (vimconv.vc_type != CONV_NONE) | |
1702 { | |
1703 char_u *conv_line; | |
1704 int len; | |
1705 | |
1706 /* Convert every line. Converting the pattern from 'enc' to | |
1707 * the tags file encoding doesn't work, because characters are | |
1708 * not recognized. */ | |
1709 conv_line = string_convert(&vimconv, lbuf, NULL); | |
1710 if (conv_line != NULL) | |
1711 { | |
1712 /* Copy or swap lbuf and conv_line. */ | |
1713 len = (int)STRLEN(conv_line) + 1; | |
1714 if (len > lbuf_size) | |
1715 { | |
1716 vim_free(lbuf); | |
1717 lbuf = conv_line; | |
1718 lbuf_size = len; | |
1719 } | |
1720 else | |
1721 { | |
1722 STRCPY(lbuf, conv_line); | |
1723 vim_free(conv_line); | |
1724 } | |
1725 } | |
1726 } | |
1727 #endif | |
1728 | |
1703 | 1729 |
1704 #ifdef FEAT_EMACS_TAGS | 1730 #ifdef FEAT_EMACS_TAGS |
1705 /* | 1731 /* |
1706 * Emacs tags line with CTRL-L: New file name on next line. | 1732 * Emacs tags line with CTRL-L: New file name on next line. |
1707 * The file name is followed by a ','. | 1733 * The file name is followed by a ','. |
1768 * When still at the start of the file, check for Emacs tags file | 1794 * When still at the start of the file, check for Emacs tags file |
1769 * format, and for "not sorted" flag. | 1795 * format, and for "not sorted" flag. |
1770 */ | 1796 */ |
1771 if (state == TS_START) | 1797 if (state == TS_START) |
1772 { | 1798 { |
1799 if (STRNCMP(lbuf, "!_TAG_", 6) <= 0) | |
1800 { | |
1801 /* | |
1802 * Read header line. | |
1803 */ | |
1804 #ifdef FEAT_TAG_BINS | |
1805 if (STRNCMP(lbuf, "!_TAG_FILE_SORTED\t", 18) == 0) | |
1806 tag_file_sorted = lbuf[18]; | |
1807 #endif | |
1808 #ifdef FEAT_MBYTE | |
1809 if (STRNCMP(lbuf, "!_TAG_FILE_ENCODING\t", 20) == 0) | |
1810 { | |
1811 /* Prepare to convert every line from the specified | |
1812 * encoding to 'encoding'. */ | |
1813 for (p = lbuf + 20; *p > ' ' && *p < 127; ++p) | |
1814 ; | |
1815 *p = NUL; | |
1816 convert_setup(&vimconv, lbuf + 20, p_enc); | |
1817 } | |
1818 #endif | |
1819 | |
1820 /* Read the next line. Unrecognized flags are ignored. */ | |
1821 continue; | |
1822 } | |
1823 | |
1824 /* Headers ends. */ | |
1825 | |
1773 #ifdef FEAT_TAG_BINS | 1826 #ifdef FEAT_TAG_BINS |
1774 /* | 1827 /* |
1775 * When there is no tag head, or ignoring case, need to do a | 1828 * When there is no tag head, or ignoring case, need to do a |
1776 * linear search. | 1829 * linear search. |
1777 * When no "!_TAG_" is found, default to binary search. If | 1830 * When no "!_TAG_" is found, default to binary search. If |
1784 if (linear || use_cscope) | 1837 if (linear || use_cscope) |
1785 # else | 1838 # else |
1786 if (linear) | 1839 if (linear) |
1787 # endif | 1840 # endif |
1788 state = TS_LINEAR; | 1841 state = TS_LINEAR; |
1789 else if (STRNCMP(lbuf, "!_TAG_", 6) > 0) | 1842 else if (tag_file_sorted == NUL) |
1790 state = TS_BINARY; | 1843 state = TS_BINARY; |
1791 else if (STRNCMP(lbuf, "!_TAG_FILE_SORTED\t", 18) == 0) | 1844 else if (tag_file_sorted == '1') |
1792 { | |
1793 /* Check sorted flag */ | |
1794 if (lbuf[18] == '1') | |
1795 state = TS_BINARY; | 1845 state = TS_BINARY; |
1796 else if (lbuf[18] == '2') | 1846 else if (tag_file_sorted == '2') |
1797 { | 1847 { |
1798 state = TS_BINARY; | 1848 state = TS_BINARY; |
1799 sortic = TRUE; | 1849 sortic = TRUE; |
1800 pats->regmatch.rm_ic = (p_ic || !noic); | 1850 orgpat.regmatch.rm_ic = (p_ic || !noic); |
1801 } | 1851 } |
1802 else | 1852 else |
1803 state = TS_LINEAR; | 1853 state = TS_LINEAR; |
1804 } | 1854 |
1805 | 1855 if (state == TS_BINARY && orgpat.regmatch.rm_ic && !sortic) |
1806 if (state == TS_BINARY && pats->regmatch.rm_ic && !sortic) | |
1807 { | 1856 { |
1808 /* binary search won't work for ignoring case, use linear | 1857 /* binary search won't work for ignoring case, use linear |
1809 * search. */ | 1858 * search. */ |
1810 linear = TRUE; | 1859 linear = TRUE; |
1811 state = TS_LINEAR; | 1860 state = TS_LINEAR; |
1841 continue; | 1890 continue; |
1842 } | 1891 } |
1843 #endif | 1892 #endif |
1844 } | 1893 } |
1845 | 1894 |
1846 #ifdef FEAT_MBYTE | |
1847 if (lbuf[0] == '!' && pats == &orgpat | |
1848 && STRNCMP(lbuf, "!_TAG_FILE_ENCODING\t", 20) == 0) | |
1849 { | |
1850 /* Convert the search pattern from 'encoding' to the | |
1851 * specified encoding. */ | |
1852 for (p = lbuf + 20; *p > ' ' && *p < 127; ++p) | |
1853 ; | |
1854 *p = NUL; | |
1855 convert_setup(&vimconv, p_enc, lbuf + 20); | |
1856 if (vimconv.vc_type != CONV_NONE) | |
1857 { | |
1858 convpat.pat = string_convert(&vimconv, pats->pat, NULL); | |
1859 if (convpat.pat != NULL) | |
1860 { | |
1861 pats = &convpat; | |
1862 pats->len = (int)STRLEN(pats->pat); | |
1863 prepare_pats(pats, has_re); | |
1864 pats->regmatch.rm_ic = orgpat.regmatch.rm_ic; | |
1865 } | |
1866 } | |
1867 | |
1868 /* Prepare for converting a match the other way around. */ | |
1869 convert_setup(&vimconv, lbuf + 20, p_enc); | |
1870 continue; | |
1871 } | |
1872 #endif | |
1873 | |
1874 /* | 1895 /* |
1875 * Figure out where the different strings are in this line. | 1896 * Figure out where the different strings are in this line. |
1876 * For "normal" tags: Do a quick check if the tag matches. | 1897 * For "normal" tags: Do a quick check if the tag matches. |
1877 * This speeds up tag searching a lot! | 1898 * This speeds up tag searching a lot! |
1878 */ | 1899 */ |
1879 if (pats->headlen | 1900 if (orgpat.headlen |
1880 #ifdef FEAT_EMACS_TAGS | 1901 #ifdef FEAT_EMACS_TAGS |
1881 && !is_etag | 1902 && !is_etag |
1882 #endif | 1903 #endif |
1883 ) | 1904 ) |
1884 { | 1905 { |
1931 * there is no regexp, or the tag is too short. | 1952 * there is no regexp, or the tag is too short. |
1932 */ | 1953 */ |
1933 cmplen = (int)(tagp.tagname_end - tagp.tagname); | 1954 cmplen = (int)(tagp.tagname_end - tagp.tagname); |
1934 if (p_tl != 0 && cmplen > p_tl) /* adjust for 'taglength' */ | 1955 if (p_tl != 0 && cmplen > p_tl) /* adjust for 'taglength' */ |
1935 cmplen = p_tl; | 1956 cmplen = p_tl; |
1936 if (has_re && pats->headlen < cmplen) | 1957 if (has_re && orgpat.headlen < cmplen) |
1937 cmplen = pats->headlen; | 1958 cmplen = orgpat.headlen; |
1938 else if (state == TS_LINEAR && pats->headlen != cmplen) | 1959 else if (state == TS_LINEAR && orgpat.headlen != cmplen) |
1939 continue; | 1960 continue; |
1940 | 1961 |
1941 #ifdef FEAT_TAG_BINS | 1962 #ifdef FEAT_TAG_BINS |
1942 if (state == TS_BINARY) | 1963 if (state == TS_BINARY) |
1943 { | 1964 { |
1952 | 1973 |
1953 /* | 1974 /* |
1954 * Compare the current tag with the searched tag. | 1975 * Compare the current tag with the searched tag. |
1955 */ | 1976 */ |
1956 if (sortic) | 1977 if (sortic) |
1957 tagcmp = tag_strnicmp(tagp.tagname, pats->head, | 1978 tagcmp = tag_strnicmp(tagp.tagname, orgpat.head, |
1958 (size_t)cmplen); | 1979 (size_t)cmplen); |
1959 else | 1980 else |
1960 tagcmp = STRNCMP(tagp.tagname, pats->head, cmplen); | 1981 tagcmp = STRNCMP(tagp.tagname, orgpat.head, cmplen); |
1961 | 1982 |
1962 /* | 1983 /* |
1963 * A match with a shorter tag means to search forward. | 1984 * A match with a shorter tag means to search forward. |
1964 * A match with a longer tag means to search backward. | 1985 * A match with a longer tag means to search backward. |
1965 */ | 1986 */ |
1966 if (tagcmp == 0) | 1987 if (tagcmp == 0) |
1967 { | 1988 { |
1968 if (cmplen < pats->headlen) | 1989 if (cmplen < orgpat.headlen) |
1969 tagcmp = -1; | 1990 tagcmp = -1; |
1970 else if (cmplen > pats->headlen) | 1991 else if (cmplen > orgpat.headlen) |
1971 tagcmp = 1; | 1992 tagcmp = 1; |
1972 } | 1993 } |
1973 | 1994 |
1974 if (tagcmp == 0) | 1995 if (tagcmp == 0) |
1975 { | 1996 { |
2009 /* No match yet and are at the end of the binary search. */ | 2030 /* No match yet and are at the end of the binary search. */ |
2010 break; | 2031 break; |
2011 } | 2032 } |
2012 else if (state == TS_SKIP_BACK) | 2033 else if (state == TS_SKIP_BACK) |
2013 { | 2034 { |
2014 if (MB_STRNICMP(tagp.tagname, pats->head, cmplen) != 0) | 2035 if (MB_STRNICMP(tagp.tagname, orgpat.head, cmplen) != 0) |
2015 state = TS_STEP_FORWARD; | 2036 state = TS_STEP_FORWARD; |
2016 else | 2037 else |
2017 /* Have to skip back more. Restore the curr_offset | 2038 /* Have to skip back more. Restore the curr_offset |
2018 * used, otherwise we get stuck at a long line. */ | 2039 * used, otherwise we get stuck at a long line. */ |
2019 search_info.curr_offset = search_info.curr_offset_used; | 2040 search_info.curr_offset = search_info.curr_offset_used; |
2020 continue; | 2041 continue; |
2021 } | 2042 } |
2022 else if (state == TS_STEP_FORWARD) | 2043 else if (state == TS_STEP_FORWARD) |
2023 { | 2044 { |
2024 if (MB_STRNICMP(tagp.tagname, pats->head, cmplen) != 0) | 2045 if (MB_STRNICMP(tagp.tagname, orgpat.head, cmplen) != 0) |
2025 { | 2046 { |
2026 if ((off_t)ftell(fp) > search_info.match_offset) | 2047 if ((off_t)ftell(fp) > search_info.match_offset) |
2027 break; /* past last match */ | 2048 break; /* past last match */ |
2028 else | 2049 else |
2029 continue; /* before first match */ | 2050 continue; /* before first match */ |
2030 } | 2051 } |
2031 } | 2052 } |
2032 else | 2053 else |
2033 #endif | 2054 #endif |
2034 /* skip this match if it can't match */ | 2055 /* skip this match if it can't match */ |
2035 if (MB_STRNICMP(tagp.tagname, pats->head, cmplen) != 0) | 2056 if (MB_STRNICMP(tagp.tagname, orgpat.head, cmplen) != 0) |
2036 continue; | 2057 continue; |
2037 | 2058 |
2038 /* | 2059 /* |
2039 * Can be a matching tag, isolate the file name and command. | 2060 * Can be a matching tag, isolate the file name and command. |
2040 */ | 2061 */ |
2081 */ | 2102 */ |
2082 cmplen = (int)(tagp.tagname_end - tagp.tagname); | 2103 cmplen = (int)(tagp.tagname_end - tagp.tagname); |
2083 if (p_tl != 0 && cmplen > p_tl) /* adjust for 'taglength' */ | 2104 if (p_tl != 0 && cmplen > p_tl) /* adjust for 'taglength' */ |
2084 cmplen = p_tl; | 2105 cmplen = p_tl; |
2085 /* if tag length does not match, don't try comparing */ | 2106 /* if tag length does not match, don't try comparing */ |
2086 if (pats->len != cmplen) | 2107 if (orgpat.len != cmplen) |
2087 match = FALSE; | 2108 match = FALSE; |
2088 else | 2109 else |
2089 { | 2110 { |
2090 if (pats->regmatch.rm_ic) | 2111 if (orgpat.regmatch.rm_ic) |
2091 { | 2112 { |
2092 match = (MB_STRNICMP(tagp.tagname, pats->pat, cmplen) == 0); | 2113 match = (MB_STRNICMP(tagp.tagname, orgpat.pat, cmplen) == 0); |
2093 if (match) | 2114 if (match) |
2094 match_no_ic = (STRNCMP(tagp.tagname, pats->pat, | 2115 match_no_ic = (STRNCMP(tagp.tagname, orgpat.pat, |
2095 cmplen) == 0); | 2116 cmplen) == 0); |
2096 } | 2117 } |
2097 else | 2118 else |
2098 match = (STRNCMP(tagp.tagname, pats->pat, cmplen) == 0); | 2119 match = (STRNCMP(tagp.tagname, orgpat.pat, cmplen) == 0); |
2099 } | 2120 } |
2100 | 2121 |
2101 /* | 2122 /* |
2102 * Has a regexp: Also find tags matching regexp. | 2123 * Has a regexp: Also find tags matching regexp. |
2103 */ | 2124 */ |
2104 match_re = FALSE; | 2125 match_re = FALSE; |
2105 if (!match && pats->regmatch.regprog != NULL) | 2126 if (!match && orgpat.regmatch.regprog != NULL) |
2106 { | 2127 { |
2107 int cc; | 2128 int cc; |
2108 | 2129 |
2109 cc = *tagp.tagname_end; | 2130 cc = *tagp.tagname_end; |
2110 *tagp.tagname_end = NUL; | 2131 *tagp.tagname_end = NUL; |
2111 match = vim_regexec(&pats->regmatch, tagp.tagname, (colnr_T)0); | 2132 match = vim_regexec(&orgpat.regmatch, tagp.tagname, (colnr_T)0); |
2112 if (match) | 2133 if (match) |
2113 { | 2134 { |
2114 matchoff = (int)(pats->regmatch.startp[0] - tagp.tagname); | 2135 matchoff = (int)(orgpat.regmatch.startp[0] - tagp.tagname); |
2115 if (pats->regmatch.rm_ic) | 2136 if (orgpat.regmatch.rm_ic) |
2116 { | 2137 { |
2117 pats->regmatch.rm_ic = FALSE; | 2138 orgpat.regmatch.rm_ic = FALSE; |
2118 match_no_ic = vim_regexec(&pats->regmatch, tagp.tagname, | 2139 match_no_ic = vim_regexec(&orgpat.regmatch, tagp.tagname, |
2119 (colnr_T)0); | 2140 (colnr_T)0); |
2120 pats->regmatch.rm_ic = TRUE; | 2141 orgpat.regmatch.rm_ic = TRUE; |
2121 } | 2142 } |
2122 } | 2143 } |
2123 *tagp.tagname_end = cc; | 2144 *tagp.tagname_end = cc; |
2124 match_re = TRUE; | 2145 match_re = TRUE; |
2125 } | 2146 } |
2172 if (is_current) | 2193 if (is_current) |
2173 mtt = MT_GL_CUR; | 2194 mtt = MT_GL_CUR; |
2174 else | 2195 else |
2175 mtt = MT_GL_OTH; | 2196 mtt = MT_GL_OTH; |
2176 } | 2197 } |
2177 if (pats->regmatch.rm_ic && !match_no_ic) | 2198 if (orgpat.regmatch.rm_ic && !match_no_ic) |
2178 mtt += MT_IC_OFF; | 2199 mtt += MT_IC_OFF; |
2179 if (match_re) | 2200 if (match_re) |
2180 mtt += MT_RE_OFF; | 2201 mtt += MT_RE_OFF; |
2181 } | 2202 } |
2182 | 2203 |
2185 * Store the info we need later, which depends on the kind of | 2206 * Store the info we need later, which depends on the kind of |
2186 * tags we are dealing with. | 2207 * tags we are dealing with. |
2187 */ | 2208 */ |
2188 if (ga_grow(&ga_match[mtt], 1) == OK) | 2209 if (ga_grow(&ga_match[mtt], 1) == OK) |
2189 { | 2210 { |
2190 #ifdef FEAT_MBYTE | |
2191 char_u *conv_line = NULL; | |
2192 char_u *lbuf_line = lbuf; | |
2193 | |
2194 if (vimconv.vc_type != CONV_NONE) | |
2195 { | |
2196 /* Convert the tag line from the encoding of the tags | |
2197 * file to 'encoding'. Then parse the line again. */ | |
2198 conv_line = string_convert(&vimconv, lbuf, NULL); | |
2199 if (conv_line != NULL) | |
2200 { | |
2201 if (parse_tag_line(conv_line, | |
2202 #ifdef FEAT_EMACS_TAGS | |
2203 is_etag, | |
2204 #endif | |
2205 &tagp) == OK) | |
2206 lbuf_line = conv_line; | |
2207 else | |
2208 /* doesn't work, go back to unconverted line. */ | |
2209 (void)parse_tag_line(lbuf, | |
2210 #ifdef FEAT_EMACS_TAGS | |
2211 is_etag, | |
2212 #endif | |
2213 &tagp); | |
2214 } | |
2215 } | |
2216 #else | |
2217 # define lbuf_line lbuf | |
2218 #endif | |
2219 if (help_only) | 2211 if (help_only) |
2220 { | 2212 { |
2221 #ifdef FEAT_MULTI_LANG | 2213 #ifdef FEAT_MULTI_LANG |
2222 # define ML_EXTRA 3 | 2214 # define ML_EXTRA 3 |
2223 #else | 2215 #else |
2305 * Emacs tag: <mtt><tag_fname><NUL><ebuf><NUL><lbuf> | 2297 * Emacs tag: <mtt><tag_fname><NUL><ebuf><NUL><lbuf> |
2306 * other tag: <mtt><tag_fname><NUL><NUL><lbuf> | 2298 * other tag: <mtt><tag_fname><NUL><NUL><lbuf> |
2307 * without Emacs tags: <mtt><tag_fname><NUL><lbuf> | 2299 * without Emacs tags: <mtt><tag_fname><NUL><lbuf> |
2308 */ | 2300 */ |
2309 len = (int)STRLEN(tag_fname) | 2301 len = (int)STRLEN(tag_fname) |
2310 + (int)STRLEN(lbuf_line) + 3; | 2302 + (int)STRLEN(lbuf) + 3; |
2311 #ifdef FEAT_EMACS_TAGS | 2303 #ifdef FEAT_EMACS_TAGS |
2312 if (is_etag) | 2304 if (is_etag) |
2313 len += (int)STRLEN(ebuf) + 1; | 2305 len += (int)STRLEN(ebuf) + 1; |
2314 else | 2306 else |
2315 ++len; | 2307 ++len; |
2335 s += STRLEN(ebuf) + 1; | 2327 s += STRLEN(ebuf) + 1; |
2336 } | 2328 } |
2337 else | 2329 else |
2338 *s++ = NUL; | 2330 *s++ = NUL; |
2339 #endif | 2331 #endif |
2340 STRCPY(s, lbuf_line); | 2332 STRCPY(s, lbuf); |
2341 } | 2333 } |
2342 } | 2334 } |
2343 | 2335 |
2344 if (mfp != NULL) | 2336 if (mfp != NULL) |
2345 { | 2337 { |
2371 ++match_count; | 2363 ++match_count; |
2372 } | 2364 } |
2373 else | 2365 else |
2374 vim_free(mfp); | 2366 vim_free(mfp); |
2375 } | 2367 } |
2376 #ifdef FEAT_MBYTE | |
2377 /* Note: this makes the values in "tagp" invalid! */ | |
2378 vim_free(conv_line); | |
2379 #endif | |
2380 } | 2368 } |
2381 else /* Out of memory! Just forget about the rest. */ | 2369 else /* Out of memory! Just forget about the rest. */ |
2382 { | 2370 { |
2383 retval = OK; | 2371 retval = OK; |
2384 stop_searching = TRUE; | 2372 stop_searching = TRUE; |
2413 fclose(incstack[incstack_idx].fp); | 2401 fclose(incstack[incstack_idx].fp); |
2414 vim_free(incstack[incstack_idx].etag_fname); | 2402 vim_free(incstack[incstack_idx].etag_fname); |
2415 } | 2403 } |
2416 #endif | 2404 #endif |
2417 #ifdef FEAT_MBYTE | 2405 #ifdef FEAT_MBYTE |
2418 if (pats == &convpat) | |
2419 { | |
2420 /* Go back from converted pattern to original pattern. */ | |
2421 vim_free(pats->pat); | |
2422 vim_free(pats->regmatch.regprog); | |
2423 orgpat.regmatch.rm_ic = pats->regmatch.rm_ic; | |
2424 pats = &orgpat; | |
2425 } | |
2426 if (vimconv.vc_type != CONV_NONE) | 2406 if (vimconv.vc_type != CONV_NONE) |
2427 convert_setup(&vimconv, NULL, NULL); | 2407 convert_setup(&vimconv, NULL, NULL); |
2428 #endif | 2408 #endif |
2429 | 2409 |
2430 #ifdef FEAT_TAG_BINS | 2410 #ifdef FEAT_TAG_BINS |
2411 tag_file_sorted = NUL; | |
2431 if (sort_error) | 2412 if (sort_error) |
2432 { | 2413 { |
2433 EMSG2(_("E432: Tags file not sorted: %s"), tag_fname); | 2414 EMSG2(_("E432: Tags file not sorted: %s"), tag_fname); |
2434 sort_error = FALSE; | 2415 sort_error = FALSE; |
2435 } | 2416 } |
2459 tagname_free(&tn); | 2440 tagname_free(&tn); |
2460 | 2441 |
2461 #ifdef FEAT_TAG_BINS | 2442 #ifdef FEAT_TAG_BINS |
2462 /* stop searching when already did a linear search, or when TAG_NOIC | 2443 /* stop searching when already did a linear search, or when TAG_NOIC |
2463 * used, and 'ignorecase' not set or already did case-ignore search */ | 2444 * used, and 'ignorecase' not set or already did case-ignore search */ |
2464 if (stop_searching || linear || (!p_ic && noic) || pats->regmatch.rm_ic) | 2445 if (stop_searching || linear || (!p_ic && noic) || orgpat.regmatch.rm_ic) |
2465 break; | 2446 break; |
2466 # ifdef FEAT_CSCOPE | 2447 # ifdef FEAT_CSCOPE |
2467 if (use_cscope) | 2448 if (use_cscope) |
2468 break; | 2449 break; |
2469 # endif | 2450 # endif |
2470 pats->regmatch.rm_ic = TRUE; /* try another time while ignoring case */ | 2451 orgpat.regmatch.rm_ic = TRUE; /* try another time while ignoring case */ |
2471 } | 2452 } |
2472 #endif | 2453 #endif |
2473 | 2454 |
2474 if (!stop_searching) | 2455 if (!stop_searching) |
2475 { | 2456 { |
2478 retval = OK; /* It's OK even when no tag found */ | 2459 retval = OK; /* It's OK even when no tag found */ |
2479 } | 2460 } |
2480 | 2461 |
2481 findtag_end: | 2462 findtag_end: |
2482 vim_free(lbuf); | 2463 vim_free(lbuf); |
2483 vim_free(pats->regmatch.regprog); | 2464 vim_free(orgpat.regmatch.regprog); |
2484 vim_free(tag_fname); | 2465 vim_free(tag_fname); |
2485 #ifdef FEAT_EMACS_TAGS | 2466 #ifdef FEAT_EMACS_TAGS |
2486 vim_free(ebuf); | 2467 vim_free(ebuf); |
2487 #endif | 2468 #endif |
2488 | 2469 |