To: vim_dev@googlegroups.com Subject: Patch 8.2.4518 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.4518 Problem: The binary tag search feature is always enabled. Solution: Remove the #ifdefs. Add a few more tests. (Yegappan Lakshmanan, closes #9893) Files: src/evalfunc.c, src/feature.h, src/tag.c, src/version.c, src/testdir/test_tagjump.vim, src/testdir/test_taglist.vim *** ../vim-8.2.4517/src/evalfunc.c 2022-02-23 21:03:28.913442583 +0000 --- src/evalfunc.c 2022-03-06 14:07:16.086379968 +0000 *************** *** 4382,4388 **** if (s == NULL || *s == NUL || (use_string && VIM_ISDIGIT(*s)) || (is_funcref && trans_name == NULL)) ! semsg(_(e_invalid_argument_str), use_string ? tv_get_string(&argvars[0]) : s); // Don't check an autoload name for existence here. else if (trans_name != NULL && (is_funcref ? find_func(trans_name, is_global) == NULL --- 4382,4389 ---- if (s == NULL || *s == NUL || (use_string && VIM_ISDIGIT(*s)) || (is_funcref && trans_name == NULL)) ! semsg(_(e_invalid_argument_str), ! use_string ? tv_get_string(&argvars[0]) : s); // Don't check an autoload name for existence here. else if (trans_name != NULL && (is_funcref ? find_func(trans_name, is_global) == NULL *************** *** 6101,6113 **** 0 #endif }, ! {"tag_binary", ! #ifdef FEAT_TAG_BINS ! 1 ! #else ! 0 ! #endif ! }, {"tcl", #if defined(FEAT_TCL) && !defined(DYNAMIC_TCL) 1 --- 6102,6108 ---- 0 #endif }, ! {"tag_binary", 1}, // graduated feature {"tcl", #if defined(FEAT_TCL) && !defined(DYNAMIC_TCL) 1 *** ../vim-8.2.4517/src/feature.h 2022-02-23 18:07:34.361914993 +0000 --- src/feature.h 2022-03-06 14:07:16.086379968 +0000 *************** *** 249,259 **** #endif /* - * +tag_binary Can use a binary search for the tags file. - */ - #define FEAT_TAG_BINS - - /* * +cscope Unix only: Cscope support. */ #if defined(UNIX) && defined(FEAT_BIG) && !defined(FEAT_CSCOPE) && !defined(MACOS_X) --- 249,254 ---- *** ../vim-8.2.4517/src/tag.c 2022-03-05 14:35:07.319171786 +0000 --- src/tag.c 2022-03-06 14:07:16.086379968 +0000 *************** *** 1270,1276 **** msg_puts("\n>"); } - #ifdef FEAT_TAG_BINS /* * Compare two strings, for length "len", ignoring case the ASCII way. * return 0 for match, < 0 for smaller, > 0 for bigger --- 1270,1275 ---- *************** *** 1294,1300 **** } return 0; // strings match } - #endif /* * Structure to hold info about the tag pattern being used. --- 1293,1298 ---- *************** *** 1592,1600 **** int did_open; // did open a tag file int mincount; // MAXCOL: find all matches // other: minimal number of matches - #ifdef FEAT_TAG_BINS int linear; // do a linear search - #endif char_u *lbuf; // line buffer int lbuf_size; // length of lbuf #ifdef FEAT_EMACS_TAGS --- 1590,1596 ---- *************** *** 1960,1969 **** return FALSE; // Read header line. - #ifdef FEAT_TAG_BINS if (STRNCMP(st->lbuf, "!_TAG_FILE_SORTED\t", 18) == 0) *sorted_file = st->lbuf[18]; - #endif if (STRNCMP(st->lbuf, "!_TAG_FILE_ENCODING\t", 20) == 0) { // Prepare to convert every line from the specified --- 1956,1963 ---- *************** *** 2264,2286 **** int help_pri = 0; char_u help_lang[3] = ""; // lang of current tags file #endif - #ifdef FEAT_TAG_BINS int tag_file_sorted = NUL; // !_TAG_FILE_SORTED value off_T filesize; int tagcmp; off_T offset; - #endif enum { TS_START, // at start of file ! TS_LINEAR // linear searching forward, till EOF ! #ifdef FEAT_TAG_BINS ! , TS_BINARY, // binary searching TS_SKIP_BACK, // skipping backwards TS_STEP_FORWARD // stepping forwards - #endif } state; // Current search state - #ifdef FEAT_TAG_BINS struct tag_search_info // Binary search file offsets { off_T low_offset; // offset for first char of first line that --- 2258,2275 ---- int help_pri = 0; char_u help_lang[3] = ""; // lang of current tags file #endif int tag_file_sorted = NUL; // !_TAG_FILE_SORTED value off_T filesize; int tagcmp; off_T offset; enum { TS_START, // at start of file ! TS_LINEAR, // linear searching forward, till EOF ! TS_BINARY, // binary searching TS_SKIP_BACK, // skipping backwards TS_STEP_FORWARD // stepping forwards } state; // Current search state struct tag_search_info // Binary search file offsets { off_T low_offset; // offset for first char of first line that *************** *** 2293,2299 **** int low_char; // first char at low_offset int high_char; // first char at high_offset } search_info; - #endif int cmplen; int match; // matches --- 2282,2287 ---- *************** *** 2305,2315 **** hash_T hash = 0; - #ifdef FEAT_TAG_BINS int sort_error = FALSE; // tags file not sorted int sortic = FALSE; // tag file sorted in nocase int noic = (flags & TAG_NOIC); - #endif int line_error = FALSE; // syntax error int has_re = (flags & TAG_REGEXP); // regexp used #ifdef FEAT_CSCOPE --- 2293,2301 ---- *************** *** 2319,2329 **** vimconv.vc_type = CONV_NONE; - #ifdef FEAT_TAG_BINS // This is only to avoid a compiler warning for using search_info // uninitialised. CLEAR_FIELD(search_info); - #endif // A file that doesn't exist is silently ignored. Only when not a // single file is found, an error message is given (further on). --- 2305,2313 ---- *************** *** 2359,2370 **** // Read and parse the lines in the file one by one for (;;) { - #ifdef FEAT_TAG_BINS // check for CTRL-C typed, more often when jumping around if (state == TS_BINARY || state == TS_SKIP_BACK) line_breakcheck(); else - #endif fast_breakcheck(); if ((flags & TAG_INS_COMP)) // Double brackets for gcc ins_compl_check_keys(30, FALSE); --- 2343,2352 ---- *************** *** 2382,2388 **** } if (st->get_searchpat) goto line_read_in; - #ifdef FEAT_TAG_BINS // For binary search: compute the next offset to use. if (state == TS_BINARY) { --- 2364,2369 ---- *************** *** 2449,2455 **** * Not jumping around in the file: Read the next line. */ else - #endif { // skip empty and blank lines do --- 2430,2435 ---- *************** *** 2460,2468 **** else #endif { - #ifdef FEAT_TAG_BINS search_info.curr_offset = vim_ftell(fp); - #endif eof = vim_fgets(st->lbuf, st->lbuf_size, fp); } } while (!eof && vim_isblankline(st->lbuf)); --- 2440,2446 ---- *************** *** 2525,2531 **** // Headers ends. - #ifdef FEAT_TAG_BINS /* * When there is no tag head, or ignoring case, need to do a * linear search. --- 2503,2508 ---- *************** *** 2561,2571 **** st->linear = TRUE; state = TS_LINEAR; } - #else - state = TS_LINEAR; - #endif - #ifdef FEAT_TAG_BINS // When starting a binary search, get the size of the file and // compute the first offset. if (state == TS_BINARY) --- 2538,2544 ---- *************** *** 2591,2597 **** } continue; } - #endif } parse_line: --- 2564,2569 ---- *************** *** 2615,2628 **** return FAIL; } - #ifdef FEAT_TAG_BINS if (state == TS_STEP_FORWARD) // Seek to the same position to read the same line again vim_fseek(fp, search_info.curr_offset, SEEK_SET); // this will try the same thing again, make sure the offset is // different search_info.curr_offset = 0; - #endif continue; } --- 2587,2598 ---- *************** *** 2659,2665 **** else if (state == TS_LINEAR && st->orgpat.headlen != cmplen) continue; - #ifdef FEAT_TAG_BINS if (state == TS_BINARY) { /* --- 2629,2634 ---- *************** *** 2750,2756 **** } } else - #endif // skip this match if it can't match if (MB_STRNICMP(tagp.tagname, st->orgpat.head, cmplen) != 0) continue; --- 2719,2724 ---- *************** *** 2874,2887 **** if (vimconv.vc_type != CONV_NONE) convert_setup(&vimconv, NULL, NULL); - #ifdef FEAT_TAG_BINS tag_file_sorted = NUL; if (sort_error) { semsg(_(e_tags_file_not_sorted_str), st->tag_fname); sort_error = FALSE; } - #endif /* * Stop searching if sufficient tags have been found. --- 2842,2853 ---- *************** *** 2983,2991 **** tagname_T tn; // info for get_tagfname() int first_file; // trying first tag file int retval = FAIL; // return value - #ifdef FEAT_TAG_BINS int round; - #endif int save_emsg_off; --- 2949,2955 ---- *************** *** 2995,3004 **** char_u *saved_pat = NULL; // copy of pat[] #endif - #ifdef FEAT_TAG_BINS int findall = (mincount == MAXCOL || mincount == TAG_MANY); // find all matching tags - #endif int has_re = (flags & TAG_REGEXP); // regexp used int noic = (flags & TAG_NOIC); #ifdef FEAT_CSCOPE --- 2959,2966 ---- *************** *** 3101,3115 **** * When the tag file is case-fold sorted, it is either one or the other. * Only ignore case when TAG_NOIC not used or 'ignorecase' set. */ - #ifdef FEAT_TAG_BINS st.orgpat.regmatch.rm_ic = ((p_ic || !noic) && (findall || st.orgpat.headlen == 0 || !p_tbs)); for (round = 1; round <= 2; ++round) { st.linear = (st.orgpat.headlen == 0 || !p_tbs || round == 2); - #else - st.orgpat.regmatch.rm_ic = (p_ic || !noic); - #endif /* * Try tag file names from tags option one by one. --- 3063,3073 ---- *************** *** 3139,3145 **** #endif tagname_free(&tn); - #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 (st.stop_searching || st.linear || (!p_ic && noic) || --- 3097,3102 ---- *************** *** 3153,3159 **** // try another time while ignoring case st.orgpat.regmatch.rm_ic = TRUE; } - #endif if (!st.stop_searching) { --- 3110,3115 ---- *** ../vim-8.2.4517/src/version.c 2022-03-06 14:01:48.179250403 +0000 --- src/version.c 2022-03-06 14:08:55.406125125 +0000 *************** *** 590,600 **** #if defined(USE_SYSTEM) && defined(UNIX) "+system()", #endif - #ifdef FEAT_TAG_BINS "+tag_binary", - #else - "-tag_binary", - #endif "-tag_old_static", "-tag_any_white", #ifdef FEAT_TCL --- 590,596 ---- *** ../vim-8.2.4517/src/testdir/test_tagjump.vim 2022-03-05 14:35:07.319171786 +0000 --- src/testdir/test_tagjump.vim 2022-03-06 14:07:16.086379968 +0000 *************** *** 1503,1506 **** --- 1503,1579 ---- set tags& endfunc + " Test for 'tagbsearch' (binary search) + func Test_tagbsearch() + " If a tags file header says the tags are sorted, but the tags are actually + " unsorted, then binary search should fail and linear search should work. + call writefile([ + \ "!_TAG_FILE_ENCODING\tutf-8\t//", + \ "!_TAG_FILE_SORTED\t1\t/0=unsorted, 1=sorted, 2=foldcase/", + \ "third\tXfoo\t3", + \ "second\tXfoo\t2", + \ "first\tXfoo\t1"], + \ 'Xtags') + set tags=Xtags + let code =<< trim [CODE] + int first() {} + int second() {} + int third() {} + [CODE] + call writefile(code, 'Xfoo') + + enew + set tagbsearch + call assert_fails('tag first', 'E426:') + call assert_equal('', bufname()) + call assert_fails('tag second', 'E426:') + call assert_equal('', bufname()) + tag third + call assert_equal('Xfoo', bufname()) + call assert_equal(3, line('.')) + %bw! + + set notagbsearch + tag first + call assert_equal('Xfoo', bufname()) + call assert_equal(1, line('.')) + enew + tag second + call assert_equal('Xfoo', bufname()) + call assert_equal(2, line('.')) + enew + tag third + call assert_equal('Xfoo', bufname()) + call assert_equal(3, line('.')) + %bw! + + " If a tags file header says the tags are unsorted, but the tags are + " actually sorted, then binary search should work. + call writefile([ + \ "!_TAG_FILE_ENCODING\tutf-8\t//", + \ "!_TAG_FILE_SORTED\t0\t/0=unsorted, 1=sorted, 2=foldcase/", + \ "first\tXfoo\t1", + \ "second\tXfoo\t2", + \ "third\tXfoo\t3"], + \ 'Xtags') + + set tagbsearch + tag first + call assert_equal('Xfoo', bufname()) + call assert_equal(1, line('.')) + enew + tag second + call assert_equal('Xfoo', bufname()) + call assert_equal(2, line('.')) + enew + tag third + call assert_equal('Xfoo', bufname()) + call assert_equal(3, line('.')) + %bw! + + call delete('Xtags') + call delete('Xfoo') + set tags& tagbsearch& + endfunc + " vim: shiftwidth=2 sts=2 expandtab *** ../vim-8.2.4517/src/testdir/test_taglist.vim 2021-12-10 20:15:11.697972271 +0000 --- src/testdir/test_taglist.vim 2022-03-06 14:07:16.086379968 +0000 *************** *** 37,42 **** --- 37,48 ---- call assert_equal('d', cmd[0]['kind']) call assert_equal('call cursor(3, 4)', cmd[0]['cmd']) + " Use characters with value > 127 in the tag extra field. + call writefile([ + \ "vFoo\tXfoo\t4" .. ';"' .. "\ttypename:int\ta£££\tv", + \ ], 'Xtags') + call assert_equal('v', taglist('vFoo')[0].kind) + call assert_fails("let l=taglist([])", 'E730:') call delete('Xtags') *************** *** 216,221 **** --- 222,232 ---- endtry call assert_true(caught_exception) + " no field after the filename for a tag + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "foo\tXfile"], 'Xtags') + call assert_fails("echo taglist('foo')", 'E431:') + set tags& call delete('Xtags') endfunc *** ../vim-8.2.4517/src/version.c 2022-03-06 14:01:48.179250403 +0000 --- src/version.c 2022-03-06 14:08:55.406125125 +0000 *************** *** 756,757 **** --- 752,755 ---- { /* Add new patch number below this line */ + /**/ + 4518, /**/ -- hundred-and-one symptoms of being an internet addict: 177. You log off of your system because it's time to go to work. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///