changeset 18550:90e5812af76b v8.1.2269

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 <Bram@vim.org> 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.
author Bram Moolenaar <Bram@vim.org>
date Thu, 07 Nov 2019 23:15:04 +0100
parents 8ce88501264f
children 3f04b0a32e7f
files src/tag.c src/testdir/test_tagjump.vim src/version.c
diffstat 3 files changed, 41 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- 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;
 
--- 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
--- 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,