Mercurial > vim
comparison src/tag.c @ 27986:c724906134a3 v8.2.4518
patch 8.2.4518: the binary tag search feature is always enabled
Commit: https://github.com/vim/vim/commit/655b734ee858e90dd8d28549b7704a71b25d30e7
Author: Yegappan Lakshmanan <yegappan@yahoo.com>
Date: Sun Mar 6 14:27:10 2022 +0000
patch 8.2.4518: the binary tag search feature is always enabled
Problem: The binary tag search feature is always enabled.
Solution: Remove the #ifdefs. Add a few more tests. (Yegappan Lakshmanan,
closes #9893)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sun, 06 Mar 2022 15:30:06 +0100 |
parents | 495418c6cac8 |
children | d59552ad3f36 |
comparison
equal
deleted
inserted
replaced
27985:719dc5b9fc6e | 27986:c724906134a3 |
---|---|
1268 } | 1268 } |
1269 if (tagstackidx == tagstacklen) // idx at top of stack | 1269 if (tagstackidx == tagstacklen) // idx at top of stack |
1270 msg_puts("\n>"); | 1270 msg_puts("\n>"); |
1271 } | 1271 } |
1272 | 1272 |
1273 #ifdef FEAT_TAG_BINS | |
1274 /* | 1273 /* |
1275 * Compare two strings, for length "len", ignoring case the ASCII way. | 1274 * Compare two strings, for length "len", ignoring case the ASCII way. |
1276 * return 0 for match, < 0 for smaller, > 0 for bigger | 1275 * return 0 for match, < 0 for smaller, > 0 for bigger |
1277 * Make sure case is folded to uppercase in comparison (like for 'sort -f') | 1276 * Make sure case is folded to uppercase in comparison (like for 'sort -f') |
1278 */ | 1277 */ |
1292 ++s2; | 1291 ++s2; |
1293 --len; | 1292 --len; |
1294 } | 1293 } |
1295 return 0; // strings match | 1294 return 0; // strings match |
1296 } | 1295 } |
1297 #endif | |
1298 | 1296 |
1299 /* | 1297 /* |
1300 * Structure to hold info about the tag pattern being used. | 1298 * Structure to hold info about the tag pattern being used. |
1301 */ | 1299 */ |
1302 typedef struct | 1300 typedef struct |
1590 int is_txt; // flag of file extension | 1588 int is_txt; // flag of file extension |
1591 #endif | 1589 #endif |
1592 int did_open; // did open a tag file | 1590 int did_open; // did open a tag file |
1593 int mincount; // MAXCOL: find all matches | 1591 int mincount; // MAXCOL: find all matches |
1594 // other: minimal number of matches | 1592 // other: minimal number of matches |
1595 #ifdef FEAT_TAG_BINS | |
1596 int linear; // do a linear search | 1593 int linear; // do a linear search |
1597 #endif | |
1598 char_u *lbuf; // line buffer | 1594 char_u *lbuf; // line buffer |
1599 int lbuf_size; // length of lbuf | 1595 int lbuf_size; // length of lbuf |
1600 #ifdef FEAT_EMACS_TAGS | 1596 #ifdef FEAT_EMACS_TAGS |
1601 char_u *ebuf; // additional buffer for etag fname | 1597 char_u *ebuf; // additional buffer for etag fname |
1602 #endif | 1598 #endif |
1958 if (STRNCMP(st->lbuf, "!_TAG_", 6) != 0) | 1954 if (STRNCMP(st->lbuf, "!_TAG_", 6) != 0) |
1959 // Non-header item before the header, e.g. "!" itself. | 1955 // Non-header item before the header, e.g. "!" itself. |
1960 return FALSE; | 1956 return FALSE; |
1961 | 1957 |
1962 // Read header line. | 1958 // Read header line. |
1963 #ifdef FEAT_TAG_BINS | |
1964 if (STRNCMP(st->lbuf, "!_TAG_FILE_SORTED\t", 18) == 0) | 1959 if (STRNCMP(st->lbuf, "!_TAG_FILE_SORTED\t", 18) == 0) |
1965 *sorted_file = st->lbuf[18]; | 1960 *sorted_file = st->lbuf[18]; |
1966 #endif | |
1967 if (STRNCMP(st->lbuf, "!_TAG_FILE_ENCODING\t", 20) == 0) | 1961 if (STRNCMP(st->lbuf, "!_TAG_FILE_ENCODING\t", 20) == 0) |
1968 { | 1962 { |
1969 // Prepare to convert every line from the specified | 1963 // Prepare to convert every line from the specified |
1970 // encoding to 'encoding'. | 1964 // encoding to 'encoding'. |
1971 for (p = st->lbuf + 20; *p > ' ' && *p < 127; ++p) | 1965 for (p = st->lbuf + 20; *p > ' ' && *p < 127; ++p) |
2262 int i; | 2256 int i; |
2263 #ifdef FEAT_MULTI_LANG | 2257 #ifdef FEAT_MULTI_LANG |
2264 int help_pri = 0; | 2258 int help_pri = 0; |
2265 char_u help_lang[3] = ""; // lang of current tags file | 2259 char_u help_lang[3] = ""; // lang of current tags file |
2266 #endif | 2260 #endif |
2267 #ifdef FEAT_TAG_BINS | |
2268 int tag_file_sorted = NUL; // !_TAG_FILE_SORTED value | 2261 int tag_file_sorted = NUL; // !_TAG_FILE_SORTED value |
2269 off_T filesize; | 2262 off_T filesize; |
2270 int tagcmp; | 2263 int tagcmp; |
2271 off_T offset; | 2264 off_T offset; |
2272 #endif | |
2273 enum | 2265 enum |
2274 { | 2266 { |
2275 TS_START, // at start of file | 2267 TS_START, // at start of file |
2276 TS_LINEAR // linear searching forward, till EOF | 2268 TS_LINEAR, // linear searching forward, till EOF |
2277 #ifdef FEAT_TAG_BINS | 2269 TS_BINARY, // binary searching |
2278 , TS_BINARY, // binary searching | |
2279 TS_SKIP_BACK, // skipping backwards | 2270 TS_SKIP_BACK, // skipping backwards |
2280 TS_STEP_FORWARD // stepping forwards | 2271 TS_STEP_FORWARD // stepping forwards |
2281 #endif | |
2282 } state; // Current search state | 2272 } state; // Current search state |
2283 #ifdef FEAT_TAG_BINS | |
2284 struct tag_search_info // Binary search file offsets | 2273 struct tag_search_info // Binary search file offsets |
2285 { | 2274 { |
2286 off_T low_offset; // offset for first char of first line that | 2275 off_T low_offset; // offset for first char of first line that |
2287 // could match | 2276 // could match |
2288 off_T high_offset; // offset of char after last line that could | 2277 off_T high_offset; // offset of char after last line that could |
2291 off_T curr_offset_used; // curr_offset used when skipping back | 2280 off_T curr_offset_used; // curr_offset used when skipping back |
2292 off_T match_offset; // Where the binary search found a tag | 2281 off_T match_offset; // Where the binary search found a tag |
2293 int low_char; // first char at low_offset | 2282 int low_char; // first char at low_offset |
2294 int high_char; // first char at high_offset | 2283 int high_char; // first char at high_offset |
2295 } search_info; | 2284 } search_info; |
2296 #endif | |
2297 | 2285 |
2298 int cmplen; | 2286 int cmplen; |
2299 int match; // matches | 2287 int match; // matches |
2300 int match_no_ic = 0;// matches with rm_ic == FALSE | 2288 int match_no_ic = 0;// matches with rm_ic == FALSE |
2301 int match_re; // match with regexp | 2289 int match_re; // match with regexp |
2303 | 2291 |
2304 int is_etag; // current file is emaces style | 2292 int is_etag; // current file is emaces style |
2305 | 2293 |
2306 hash_T hash = 0; | 2294 hash_T hash = 0; |
2307 | 2295 |
2308 #ifdef FEAT_TAG_BINS | |
2309 int sort_error = FALSE; // tags file not sorted | 2296 int sort_error = FALSE; // tags file not sorted |
2310 int sortic = FALSE; // tag file sorted in nocase | 2297 int sortic = FALSE; // tag file sorted in nocase |
2311 int noic = (flags & TAG_NOIC); | 2298 int noic = (flags & TAG_NOIC); |
2312 #endif | |
2313 int line_error = FALSE; // syntax error | 2299 int line_error = FALSE; // syntax error |
2314 int has_re = (flags & TAG_REGEXP); // regexp used | 2300 int has_re = (flags & TAG_REGEXP); // regexp used |
2315 #ifdef FEAT_CSCOPE | 2301 #ifdef FEAT_CSCOPE |
2316 int use_cscope = (flags & TAG_CSCOPE); | 2302 int use_cscope = (flags & TAG_CSCOPE); |
2317 #endif | 2303 #endif |
2318 vimconv_T vimconv; | 2304 vimconv_T vimconv; |
2319 | 2305 |
2320 vimconv.vc_type = CONV_NONE; | 2306 vimconv.vc_type = CONV_NONE; |
2321 | 2307 |
2322 #ifdef FEAT_TAG_BINS | |
2323 // This is only to avoid a compiler warning for using search_info | 2308 // This is only to avoid a compiler warning for using search_info |
2324 // uninitialised. | 2309 // uninitialised. |
2325 CLEAR_FIELD(search_info); | 2310 CLEAR_FIELD(search_info); |
2326 #endif | |
2327 | 2311 |
2328 // A file that doesn't exist is silently ignored. Only when not a | 2312 // A file that doesn't exist is silently ignored. Only when not a |
2329 // single file is found, an error message is given (further on). | 2313 // single file is found, an error message is given (further on). |
2330 #ifdef FEAT_CSCOPE | 2314 #ifdef FEAT_CSCOPE |
2331 if (use_cscope) | 2315 if (use_cscope) |
2357 is_etag = 0; // default is: not emacs style | 2341 is_etag = 0; // default is: not emacs style |
2358 | 2342 |
2359 // Read and parse the lines in the file one by one | 2343 // Read and parse the lines in the file one by one |
2360 for (;;) | 2344 for (;;) |
2361 { | 2345 { |
2362 #ifdef FEAT_TAG_BINS | |
2363 // check for CTRL-C typed, more often when jumping around | 2346 // check for CTRL-C typed, more often when jumping around |
2364 if (state == TS_BINARY || state == TS_SKIP_BACK) | 2347 if (state == TS_BINARY || state == TS_SKIP_BACK) |
2365 line_breakcheck(); | 2348 line_breakcheck(); |
2366 else | 2349 else |
2367 #endif | |
2368 fast_breakcheck(); | 2350 fast_breakcheck(); |
2369 if ((flags & TAG_INS_COMP)) // Double brackets for gcc | 2351 if ((flags & TAG_INS_COMP)) // Double brackets for gcc |
2370 ins_compl_check_keys(30, FALSE); | 2352 ins_compl_check_keys(30, FALSE); |
2371 if (got_int || ins_compl_interrupted()) | 2353 if (got_int || ins_compl_interrupted()) |
2372 { | 2354 { |
2380 st->stop_searching = TRUE; | 2362 st->stop_searching = TRUE; |
2381 break; | 2363 break; |
2382 } | 2364 } |
2383 if (st->get_searchpat) | 2365 if (st->get_searchpat) |
2384 goto line_read_in; | 2366 goto line_read_in; |
2385 #ifdef FEAT_TAG_BINS | |
2386 // For binary search: compute the next offset to use. | 2367 // For binary search: compute the next offset to use. |
2387 if (state == TS_BINARY) | 2368 if (state == TS_BINARY) |
2388 { | 2369 { |
2389 offset = search_info.low_offset + ((search_info.high_offset | 2370 offset = search_info.low_offset + ((search_info.high_offset |
2390 - search_info.low_offset) / 2); | 2371 - search_info.low_offset) / 2); |
2447 | 2428 |
2448 /* | 2429 /* |
2449 * Not jumping around in the file: Read the next line. | 2430 * Not jumping around in the file: Read the next line. |
2450 */ | 2431 */ |
2451 else | 2432 else |
2452 #endif | |
2453 { | 2433 { |
2454 // skip empty and blank lines | 2434 // skip empty and blank lines |
2455 do | 2435 do |
2456 { | 2436 { |
2457 #ifdef FEAT_CSCOPE | 2437 #ifdef FEAT_CSCOPE |
2458 if (use_cscope) | 2438 if (use_cscope) |
2459 eof = cs_fgets(st->lbuf, st->lbuf_size); | 2439 eof = cs_fgets(st->lbuf, st->lbuf_size); |
2460 else | 2440 else |
2461 #endif | 2441 #endif |
2462 { | 2442 { |
2463 #ifdef FEAT_TAG_BINS | |
2464 search_info.curr_offset = vim_ftell(fp); | 2443 search_info.curr_offset = vim_ftell(fp); |
2465 #endif | |
2466 eof = vim_fgets(st->lbuf, st->lbuf_size, fp); | 2444 eof = vim_fgets(st->lbuf, st->lbuf_size, fp); |
2467 } | 2445 } |
2468 } while (!eof && vim_isblankline(st->lbuf)); | 2446 } while (!eof && vim_isblankline(st->lbuf)); |
2469 | 2447 |
2470 if (eof) | 2448 if (eof) |
2523 goto parse_line; | 2501 goto parse_line; |
2524 } | 2502 } |
2525 | 2503 |
2526 // Headers ends. | 2504 // Headers ends. |
2527 | 2505 |
2528 #ifdef FEAT_TAG_BINS | |
2529 /* | 2506 /* |
2530 * When there is no tag head, or ignoring case, need to do a | 2507 * When there is no tag head, or ignoring case, need to do a |
2531 * linear search. | 2508 * linear search. |
2532 * When no "!_TAG_" is found, default to binary search. If | 2509 * When no "!_TAG_" is found, default to binary search. If |
2533 * the tag file isn't sorted, the second loop will find it. | 2510 * the tag file isn't sorted, the second loop will find it. |
2559 // Binary search won't work for ignoring case, use linear | 2536 // Binary search won't work for ignoring case, use linear |
2560 // search. | 2537 // search. |
2561 st->linear = TRUE; | 2538 st->linear = TRUE; |
2562 state = TS_LINEAR; | 2539 state = TS_LINEAR; |
2563 } | 2540 } |
2564 #else | 2541 |
2565 state = TS_LINEAR; | |
2566 #endif | |
2567 | |
2568 #ifdef FEAT_TAG_BINS | |
2569 // When starting a binary search, get the size of the file and | 2542 // When starting a binary search, get the size of the file and |
2570 // compute the first offset. | 2543 // compute the first offset. |
2571 if (state == TS_BINARY) | 2544 if (state == TS_BINARY) |
2572 { | 2545 { |
2573 if (vim_fseek(fp, 0L, SEEK_END) != 0) | 2546 if (vim_fseek(fp, 0L, SEEK_END) != 0) |
2589 search_info.curr_offset = 0; | 2562 search_info.curr_offset = 0; |
2590 search_info.high_char = 0xff; | 2563 search_info.high_char = 0xff; |
2591 } | 2564 } |
2592 continue; | 2565 continue; |
2593 } | 2566 } |
2594 #endif | |
2595 } | 2567 } |
2596 | 2568 |
2597 parse_line: | 2569 parse_line: |
2598 // When the line is too long the NUL will not be in the | 2570 // When the line is too long the NUL will not be in the |
2599 // last-but-one byte (see vim_fgets()). | 2571 // last-but-one byte (see vim_fgets()). |
2613 if (fp != NULL) | 2585 if (fp != NULL) |
2614 fclose(fp); | 2586 fclose(fp); |
2615 return FAIL; | 2587 return FAIL; |
2616 } | 2588 } |
2617 | 2589 |
2618 #ifdef FEAT_TAG_BINS | |
2619 if (state == TS_STEP_FORWARD) | 2590 if (state == TS_STEP_FORWARD) |
2620 // Seek to the same position to read the same line again | 2591 // Seek to the same position to read the same line again |
2621 vim_fseek(fp, search_info.curr_offset, SEEK_SET); | 2592 vim_fseek(fp, search_info.curr_offset, SEEK_SET); |
2622 // this will try the same thing again, make sure the offset is | 2593 // this will try the same thing again, make sure the offset is |
2623 // different | 2594 // different |
2624 search_info.curr_offset = 0; | 2595 search_info.curr_offset = 0; |
2625 #endif | |
2626 continue; | 2596 continue; |
2627 } | 2597 } |
2628 | 2598 |
2629 /* | 2599 /* |
2630 * Figure out where the different strings are in this line. | 2600 * Figure out where the different strings are in this line. |
2657 if (has_re && st->orgpat.headlen < cmplen) | 2627 if (has_re && st->orgpat.headlen < cmplen) |
2658 cmplen = st->orgpat.headlen; | 2628 cmplen = st->orgpat.headlen; |
2659 else if (state == TS_LINEAR && st->orgpat.headlen != cmplen) | 2629 else if (state == TS_LINEAR && st->orgpat.headlen != cmplen) |
2660 continue; | 2630 continue; |
2661 | 2631 |
2662 #ifdef FEAT_TAG_BINS | |
2663 if (state == TS_BINARY) | 2632 if (state == TS_BINARY) |
2664 { | 2633 { |
2665 /* | 2634 /* |
2666 * Simplistic check for unsorted tags file. | 2635 * Simplistic check for unsorted tags file. |
2667 */ | 2636 */ |
2748 else | 2717 else |
2749 continue; // before first match | 2718 continue; // before first match |
2750 } | 2719 } |
2751 } | 2720 } |
2752 else | 2721 else |
2753 #endif | |
2754 // skip this match if it can't match | 2722 // skip this match if it can't match |
2755 if (MB_STRNICMP(tagp.tagname, st->orgpat.head, cmplen) != 0) | 2723 if (MB_STRNICMP(tagp.tagname, st->orgpat.head, cmplen) != 0) |
2756 continue; | 2724 continue; |
2757 | 2725 |
2758 /* | 2726 /* |
2872 emacs_tags_incstack_free(); | 2840 emacs_tags_incstack_free(); |
2873 #endif | 2841 #endif |
2874 if (vimconv.vc_type != CONV_NONE) | 2842 if (vimconv.vc_type != CONV_NONE) |
2875 convert_setup(&vimconv, NULL, NULL); | 2843 convert_setup(&vimconv, NULL, NULL); |
2876 | 2844 |
2877 #ifdef FEAT_TAG_BINS | |
2878 tag_file_sorted = NUL; | 2845 tag_file_sorted = NUL; |
2879 if (sort_error) | 2846 if (sort_error) |
2880 { | 2847 { |
2881 semsg(_(e_tags_file_not_sorted_str), st->tag_fname); | 2848 semsg(_(e_tags_file_not_sorted_str), st->tag_fname); |
2882 sort_error = FALSE; | 2849 sort_error = FALSE; |
2883 } | 2850 } |
2884 #endif | |
2885 | 2851 |
2886 /* | 2852 /* |
2887 * Stop searching if sufficient tags have been found. | 2853 * Stop searching if sufficient tags have been found. |
2888 */ | 2854 */ |
2889 if (st->match_count >= st->mincount) | 2855 if (st->match_count >= st->mincount) |
2981 { | 2947 { |
2982 findtags_state_T st; | 2948 findtags_state_T st; |
2983 tagname_T tn; // info for get_tagfname() | 2949 tagname_T tn; // info for get_tagfname() |
2984 int first_file; // trying first tag file | 2950 int first_file; // trying first tag file |
2985 int retval = FAIL; // return value | 2951 int retval = FAIL; // return value |
2986 #ifdef FEAT_TAG_BINS | |
2987 int round; | 2952 int round; |
2988 #endif | |
2989 | 2953 |
2990 int save_emsg_off; | 2954 int save_emsg_off; |
2991 | 2955 |
2992 int help_save; | 2956 int help_save; |
2993 #ifdef FEAT_MULTI_LANG | 2957 #ifdef FEAT_MULTI_LANG |
2994 int i; | 2958 int i; |
2995 char_u *saved_pat = NULL; // copy of pat[] | 2959 char_u *saved_pat = NULL; // copy of pat[] |
2996 #endif | 2960 #endif |
2997 | 2961 |
2998 #ifdef FEAT_TAG_BINS | |
2999 int findall = (mincount == MAXCOL || mincount == TAG_MANY); | 2962 int findall = (mincount == MAXCOL || mincount == TAG_MANY); |
3000 // find all matching tags | 2963 // find all matching tags |
3001 #endif | |
3002 int has_re = (flags & TAG_REGEXP); // regexp used | 2964 int has_re = (flags & TAG_REGEXP); // regexp used |
3003 int noic = (flags & TAG_NOIC); | 2965 int noic = (flags & TAG_NOIC); |
3004 #ifdef FEAT_CSCOPE | 2966 #ifdef FEAT_CSCOPE |
3005 int use_cscope = (flags & TAG_CSCOPE); | 2967 int use_cscope = (flags & TAG_CSCOPE); |
3006 #endif | 2968 #endif |
3099 * string to look for, ignore case right away to avoid going though the | 3061 * string to look for, ignore case right away to avoid going though the |
3100 * tags files twice. | 3062 * tags files twice. |
3101 * When the tag file is case-fold sorted, it is either one or the other. | 3063 * When the tag file is case-fold sorted, it is either one or the other. |
3102 * Only ignore case when TAG_NOIC not used or 'ignorecase' set. | 3064 * Only ignore case when TAG_NOIC not used or 'ignorecase' set. |
3103 */ | 3065 */ |
3104 #ifdef FEAT_TAG_BINS | |
3105 st.orgpat.regmatch.rm_ic = ((p_ic || !noic) | 3066 st.orgpat.regmatch.rm_ic = ((p_ic || !noic) |
3106 && (findall || st.orgpat.headlen == 0 || !p_tbs)); | 3067 && (findall || st.orgpat.headlen == 0 || !p_tbs)); |
3107 for (round = 1; round <= 2; ++round) | 3068 for (round = 1; round <= 2; ++round) |
3108 { | 3069 { |
3109 st.linear = (st.orgpat.headlen == 0 || !p_tbs || round == 2); | 3070 st.linear = (st.orgpat.headlen == 0 || !p_tbs || round == 2); |
3110 #else | |
3111 st.orgpat.regmatch.rm_ic = (p_ic || !noic); | |
3112 #endif | |
3113 | 3071 |
3114 /* | 3072 /* |
3115 * Try tag file names from tags option one by one. | 3073 * Try tag file names from tags option one by one. |
3116 */ | 3074 */ |
3117 for (first_file = TRUE; | 3075 for (first_file = TRUE; |
3137 #ifdef FEAT_CSCOPE | 3095 #ifdef FEAT_CSCOPE |
3138 if (!use_cscope) | 3096 if (!use_cscope) |
3139 #endif | 3097 #endif |
3140 tagname_free(&tn); | 3098 tagname_free(&tn); |
3141 | 3099 |
3142 #ifdef FEAT_TAG_BINS | |
3143 // stop searching when already did a linear search, or when TAG_NOIC | 3100 // stop searching when already did a linear search, or when TAG_NOIC |
3144 // used, and 'ignorecase' not set or already did case-ignore search | 3101 // used, and 'ignorecase' not set or already did case-ignore search |
3145 if (st.stop_searching || st.linear || (!p_ic && noic) || | 3102 if (st.stop_searching || st.linear || (!p_ic && noic) || |
3146 st.orgpat.regmatch.rm_ic) | 3103 st.orgpat.regmatch.rm_ic) |
3147 break; | 3104 break; |
3151 # endif | 3108 # endif |
3152 | 3109 |
3153 // try another time while ignoring case | 3110 // try another time while ignoring case |
3154 st.orgpat.regmatch.rm_ic = TRUE; | 3111 st.orgpat.regmatch.rm_ic = TRUE; |
3155 } | 3112 } |
3156 #endif | |
3157 | 3113 |
3158 if (!st.stop_searching) | 3114 if (!st.stop_searching) |
3159 { | 3115 { |
3160 if (!st.did_open && verbose) // never opened any tags file | 3116 if (!st.did_open && verbose) // never opened any tags file |
3161 emsg(_(e_no_tags_file)); | 3117 emsg(_(e_no_tags_file)); |