# HG changeset patch # User Bram Moolenaar # Date 1573164904 -3600 # Node ID 90e5812af76ba00506ab9316af7d8bbb2f2f0b2f # Parent 8ce88501264f4862ba6819e55319371739b7f47b patch 8.1.2269: tags file with very long line stops using binary search Commit: https://github.com/vim/vim/commit/dc9ef26845c6bf5ba63bfa8d00fc8a9bdc3b2de5 Author: Bram Moolenaar Date: Thu Nov 7 23:08:42 2019 +0100 patch 8.1.2269: tags file with very long line stops using binary search Problem: Tags file with very long line stops using binary search. Solution: Reallocate the buffer if needed. diff --git a/src/tag.c b/src/tag.c --- a/src/tag.c +++ b/src/tag.c @@ -1937,7 +1937,7 @@ find_tags( */ else if (state == TS_SKIP_BACK) { - search_info.curr_offset -= LSIZE * 2; + search_info.curr_offset -= lbuf_size * 2; if (search_info.curr_offset < 0) { search_info.curr_offset = 0; @@ -1955,7 +1955,7 @@ find_tags( /* Adjust the search file offset to the correct position */ search_info.curr_offset_used = search_info.curr_offset; vim_fseek(fp, search_info.curr_offset, SEEK_SET); - eof = vim_fgets(lbuf, LSIZE, fp); + eof = vim_fgets(lbuf, lbuf_size, fp); if (!eof && search_info.curr_offset != 0) { /* The explicit cast is to work around a bug in gcc 3.4.2 @@ -1967,13 +1967,13 @@ find_tags( vim_fseek(fp, search_info.low_offset, SEEK_SET); search_info.curr_offset = search_info.low_offset; } - eof = vim_fgets(lbuf, LSIZE, fp); + eof = vim_fgets(lbuf, lbuf_size, fp); } /* skip empty and blank lines */ while (!eof && vim_isblankline(lbuf)) { search_info.curr_offset = vim_ftell(fp); - eof = vim_fgets(lbuf, LSIZE, fp); + eof = vim_fgets(lbuf, lbuf_size, fp); } if (eof) { @@ -1996,10 +1996,10 @@ find_tags( { #ifdef FEAT_CSCOPE if (use_cscope) - eof = cs_fgets(lbuf, LSIZE); + eof = cs_fgets(lbuf, lbuf_size); else #endif - eof = vim_fgets(lbuf, LSIZE, fp); + eof = vim_fgets(lbuf, lbuf_size, fp); } while (!eof && vim_isblankline(lbuf)); if (eof) @@ -2230,28 +2230,21 @@ parse_line: // When the line is too long the NUL will not be in the // last-but-one byte (see vim_fgets()). // Has been reported for Mozilla JS with extremely long names. - // In that case we can't parse it and we ignore the line. - if (lbuf[LSIZE - 2] != NUL + // In that case we need to increase lbuf_size. + if (lbuf[lbuf_size - 2] != NUL #ifdef FEAT_CSCOPE && !use_cscope #endif ) { - if (p_verbose >= 5) - { - verbose_enter(); - msg(_("Ignoring long line in tags file")); - verbose_leave(); - } -#ifdef FEAT_TAG_BINS - if (state != TS_LINEAR) - { - // Avoid getting stuck. - linear = TRUE; - state = TS_LINEAR; - vim_fseek(fp, search_info.low_offset, SEEK_SET); - } -#endif + lbuf_size *= 2; + vim_free(lbuf); + lbuf = alloc(lbuf_size); + if (lbuf == NULL) + goto findtag_end; + // this will try the same thing again, make sure the offset is + // different + search_info.curr_offset = 0; continue; } @@ -3367,6 +3360,8 @@ jumpto_tag( break; #endif *pbuf_end++ = *str++; + if (pbuf_end - pbuf + 1 >= LSIZE) + break; } *pbuf_end = NUL; diff --git a/src/testdir/test_tagjump.vim b/src/testdir/test_tagjump.vim --- a/src/testdir/test_tagjump.vim +++ b/src/testdir/test_tagjump.vim @@ -459,7 +459,8 @@ func Test_tag_line_toolong() call assert_report(v:exception) catch /.*/ endtry - call assert_equal('Ignoring long line in tags file', split(execute('messages'), '\n')[-1]) + call assert_equal('Searching tags file Xtags', split(execute('messages'), '\n')[-1]) + call writefile([ \ '123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567 django/contrib/admin/templates/admin/edit_inline/stacked.html 16;" j line:16 language:HTML' \ ], 'Xtags') @@ -470,8 +471,26 @@ func Test_tag_line_toolong() call assert_report(v:exception) catch /.*/ endtry - call assert_equal('Ignoring long line in tags file', split(execute('messages'), '\n')[-1]) + call assert_equal('Searching tags file Xtags', split(execute('messages'), '\n')[-1]) + + " binary search works in file with long line + call writefile([ + \ 'asdfasfd nowhere 16', + \ 'foobar Xsomewhere 3; " 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567', + \ 'zasdfasfd nowhere 16', + \ ], 'Xtags') + call writefile([ + \ 'one', + \ 'two', + \ 'trhee', + \ 'four', + \ ], 'Xsomewhere') + tag foobar + call assert_equal('Xsomewhere', expand('%')) + call assert_equal(3, getcurpos()[1]) + call delete('Xtags') + call delete('Xsomewhere') set tags& let &verbose = old_vbs endfunc diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2269, +/**/ 2268, /**/ 2267,