]> granicus.if.org Git - vim/commitdiff
patch 8.1.2269: tags file with very long line stops using binary search v8.1.2269
authorBram Moolenaar <Bram@vim.org>
Thu, 7 Nov 2019 22:08:42 +0000 (23:08 +0100)
committerBram Moolenaar <Bram@vim.org>
Thu, 7 Nov 2019 22:08:42 +0000 (23:08 +0100)
Problem:    Tags file with very long line stops using binary search.
Solution:   Reallocate the buffer if needed.

src/tag.c
src/testdir/test_tagjump.vim
src/version.c

index 136fea520470f748f841958941ecfc00c3544550..ab79690adaa5d03e9f1d5776bbd481ba52a114f6 100644 (file)
--- 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;
 
index 81d3e80a1c7567460d05761190877f2198cdb774..34a3c3055bd80ca7162074485d3e7346541942f8 100644 (file)
@@ -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
index 2db75aa6e0b668bc86d7a26096d7edbe59bc0a5c..541b2adc732a7aaa7db5d1d48e8e96c8a90dfe89 100644 (file)
@@ -741,6 +741,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2269,
 /**/
     2268,
 /**/