1 /* vi:set ts=8 sts=4 sw=4 noet: 2 * 3 * VIM - Vi IMproved by Bram Moolenaar 4 * 5 * Do ":help uganda" in Vim to read copying and usage conditions. 6 * Do ":help credits" in Vim to see a list of people who contributed. 7 * See README.txt for an overview of the Vim source code. 8 */ 9 10 /* 11 * Code to handle tags and the tag stack 12 */ 13 14 #include "vim.h" 15 16 /* 17 * Structure to hold pointers to various items in a tag line. 18 */ 19 typedef struct tag_pointers 20 { 21 // filled in by parse_tag_line(): 22 char_u *tagname; // start of tag name (skip "file:") 23 char_u *tagname_end; // char after tag name 24 char_u *fname; // first char of file name 25 char_u *fname_end; // char after file name 26 char_u *command; // first char of command 27 // filled in by parse_match(): 28 char_u *command_end; // first char after command 29 char_u *tag_fname; // file name of the tags file. This is used 30 // when 'tr' is set. 31 #ifdef FEAT_EMACS_TAGS 32 int is_etag; // TRUE for emacs tag 33 #endif 34 char_u *tagkind; // "kind:" value 35 char_u *tagkind_end; // end of tagkind 36 char_u *user_data; // user_data string 37 char_u *user_data_end; // end of user_data 38 linenr_T tagline; // "line:" value 39 } tagptrs_T; 40 41 /* 42 * The matching tags are first stored in one of the hash tables. In 43 * which one depends on the priority of the match. 44 * ht_match[] is used to find duplicates, ga_match[] to keep them in sequence. 45 * At the end, all the matches from ga_match[] are concatenated, to make a list 46 * sorted on priority. 47 */ 48 #define MT_ST_CUR 0 // static match in current file 49 #define MT_GL_CUR 1 // global match in current file 50 #define MT_GL_OTH 2 // global match in other file 51 #define MT_ST_OTH 3 // static match in other file 52 #define MT_IC_OFF 4 // add for icase match 53 #define MT_RE_OFF 8 // add for regexp match 54 #define MT_MASK 7 // mask for printing priority 55 #define MT_COUNT 16 56 57 static char *mt_names[MT_COUNT/2] = 58 {"FSC", "F C", "F ", "FS ", " SC", " C", " ", " S "}; 59 60 #define NOTAGFILE 99 // return value for jumpto_tag 61 static char_u *nofile_fname = NULL; // fname for NOTAGFILE error 62 63 static void taglen_advance(int l); 64 65 static int jumpto_tag(char_u *lbuf, int forceit, int keep_help); 66 #ifdef FEAT_EMACS_TAGS 67 static int parse_tag_line(char_u *lbuf, int is_etag, tagptrs_T *tagp); 68 #else 69 static int parse_tag_line(char_u *lbuf, tagptrs_T *tagp); 70 #endif 71 static int test_for_static(tagptrs_T *); 72 static int parse_match(char_u *lbuf, tagptrs_T *tagp); 73 static char_u *tag_full_fname(tagptrs_T *tagp); 74 static char_u *expand_tag_fname(char_u *fname, char_u *tag_fname, int expand); 75 #ifdef FEAT_EMACS_TAGS 76 static int test_for_current(int, char_u *, char_u *, char_u *, char_u *); 77 #else 78 static int test_for_current(char_u *, char_u *, char_u *, char_u *); 79 #endif 80 static int find_extra(char_u **pp); 81 static void print_tag_list(int new_tag, int use_tagstack, int num_matches, char_u **matches); 82 #if defined(FEAT_QUICKFIX) && defined(FEAT_EVAL) 83 static int add_llist_tags(char_u *tag, int num_matches, char_u **matches); 84 #endif 85 static void tagstack_clear_entry(taggy_T *item); 86 87 static char_u *bottommsg = (char_u *)N_("E555: at bottom of tag stack"); 88 static char_u *topmsg = (char_u *)N_("E556: at top of tag stack"); 89 #ifdef FEAT_EVAL 90 static char_u *recurmsg = (char_u *)N_("E986: cannot modify the tag stack within tagfunc"); 91 static char_u *tfu_inv_ret_msg = (char_u *)N_("E987: invalid return value from tagfunc"); 92 #endif 93 94 static char_u *tagmatchname = NULL; // name of last used tag 95 96 #if defined(FEAT_QUICKFIX) 97 /* 98 * Tag for preview window is remembered separately, to avoid messing up the 99 * normal tagstack. 100 */ 101 static taggy_T ptag_entry = {NULL, {{0, 0, 0}, 0}, 0, 0, NULL}; 102 #endif 103 104 #ifdef FEAT_EVAL 105 static int tfu_in_use = FALSE; // disallow recursive call of tagfunc 106 #endif 107 108 // Used instead of NUL to separate tag fields in the growarrays. 109 #define TAG_SEP 0x02 110 111 /* 112 * Jump to tag; handling of tag commands and tag stack 113 * 114 * *tag != NUL: ":tag {tag}", jump to new tag, add to tag stack 115 * 116 * type == DT_TAG: ":tag [tag]", jump to newer position or same tag again 117 * type == DT_HELP: like DT_TAG, but don't use regexp. 118 * type == DT_POP: ":pop" or CTRL-T, jump to old position 119 * type == DT_NEXT: jump to next match of same tag 120 * type == DT_PREV: jump to previous match of same tag 121 * type == DT_FIRST: jump to first match of same tag 122 * type == DT_LAST: jump to last match of same tag 123 * type == DT_SELECT: ":tselect [tag]", select tag from a list of all matches 124 * type == DT_JUMP: ":tjump [tag]", jump to tag or select tag from a list 125 * type == DT_CSCOPE: use cscope to find the tag 126 * type == DT_LTAG: use location list for displaying tag matches 127 * type == DT_FREE: free cached matches 128 * 129 * for cscope, returns TRUE if we jumped to tag or aborted, FALSE otherwise 130 */ 131 int 132 do_tag( 133 char_u *tag, // tag (pattern) to jump to 134 int type, 135 int count, 136 int forceit, // :ta with ! 137 int verbose) // print "tag not found" message 138 { 139 taggy_T *tagstack = curwin->w_tagstack; 140 int tagstackidx = curwin->w_tagstackidx; 141 int tagstacklen = curwin->w_tagstacklen; 142 int cur_match = 0; 143 int cur_fnum = curbuf->b_fnum; 144 int oldtagstackidx = tagstackidx; 145 int prevtagstackidx = tagstackidx; 146 int prev_num_matches; 147 int new_tag = FALSE; 148 int i; 149 int ic; 150 int no_regexp = FALSE; 151 int error_cur_match = 0; 152 int save_pos = FALSE; 153 fmark_T saved_fmark; 154 #ifdef FEAT_CSCOPE 155 int jumped_to_tag = FALSE; 156 #endif 157 int new_num_matches; 158 char_u **new_matches; 159 int use_tagstack; 160 int skip_msg = FALSE; 161 char_u *buf_ffname = curbuf->b_ffname; // name to use for 162 // priority computation 163 int use_tfu = 1; 164 165 // remember the matches for the last used tag 166 static int num_matches = 0; 167 static int max_num_matches = 0; // limit used for match search 168 static char_u **matches = NULL; 169 static int flags; 170 171 #ifdef FEAT_EVAL 172 if (tfu_in_use) 173 { 174 emsg(_(recurmsg)); 175 return FALSE; 176 } 177 #endif 178 179 #ifdef EXITFREE 180 if (type == DT_FREE) 181 { 182 // remove the list of matches 183 FreeWild(num_matches, matches); 184 # ifdef FEAT_CSCOPE 185 cs_free_tags(); 186 # endif 187 num_matches = 0; 188 return FALSE; 189 } 190 #endif 191 192 if (type == DT_HELP) 193 { 194 type = DT_TAG; 195 no_regexp = TRUE; 196 use_tfu = 0; 197 } 198 199 prev_num_matches = num_matches; 200 free_string_option(nofile_fname); 201 nofile_fname = NULL; 202 203 CLEAR_POS(&saved_fmark.mark); // shutup gcc 4.0 204 saved_fmark.fnum = 0; 205 206 /* 207 * Don't add a tag to the tagstack if 'tagstack' has been reset. 208 */ 209 if ((!p_tgst && *tag != NUL)) 210 { 211 use_tagstack = FALSE; 212 new_tag = TRUE; 213 #if defined(FEAT_QUICKFIX) 214 if (g_do_tagpreview != 0) 215 { 216 tagstack_clear_entry(&ptag_entry); 217 if ((ptag_entry.tagname = vim_strsave(tag)) == NULL) 218 goto end_do_tag; 219 } 220 #endif 221 } 222 else 223 { 224 #if defined(FEAT_QUICKFIX) 225 if (g_do_tagpreview != 0) 226 use_tagstack = FALSE; 227 else 228 #endif 229 use_tagstack = TRUE; 230 231 // new pattern, add to the tag stack 232 if (*tag != NUL 233 && (type == DT_TAG || type == DT_SELECT || type == DT_JUMP 234 #ifdef FEAT_QUICKFIX 235 || type == DT_LTAG 236 #endif 237 #ifdef FEAT_CSCOPE 238 || type == DT_CSCOPE 239 #endif 240 )) 241 { 242 #if defined(FEAT_QUICKFIX) 243 if (g_do_tagpreview != 0) 244 { 245 if (ptag_entry.tagname != NULL 246 && STRCMP(ptag_entry.tagname, tag) == 0) 247 { 248 // Jumping to same tag: keep the current match, so that 249 // the CursorHold autocommand example works. 250 cur_match = ptag_entry.cur_match; 251 cur_fnum = ptag_entry.cur_fnum; 252 } 253 else 254 { 255 tagstack_clear_entry(&ptag_entry); 256 if ((ptag_entry.tagname = vim_strsave(tag)) == NULL) 257 goto end_do_tag; 258 } 259 } 260 else 261 #endif 262 { 263 /* 264 * If the last used entry is not at the top, delete all tag 265 * stack entries above it. 266 */ 267 while (tagstackidx < tagstacklen) 268 tagstack_clear_entry(&tagstack[--tagstacklen]); 269 270 // if the tagstack is full: remove oldest entry 271 if (++tagstacklen > TAGSTACKSIZE) 272 { 273 tagstacklen = TAGSTACKSIZE; 274 tagstack_clear_entry(&tagstack[0]); 275 for (i = 1; i < tagstacklen; ++i) 276 tagstack[i - 1] = tagstack[i]; 277 --tagstackidx; 278 } 279 280 /* 281 * put the tag name in the tag stack 282 */ 283 if ((tagstack[tagstackidx].tagname = vim_strsave(tag)) == NULL) 284 { 285 curwin->w_tagstacklen = tagstacklen - 1; 286 goto end_do_tag; 287 } 288 curwin->w_tagstacklen = tagstacklen; 289 290 save_pos = TRUE; // save the cursor position below 291 } 292 293 new_tag = TRUE; 294 } 295 else 296 { 297 if ( 298 #if defined(FEAT_QUICKFIX) 299 g_do_tagpreview != 0 ? ptag_entry.tagname == NULL : 300 #endif 301 tagstacklen == 0) 302 { 303 // empty stack 304 emsg(_(e_tagstack)); 305 goto end_do_tag; 306 } 307 308 if (type == DT_POP) // go to older position 309 { 310 #ifdef FEAT_FOLDING 311 int old_KeyTyped = KeyTyped; 312 #endif 313 if ((tagstackidx -= count) < 0) 314 { 315 emsg(_(bottommsg)); 316 if (tagstackidx + count == 0) 317 { 318 // We did [num]^T from the bottom of the stack 319 tagstackidx = 0; 320 goto end_do_tag; 321 } 322 // We weren't at the bottom of the stack, so jump all the 323 // way to the bottom now. 324 tagstackidx = 0; 325 } 326 else if (tagstackidx >= tagstacklen) // count == 0? 327 { 328 emsg(_(topmsg)); 329 goto end_do_tag; 330 } 331 332 // Make a copy of the fmark, autocommands may invalidate the 333 // tagstack before it's used. 334 saved_fmark = tagstack[tagstackidx].fmark; 335 if (saved_fmark.fnum != curbuf->b_fnum) 336 { 337 /* 338 * Jump to other file. If this fails (e.g. because the 339 * file was changed) keep original position in tag stack. 340 */ 341 if (buflist_getfile(saved_fmark.fnum, saved_fmark.mark.lnum, 342 GETF_SETMARK, forceit) == FAIL) 343 { 344 tagstackidx = oldtagstackidx; // back to old posn 345 goto end_do_tag; 346 } 347 // An BufReadPost autocommand may jump to the '" mark, but 348 // we don't what that here. 349 curwin->w_cursor.lnum = saved_fmark.mark.lnum; 350 } 351 else 352 { 353 setpcmark(); 354 curwin->w_cursor.lnum = saved_fmark.mark.lnum; 355 } 356 curwin->w_cursor.col = saved_fmark.mark.col; 357 curwin->w_set_curswant = TRUE; 358 check_cursor(); 359 #ifdef FEAT_FOLDING 360 if ((fdo_flags & FDO_TAG) && old_KeyTyped) 361 foldOpenCursor(); 362 #endif 363 364 // remove the old list of matches 365 FreeWild(num_matches, matches); 366 #ifdef FEAT_CSCOPE 367 cs_free_tags(); 368 #endif 369 num_matches = 0; 370 tag_freematch(); 371 goto end_do_tag; 372 } 373 374 if (type == DT_TAG 375 #if defined(FEAT_QUICKFIX) 376 || type == DT_LTAG 377 #endif 378 ) 379 { 380 #if defined(FEAT_QUICKFIX) 381 if (g_do_tagpreview != 0) 382 { 383 cur_match = ptag_entry.cur_match; 384 cur_fnum = ptag_entry.cur_fnum; 385 } 386 else 387 #endif 388 { 389 // ":tag" (no argument): go to newer pattern 390 save_pos = TRUE; // save the cursor position below 391 if ((tagstackidx += count - 1) >= tagstacklen) 392 { 393 /* 394 * Beyond the last one, just give an error message and 395 * go to the last one. Don't store the cursor 396 * position. 397 */ 398 tagstackidx = tagstacklen - 1; 399 emsg(_(topmsg)); 400 save_pos = FALSE; 401 } 402 else if (tagstackidx < 0) // must have been count == 0 403 { 404 emsg(_(bottommsg)); 405 tagstackidx = 0; 406 goto end_do_tag; 407 } 408 cur_match = tagstack[tagstackidx].cur_match; 409 cur_fnum = tagstack[tagstackidx].cur_fnum; 410 } 411 new_tag = TRUE; 412 } 413 else // go to other matching tag 414 { 415 // Save index for when selection is cancelled. 416 prevtagstackidx = tagstackidx; 417 418 #if defined(FEAT_QUICKFIX) 419 if (g_do_tagpreview != 0) 420 { 421 cur_match = ptag_entry.cur_match; 422 cur_fnum = ptag_entry.cur_fnum; 423 } 424 else 425 #endif 426 { 427 if (--tagstackidx < 0) 428 tagstackidx = 0; 429 cur_match = tagstack[tagstackidx].cur_match; 430 cur_fnum = tagstack[tagstackidx].cur_fnum; 431 } 432 switch (type) 433 { 434 case DT_FIRST: cur_match = count - 1; break; 435 case DT_SELECT: 436 case DT_JUMP: 437 #ifdef FEAT_CSCOPE 438 case DT_CSCOPE: 439 #endif 440 case DT_LAST: cur_match = MAXCOL - 1; break; 441 case DT_NEXT: cur_match += count; break; 442 case DT_PREV: cur_match -= count; break; 443 } 444 if (cur_match >= MAXCOL) 445 cur_match = MAXCOL - 1; 446 else if (cur_match < 0) 447 { 448 emsg(_("E425: Cannot go before first matching tag")); 449 skip_msg = TRUE; 450 cur_match = 0; 451 cur_fnum = curbuf->b_fnum; 452 } 453 } 454 } 455 456 #if defined(FEAT_QUICKFIX) 457 if (g_do_tagpreview != 0) 458 { 459 if (type != DT_SELECT && type != DT_JUMP) 460 { 461 ptag_entry.cur_match = cur_match; 462 ptag_entry.cur_fnum = cur_fnum; 463 } 464 } 465 else 466 #endif 467 { 468 /* 469 * For ":tag [arg]" or ":tselect" remember position before the jump. 470 */ 471 saved_fmark = tagstack[tagstackidx].fmark; 472 if (save_pos) 473 { 474 tagstack[tagstackidx].fmark.mark = curwin->w_cursor; 475 tagstack[tagstackidx].fmark.fnum = curbuf->b_fnum; 476 } 477 478 // Curwin will change in the call to jumpto_tag() if ":stag" was 479 // used or an autocommand jumps to another window; store value of 480 // tagstackidx now. 481 curwin->w_tagstackidx = tagstackidx; 482 if (type != DT_SELECT && type != DT_JUMP) 483 { 484 curwin->w_tagstack[tagstackidx].cur_match = cur_match; 485 curwin->w_tagstack[tagstackidx].cur_fnum = cur_fnum; 486 } 487 } 488 } 489 490 // When not using the current buffer get the name of buffer "cur_fnum". 491 // Makes sure that the tag order doesn't change when using a remembered 492 // position for "cur_match". 493 if (cur_fnum != curbuf->b_fnum) 494 { 495 buf_T *buf = buflist_findnr(cur_fnum); 496 497 if (buf != NULL) 498 buf_ffname = buf->b_ffname; 499 } 500 501 /* 502 * Repeat searching for tags, when a file has not been found. 503 */ 504 for (;;) 505 { 506 int other_name; 507 char_u *name; 508 509 /* 510 * When desired match not found yet, try to find it (and others). 511 */ 512 if (use_tagstack) 513 name = tagstack[tagstackidx].tagname; 514 #if defined(FEAT_QUICKFIX) 515 else if (g_do_tagpreview != 0) 516 name = ptag_entry.tagname; 517 #endif 518 else 519 name = tag; 520 other_name = (tagmatchname == NULL || STRCMP(tagmatchname, name) != 0); 521 if (new_tag 522 || (cur_match >= num_matches && max_num_matches != MAXCOL) 523 || other_name) 524 { 525 if (other_name) 526 { 527 vim_free(tagmatchname); 528 tagmatchname = vim_strsave(name); 529 } 530 531 if (type == DT_SELECT || type == DT_JUMP 532 #if defined(FEAT_QUICKFIX) 533 || type == DT_LTAG 534 #endif 535 ) 536 cur_match = MAXCOL - 1; 537 if (type == DT_TAG) 538 max_num_matches = MAXCOL; 539 else 540 max_num_matches = cur_match + 1; 541 542 // when the argument starts with '/', use it as a regexp 543 if (!no_regexp && *name == '/') 544 { 545 flags = TAG_REGEXP; 546 ++name; 547 } 548 else 549 flags = TAG_NOIC; 550 551 #ifdef FEAT_CSCOPE 552 if (type == DT_CSCOPE) 553 flags = TAG_CSCOPE; 554 #endif 555 if (verbose) 556 flags |= TAG_VERBOSE; 557 558 if (!use_tfu) 559 flags |= TAG_NO_TAGFUNC; 560 561 if (find_tags(name, &new_num_matches, &new_matches, flags, 562 max_num_matches, buf_ffname) == OK 563 && new_num_matches < max_num_matches) 564 max_num_matches = MAXCOL; // If less than max_num_matches 565 // found: all matches found. 566 567 // If there already were some matches for the same name, move them 568 // to the start. Avoids that the order changes when using 569 // ":tnext" and jumping to another file. 570 if (!new_tag && !other_name) 571 { 572 int j, k; 573 int idx = 0; 574 tagptrs_T tagp, tagp2; 575 576 // Find the position of each old match in the new list. Need 577 // to use parse_match() to find the tag line. 578 for (j = 0; j < num_matches; ++j) 579 { 580 parse_match(matches[j], &tagp); 581 for (i = idx; i < new_num_matches; ++i) 582 { 583 parse_match(new_matches[i], &tagp2); 584 if (STRCMP(tagp.tagname, tagp2.tagname) == 0) 585 { 586 char_u *p = new_matches[i]; 587 for (k = i; k > idx; --k) 588 new_matches[k] = new_matches[k - 1]; 589 new_matches[idx++] = p; 590 break; 591 } 592 } 593 } 594 } 595 FreeWild(num_matches, matches); 596 num_matches = new_num_matches; 597 matches = new_matches; 598 } 599 600 if (num_matches <= 0) 601 { 602 if (verbose) 603 semsg(_("E426: tag not found: %s"), name); 604 #if defined(FEAT_QUICKFIX) 605 g_do_tagpreview = 0; 606 #endif 607 } 608 else 609 { 610 int ask_for_selection = FALSE; 611 612 #ifdef FEAT_CSCOPE 613 if (type == DT_CSCOPE && num_matches > 1) 614 { 615 cs_print_tags(); 616 ask_for_selection = TRUE; 617 } 618 else 619 #endif 620 if (type == DT_TAG && *tag != NUL) 621 // If a count is supplied to the ":tag <name>" command, then 622 // jump to count'th matching tag. 623 cur_match = count > 0 ? count - 1 : 0; 624 else if (type == DT_SELECT || (type == DT_JUMP && num_matches > 1)) 625 { 626 print_tag_list(new_tag, use_tagstack, num_matches, matches); 627 ask_for_selection = TRUE; 628 } 629 #if defined(FEAT_QUICKFIX) && defined(FEAT_EVAL) 630 else if (type == DT_LTAG) 631 { 632 if (add_llist_tags(tag, num_matches, matches) == FAIL) 633 goto end_do_tag; 634 cur_match = 0; // Jump to the first tag 635 } 636 #endif 637 638 if (ask_for_selection == TRUE) 639 { 640 /* 641 * Ask to select a tag from the list. 642 */ 643 i = prompt_for_number(NULL); 644 if (i <= 0 || i > num_matches || got_int) 645 { 646 // no valid choice: don't change anything 647 if (use_tagstack) 648 { 649 tagstack[tagstackidx].fmark = saved_fmark; 650 tagstackidx = prevtagstackidx; 651 } 652 #ifdef FEAT_CSCOPE 653 cs_free_tags(); 654 jumped_to_tag = TRUE; 655 #endif 656 break; 657 } 658 cur_match = i - 1; 659 } 660 661 if (cur_match >= num_matches) 662 { 663 // Avoid giving this error when a file wasn't found and we're 664 // looking for a match in another file, which wasn't found. 665 // There will be an emsg("file doesn't exist") below then. 666 if ((type == DT_NEXT || type == DT_FIRST) 667 && nofile_fname == NULL) 668 { 669 if (num_matches == 1) 670 emsg(_("E427: There is only one matching tag")); 671 else 672 emsg(_("E428: Cannot go beyond last matching tag")); 673 skip_msg = TRUE; 674 } 675 cur_match = num_matches - 1; 676 } 677 if (use_tagstack) 678 { 679 tagptrs_T tagp; 680 681 tagstack[tagstackidx].cur_match = cur_match; 682 tagstack[tagstackidx].cur_fnum = cur_fnum; 683 684 // store user-provided data originating from tagfunc 685 if (use_tfu && parse_match(matches[cur_match], &tagp) == OK 686 && tagp.user_data) 687 { 688 VIM_CLEAR(tagstack[tagstackidx].user_data); 689 tagstack[tagstackidx].user_data = vim_strnsave( 690 tagp.user_data, tagp.user_data_end - tagp.user_data); 691 } 692 693 ++tagstackidx; 694 } 695 #if defined(FEAT_QUICKFIX) 696 else if (g_do_tagpreview != 0) 697 { 698 ptag_entry.cur_match = cur_match; 699 ptag_entry.cur_fnum = cur_fnum; 700 } 701 #endif 702 703 /* 704 * Only when going to try the next match, report that the previous 705 * file didn't exist. Otherwise an emsg() is given below. 706 */ 707 if (nofile_fname != NULL && error_cur_match != cur_match) 708 smsg(_("File \"%s\" does not exist"), nofile_fname); 709 710 711 ic = (matches[cur_match][0] & MT_IC_OFF); 712 if (type != DT_TAG && type != DT_SELECT && type != DT_JUMP 713 #ifdef FEAT_CSCOPE 714 && type != DT_CSCOPE 715 #endif 716 && (num_matches > 1 || ic) 717 && !skip_msg) 718 { 719 // Give an indication of the number of matching tags 720 sprintf((char *)IObuff, _("tag %d of %d%s"), 721 cur_match + 1, 722 num_matches, 723 max_num_matches != MAXCOL ? _(" or more") : ""); 724 if (ic) 725 STRCAT(IObuff, _(" Using tag with different case!")); 726 if ((num_matches > prev_num_matches || new_tag) 727 && num_matches > 1) 728 { 729 if (ic) 730 msg_attr((char *)IObuff, HL_ATTR(HLF_W)); 731 else 732 msg((char *)IObuff); 733 msg_scroll = TRUE; // don't overwrite this message 734 } 735 else 736 give_warning(IObuff, ic); 737 if (ic && !msg_scrolled && msg_silent == 0) 738 { 739 out_flush(); 740 ui_delay(1007L, TRUE); 741 } 742 } 743 744 #if defined(FEAT_EVAL) 745 // Let the SwapExists event know what tag we are jumping to. 746 vim_snprintf((char *)IObuff, IOSIZE, ":ta %s\r", name); 747 set_vim_var_string(VV_SWAPCOMMAND, IObuff, -1); 748 #endif 749 750 /* 751 * Jump to the desired match. 752 */ 753 i = jumpto_tag(matches[cur_match], forceit, type != DT_CSCOPE); 754 755 #if defined(FEAT_EVAL) 756 set_vim_var_string(VV_SWAPCOMMAND, NULL, -1); 757 #endif 758 759 if (i == NOTAGFILE) 760 { 761 // File not found: try again with another matching tag 762 if ((type == DT_PREV && cur_match > 0) 763 || ((type == DT_TAG || type == DT_NEXT 764 || type == DT_FIRST) 765 && (max_num_matches != MAXCOL 766 || cur_match < num_matches - 1))) 767 { 768 error_cur_match = cur_match; 769 if (use_tagstack) 770 --tagstackidx; 771 if (type == DT_PREV) 772 --cur_match; 773 else 774 { 775 type = DT_NEXT; 776 ++cur_match; 777 } 778 continue; 779 } 780 semsg(_("E429: File \"%s\" does not exist"), nofile_fname); 781 } 782 else 783 { 784 // We may have jumped to another window, check that 785 // tagstackidx is still valid. 786 if (use_tagstack && tagstackidx > curwin->w_tagstacklen) 787 tagstackidx = curwin->w_tagstackidx; 788 #ifdef FEAT_CSCOPE 789 jumped_to_tag = TRUE; 790 #endif 791 } 792 } 793 break; 794 } 795 796 end_do_tag: 797 // Only store the new index when using the tagstack and it's valid. 798 if (use_tagstack && tagstackidx <= curwin->w_tagstacklen) 799 curwin->w_tagstackidx = tagstackidx; 800 postponed_split = 0; // don't split next time 801 # ifdef FEAT_QUICKFIX 802 g_do_tagpreview = 0; // don't do tag preview next time 803 # endif 804 805 #ifdef FEAT_CSCOPE 806 return jumped_to_tag; 807 #else 808 return FALSE; 809 #endif 810 } 811 812 /* 813 * List all the matching tags. 814 */ 815 static void 816 print_tag_list( 817 int new_tag, 818 int use_tagstack, 819 int num_matches, 820 char_u **matches) 821 { 822 taggy_T *tagstack = curwin->w_tagstack; 823 int tagstackidx = curwin->w_tagstackidx; 824 int i; 825 char_u *p; 826 char_u *command_end; 827 tagptrs_T tagp; 828 int taglen; 829 int attr; 830 831 /* 832 * Assume that the first match indicates how long the tags can 833 * be, and align the file names to that. 834 */ 835 parse_match(matches[0], &tagp); 836 taglen = (int)(tagp.tagname_end - tagp.tagname + 2); 837 if (taglen < 18) 838 taglen = 18; 839 if (taglen > Columns - 25) 840 taglen = MAXCOL; 841 if (msg_col == 0) 842 msg_didout = FALSE; // overwrite previous message 843 msg_start(); 844 msg_puts_attr(_(" # pri kind tag"), HL_ATTR(HLF_T)); 845 msg_clr_eos(); 846 taglen_advance(taglen); 847 msg_puts_attr(_("file\n"), HL_ATTR(HLF_T)); 848 849 for (i = 0; i < num_matches && !got_int; ++i) 850 { 851 parse_match(matches[i], &tagp); 852 if (!new_tag && ( 853 #if defined(FEAT_QUICKFIX) 854 (g_do_tagpreview != 0 855 && i == ptag_entry.cur_match) || 856 #endif 857 (use_tagstack 858 && i == tagstack[tagstackidx].cur_match))) 859 *IObuff = '>'; 860 else 861 *IObuff = ' '; 862 vim_snprintf((char *)IObuff + 1, IOSIZE - 1, 863 "%2d %s ", i + 1, 864 mt_names[matches[i][0] & MT_MASK]); 865 msg_puts((char *)IObuff); 866 if (tagp.tagkind != NULL) 867 msg_outtrans_len(tagp.tagkind, 868 (int)(tagp.tagkind_end - tagp.tagkind)); 869 msg_advance(13); 870 msg_outtrans_len_attr(tagp.tagname, 871 (int)(tagp.tagname_end - tagp.tagname), 872 HL_ATTR(HLF_T)); 873 msg_putchar(' '); 874 taglen_advance(taglen); 875 876 // Find out the actual file name. If it is long, truncate 877 // it and put "..." in the middle 878 p = tag_full_fname(&tagp); 879 if (p != NULL) 880 { 881 msg_outtrans_long_attr(p, HL_ATTR(HLF_D)); 882 vim_free(p); 883 } 884 if (msg_col > 0) 885 msg_putchar('\n'); 886 if (got_int) 887 break; 888 msg_advance(15); 889 890 // print any extra fields 891 command_end = tagp.command_end; 892 if (command_end != NULL) 893 { 894 p = command_end + 3; 895 while (*p && *p != '\r' && *p != '\n') 896 { 897 while (*p == TAB) 898 ++p; 899 900 // skip "file:" without a value (static tag) 901 if (STRNCMP(p, "file:", 5) == 0 902 && vim_isspace(p[5])) 903 { 904 p += 5; 905 continue; 906 } 907 // skip "kind:<kind>" and "<kind>" 908 if (p == tagp.tagkind 909 || (p + 5 == tagp.tagkind 910 && STRNCMP(p, "kind:", 5) == 0)) 911 { 912 p = tagp.tagkind_end; 913 continue; 914 } 915 // print all other extra fields 916 attr = HL_ATTR(HLF_CM); 917 while (*p && *p != '\r' && *p != '\n') 918 { 919 if (msg_col + ptr2cells(p) >= Columns) 920 { 921 msg_putchar('\n'); 922 if (got_int) 923 break; 924 msg_advance(15); 925 } 926 p = msg_outtrans_one(p, attr); 927 if (*p == TAB) 928 { 929 msg_puts_attr(" ", attr); 930 break; 931 } 932 if (*p == ':') 933 attr = 0; 934 } 935 } 936 if (msg_col > 15) 937 { 938 msg_putchar('\n'); 939 if (got_int) 940 break; 941 msg_advance(15); 942 } 943 } 944 else 945 { 946 for (p = tagp.command; 947 *p && *p != '\r' && *p != '\n'; ++p) 948 ; 949 command_end = p; 950 } 951 952 // Put the info (in several lines) at column 15. 953 // Don't display "/^" and "?^". 954 p = tagp.command; 955 if (*p == '/' || *p == '?') 956 { 957 ++p; 958 if (*p == '^') 959 ++p; 960 } 961 // Remove leading whitespace from pattern 962 while (p != command_end && vim_isspace(*p)) 963 ++p; 964 965 while (p != command_end) 966 { 967 if (msg_col + (*p == TAB ? 1 : ptr2cells(p)) > Columns) 968 msg_putchar('\n'); 969 if (got_int) 970 break; 971 msg_advance(15); 972 973 // skip backslash used for escaping a command char or 974 // a backslash 975 if (*p == '\\' && (*(p + 1) == *tagp.command 976 || *(p + 1) == '\\')) 977 ++p; 978 979 if (*p == TAB) 980 { 981 msg_putchar(' '); 982 ++p; 983 } 984 else 985 p = msg_outtrans_one(p, 0); 986 987 // don't display the "$/;\"" and "$?;\"" 988 if (p == command_end - 2 && *p == '$' 989 && *(p + 1) == *tagp.command) 990 break; 991 // don't display matching '/' or '?' 992 if (p == command_end - 1 && *p == *tagp.command 993 && (*p == '/' || *p == '?')) 994 break; 995 } 996 if (msg_col) 997 msg_putchar('\n'); 998 ui_breakcheck(); 999 } 1000 if (got_int) 1001 got_int = FALSE; // only stop the listing 1002 } 1003 1004 #if defined(FEAT_QUICKFIX) && defined(FEAT_EVAL) 1005 /* 1006 * Add the matching tags to the location list for the current 1007 * window. 1008 */ 1009 static int 1010 add_llist_tags( 1011 char_u *tag, 1012 int num_matches, 1013 char_u **matches) 1014 { 1015 list_T *list; 1016 char_u tag_name[128 + 1]; 1017 char_u *fname; 1018 char_u *cmd; 1019 int i; 1020 char_u *p; 1021 tagptrs_T tagp; 1022 1023 fname = alloc(MAXPATHL + 1); 1024 cmd = alloc(CMDBUFFSIZE + 1); 1025 list = list_alloc(); 1026 if (list == NULL || fname == NULL || cmd == NULL) 1027 { 1028 vim_free(cmd); 1029 vim_free(fname); 1030 if (list != NULL) 1031 list_free(list); 1032 return FAIL; 1033 } 1034 1035 for (i = 0; i < num_matches; ++i) 1036 { 1037 int len, cmd_len; 1038 long lnum; 1039 dict_T *dict; 1040 1041 parse_match(matches[i], &tagp); 1042 1043 // Save the tag name 1044 len = (int)(tagp.tagname_end - tagp.tagname); 1045 if (len > 128) 1046 len = 128; 1047 vim_strncpy(tag_name, tagp.tagname, len); 1048 tag_name[len] = NUL; 1049 1050 // Save the tag file name 1051 p = tag_full_fname(&tagp); 1052 if (p == NULL) 1053 continue; 1054 vim_strncpy(fname, p, MAXPATHL); 1055 vim_free(p); 1056 1057 // Get the line number or the search pattern used to locate 1058 // the tag. 1059 lnum = 0; 1060 if (isdigit(*tagp.command)) 1061 // Line number is used to locate the tag 1062 lnum = atol((char *)tagp.command); 1063 else 1064 { 1065 char_u *cmd_start, *cmd_end; 1066 1067 // Search pattern is used to locate the tag 1068 1069 // Locate the end of the command 1070 cmd_start = tagp.command; 1071 cmd_end = tagp.command_end; 1072 if (cmd_end == NULL) 1073 { 1074 for (p = tagp.command; 1075 *p && *p != '\r' && *p != '\n'; ++p) 1076 ; 1077 cmd_end = p; 1078 } 1079 1080 // Now, cmd_end points to the character after the 1081 // command. Adjust it to point to the last 1082 // character of the command. 1083 cmd_end--; 1084 1085 // Skip the '/' and '?' characters at the 1086 // beginning and end of the search pattern. 1087 if (*cmd_start == '/' || *cmd_start == '?') 1088 cmd_start++; 1089 1090 if (*cmd_end == '/' || *cmd_end == '?') 1091 cmd_end--; 1092 1093 len = 0; 1094 cmd[0] = NUL; 1095 1096 // If "^" is present in the tag search pattern, then 1097 // copy it first. 1098 if (*cmd_start == '^') 1099 { 1100 STRCPY(cmd, "^"); 1101 cmd_start++; 1102 len++; 1103 } 1104 1105 // Precede the tag pattern with \V to make it very 1106 // nomagic. 1107 STRCAT(cmd, "\\V"); 1108 len += 2; 1109 1110 cmd_len = (int)(cmd_end - cmd_start + 1); 1111 if (cmd_len > (CMDBUFFSIZE - 5)) 1112 cmd_len = CMDBUFFSIZE - 5; 1113 STRNCAT(cmd, cmd_start, cmd_len); 1114 len += cmd_len; 1115 1116 if (cmd[len - 1] == '$') 1117 { 1118 // Replace '$' at the end of the search pattern 1119 // with '\$' 1120 cmd[len - 1] = '\\'; 1121 cmd[len] = '$'; 1122 len++; 1123 } 1124 1125 cmd[len] = NUL; 1126 } 1127 1128 if ((dict = dict_alloc()) == NULL) 1129 continue; 1130 if (list_append_dict(list, dict) == FAIL) 1131 { 1132 vim_free(dict); 1133 continue; 1134 } 1135 1136 dict_add_string(dict, "text", tag_name); 1137 dict_add_string(dict, "filename", fname); 1138 dict_add_number(dict, "lnum", lnum); 1139 if (lnum == 0) 1140 dict_add_string(dict, "pattern", cmd); 1141 } 1142 1143 vim_snprintf((char *)IObuff, IOSIZE, "ltag %s", tag); 1144 set_errorlist(curwin, list, ' ', IObuff, NULL); 1145 1146 list_free(list); 1147 vim_free(fname); 1148 vim_free(cmd); 1149 1150 return OK; 1151 } 1152 #endif 1153 1154 /* 1155 * Free cached tags. 1156 */ 1157 void 1158 tag_freematch(void) 1159 { 1160 VIM_CLEAR(tagmatchname); 1161 } 1162 1163 static void 1164 taglen_advance(int l) 1165 { 1166 if (l == MAXCOL) 1167 { 1168 msg_putchar('\n'); 1169 msg_advance(24); 1170 } 1171 else 1172 msg_advance(13 + l); 1173 } 1174 1175 /* 1176 * Print the tag stack 1177 */ 1178 void 1179 do_tags(exarg_T *eap UNUSED) 1180 { 1181 int i; 1182 char_u *name; 1183 taggy_T *tagstack = curwin->w_tagstack; 1184 int tagstackidx = curwin->w_tagstackidx; 1185 int tagstacklen = curwin->w_tagstacklen; 1186 1187 // Highlight title 1188 msg_puts_title(_("\n # TO tag FROM line in file/text")); 1189 for (i = 0; i < tagstacklen; ++i) 1190 { 1191 if (tagstack[i].tagname != NULL) 1192 { 1193 name = fm_getname(&(tagstack[i].fmark), 30); 1194 if (name == NULL) // file name not available 1195 continue; 1196 1197 msg_putchar('\n'); 1198 vim_snprintf((char *)IObuff, IOSIZE, "%c%2d %2d %-15s %5ld ", 1199 i == tagstackidx ? '>' : ' ', 1200 i + 1, 1201 tagstack[i].cur_match + 1, 1202 tagstack[i].tagname, 1203 tagstack[i].fmark.mark.lnum); 1204 msg_outtrans(IObuff); 1205 msg_outtrans_attr(name, tagstack[i].fmark.fnum == curbuf->b_fnum 1206 ? HL_ATTR(HLF_D) : 0); 1207 vim_free(name); 1208 } 1209 out_flush(); // show one line at a time 1210 } 1211 if (tagstackidx == tagstacklen) // idx at top of stack 1212 msg_puts("\n>"); 1213 } 1214 1215 #ifdef FEAT_TAG_BINS 1216 /* 1217 * Compare two strings, for length "len", ignoring case the ASCII way. 1218 * return 0 for match, < 0 for smaller, > 0 for bigger 1219 * Make sure case is folded to uppercase in comparison (like for 'sort -f') 1220 */ 1221 static int 1222 tag_strnicmp(char_u *s1, char_u *s2, size_t len) 1223 { 1224 int i; 1225 1226 while (len > 0) 1227 { 1228 i = (int)TOUPPER_ASC(*s1) - (int)TOUPPER_ASC(*s2); 1229 if (i != 0) 1230 return i; // this character different 1231 if (*s1 == NUL) 1232 break; // strings match until NUL 1233 ++s1; 1234 ++s2; 1235 --len; 1236 } 1237 return 0; // strings match 1238 } 1239 #endif 1240 1241 /* 1242 * Structure to hold info about the tag pattern being used. 1243 */ 1244 typedef struct 1245 { 1246 char_u *pat; // the pattern 1247 int len; // length of pat[] 1248 char_u *head; // start of pattern head 1249 int headlen; // length of head[] 1250 regmatch_T regmatch; // regexp program, may be NULL 1251 } pat_T; 1252 1253 /* 1254 * Extract info from the tag search pattern "pats->pat". 1255 */ 1256 static void 1257 prepare_pats(pat_T *pats, int has_re) 1258 { 1259 pats->head = pats->pat; 1260 pats->headlen = pats->len; 1261 if (has_re) 1262 { 1263 // When the pattern starts with '^' or "\\<", binary searching can be 1264 // used (much faster). 1265 if (pats->pat[0] == '^') 1266 pats->head = pats->pat + 1; 1267 else if (pats->pat[0] == '\\' && pats->pat[1] == '<') 1268 pats->head = pats->pat + 2; 1269 if (pats->head == pats->pat) 1270 pats->headlen = 0; 1271 else 1272 for (pats->headlen = 0; pats->head[pats->headlen] != NUL; 1273 ++pats->headlen) 1274 if (vim_strchr((char_u *)(p_magic ? ".[~*\\$" : "\\$"), 1275 pats->head[pats->headlen]) != NULL) 1276 break; 1277 if (p_tl != 0 && pats->headlen > p_tl) // adjust for 'taglength' 1278 pats->headlen = p_tl; 1279 } 1280 1281 if (has_re) 1282 pats->regmatch.regprog = vim_regcomp(pats->pat, p_magic ? RE_MAGIC : 0); 1283 else 1284 pats->regmatch.regprog = NULL; 1285 } 1286 1287 #ifdef FEAT_EVAL 1288 /* 1289 * Call the user-defined function to generate a list of tags used by 1290 * find_tags(). 1291 * 1292 * Return OK if at least 1 tag has been successfully found, 1293 * NOTDONE if the function returns v:null, and FAIL otherwise. 1294 */ 1295 static int 1296 find_tagfunc_tags( 1297 char_u *pat, // pattern supplied to the user-defined function 1298 garray_T *ga, // the tags will be placed here 1299 int *match_count, // here the number of tags found will be placed 1300 int flags, // flags from find_tags (TAG_*) 1301 char_u *buf_ffname) // name of buffer for priority 1302 { 1303 pos_T save_pos; 1304 list_T *taglist; 1305 listitem_T *item; 1306 int ntags = 0; 1307 int result = FAIL; 1308 typval_T args[4]; 1309 typval_T rettv; 1310 char_u flagString[3]; 1311 dict_T *d; 1312 taggy_T *tag = &curwin->w_tagstack[curwin->w_tagstackidx]; 1313 1314 if (*curbuf->b_p_tfu == NUL) 1315 return FAIL; 1316 1317 args[0].v_type = VAR_STRING; 1318 args[0].vval.v_string = pat; 1319 args[1].v_type = VAR_STRING; 1320 args[1].vval.v_string = flagString; 1321 1322 // create 'info' dict argument 1323 if ((d = dict_alloc_lock(VAR_FIXED)) == NULL) 1324 return FAIL; 1325 if (tag->user_data != NULL) 1326 dict_add_string(d, "user_data", tag->user_data); 1327 if (buf_ffname != NULL) 1328 dict_add_string(d, "buf_ffname", buf_ffname); 1329 1330 ++d->dv_refcount; 1331 args[2].v_type = VAR_DICT; 1332 args[2].vval.v_dict = d; 1333 1334 args[3].v_type = VAR_UNKNOWN; 1335 1336 vim_snprintf((char *)flagString, sizeof(flagString), 1337 "%s%s", 1338 g_tag_at_cursor ? "c": "", 1339 flags & TAG_INS_COMP ? "i": ""); 1340 1341 save_pos = curwin->w_cursor; 1342 result = call_vim_function(curbuf->b_p_tfu, 3, args, &rettv); 1343 curwin->w_cursor = save_pos; // restore the cursor position 1344 --d->dv_refcount; 1345 1346 if (result == FAIL) 1347 return FAIL; 1348 if (rettv.v_type == VAR_SPECIAL && rettv.vval.v_number == VVAL_NULL) 1349 { 1350 clear_tv(&rettv); 1351 return NOTDONE; 1352 } 1353 if (rettv.v_type != VAR_LIST || !rettv.vval.v_list) 1354 { 1355 clear_tv(&rettv); 1356 emsg(_(tfu_inv_ret_msg)); 1357 return FAIL; 1358 } 1359 taglist = rettv.vval.v_list; 1360 1361 FOR_ALL_LIST_ITEMS(taglist, item) 1362 { 1363 char_u *mfp; 1364 char_u *res_name, *res_fname, *res_cmd, *res_kind; 1365 int len; 1366 dict_iterator_T iter; 1367 char_u *dict_key; 1368 typval_T *tv; 1369 int has_extra = 0; 1370 int name_only = flags & TAG_NAMES; 1371 1372 if (item->li_tv.v_type != VAR_DICT) 1373 { 1374 emsg(_(tfu_inv_ret_msg)); 1375 break; 1376 } 1377 1378 #ifdef FEAT_EMACS_TAGS 1379 len = 3; 1380 #else 1381 len = 2; 1382 #endif 1383 res_name = NULL; 1384 res_fname = NULL; 1385 res_cmd = NULL; 1386 res_kind = NULL; 1387 1388 dict_iterate_start(&item->li_tv, &iter); 1389 while (NULL != (dict_key = dict_iterate_next(&iter, &tv))) 1390 { 1391 if (tv->v_type != VAR_STRING || tv->vval.v_string == NULL) 1392 continue; 1393 1394 len += (int)STRLEN(tv->vval.v_string) + 1; // Space for "\tVALUE" 1395 if (!STRCMP(dict_key, "name")) 1396 { 1397 res_name = tv->vval.v_string; 1398 continue; 1399 } 1400 if (!STRCMP(dict_key, "filename")) 1401 { 1402 res_fname = tv->vval.v_string; 1403 continue; 1404 } 1405 if (!STRCMP(dict_key, "cmd")) 1406 { 1407 res_cmd = tv->vval.v_string; 1408 continue; 1409 } 1410 has_extra = 1; 1411 if (!STRCMP(dict_key, "kind")) 1412 { 1413 res_kind = tv->vval.v_string; 1414 continue; 1415 } 1416 // Other elements will be stored as "\tKEY:VALUE" 1417 // Allocate space for the key and the colon 1418 len += (int)STRLEN(dict_key) + 1; 1419 } 1420 1421 if (has_extra) 1422 len += 2; // need space for ;" 1423 1424 if (!res_name || !res_fname || !res_cmd) 1425 { 1426 emsg(_(tfu_inv_ret_msg)); 1427 break; 1428 } 1429 1430 if (name_only) 1431 mfp = vim_strsave(res_name); 1432 else 1433 mfp = alloc(sizeof(char_u) + len + 1); 1434 1435 if (mfp == NULL) 1436 continue; 1437 1438 if (!name_only) 1439 { 1440 char_u *p = mfp; 1441 1442 *p++ = MT_GL_OTH + 1; // mtt 1443 *p++ = TAG_SEP; // no tag file name 1444 #ifdef FEAT_EMACS_TAGS 1445 *p++ = TAG_SEP; 1446 #endif 1447 1448 STRCPY(p, res_name); 1449 p += STRLEN(p); 1450 1451 *p++ = TAB; 1452 STRCPY(p, res_fname); 1453 p += STRLEN(p); 1454 1455 *p++ = TAB; 1456 STRCPY(p, res_cmd); 1457 p += STRLEN(p); 1458 1459 if (has_extra) 1460 { 1461 STRCPY(p, ";\""); 1462 p += STRLEN(p); 1463 1464 if (res_kind) 1465 { 1466 *p++ = TAB; 1467 STRCPY(p, res_kind); 1468 p += STRLEN(p); 1469 } 1470 1471 dict_iterate_start(&item->li_tv, &iter); 1472 while (NULL != (dict_key = dict_iterate_next(&iter, &tv))) 1473 { 1474 if (tv->v_type != VAR_STRING || tv->vval.v_string == NULL) 1475 continue; 1476 1477 if (!STRCMP(dict_key, "name")) 1478 continue; 1479 if (!STRCMP(dict_key, "filename")) 1480 continue; 1481 if (!STRCMP(dict_key, "cmd")) 1482 continue; 1483 if (!STRCMP(dict_key, "kind")) 1484 continue; 1485 1486 *p++ = TAB; 1487 STRCPY(p, dict_key); 1488 p += STRLEN(p); 1489 STRCPY(p, ":"); 1490 p += STRLEN(p); 1491 STRCPY(p, tv->vval.v_string); 1492 p += STRLEN(p); 1493 } 1494 } 1495 } 1496 1497 // Add all matches because tagfunc should do filtering. 1498 if (ga_grow(ga, 1) == OK) 1499 { 1500 ((char_u **)(ga->ga_data))[ga->ga_len++] = mfp; 1501 ++ntags; 1502 result = OK; 1503 } 1504 else 1505 { 1506 vim_free(mfp); 1507 break; 1508 } 1509 } 1510 1511 clear_tv(&rettv); 1512 1513 *match_count = ntags; 1514 return result; 1515 } 1516 #endif 1517 1518 /* 1519 * find_tags() - search for tags in tags files 1520 * 1521 * Return FAIL if search completely failed (*num_matches will be 0, *matchesp 1522 * will be NULL), OK otherwise. 1523 * 1524 * There is a priority in which type of tag is recognized. 1525 * 1526 * 6. A static or global tag with a full matching tag for the current file. 1527 * 5. A global tag with a full matching tag for another file. 1528 * 4. A static tag with a full matching tag for another file. 1529 * 3. A static or global tag with an ignore-case matching tag for the 1530 * current file. 1531 * 2. A global tag with an ignore-case matching tag for another file. 1532 * 1. A static tag with an ignore-case matching tag for another file. 1533 * 1534 * Tags in an emacs-style tags file are always global. 1535 * 1536 * flags: 1537 * TAG_HELP only search for help tags 1538 * TAG_NAMES only return name of tag 1539 * TAG_REGEXP use "pat" as a regexp 1540 * TAG_NOIC don't always ignore case 1541 * TAG_KEEP_LANG keep language 1542 * TAG_CSCOPE use cscope results for tags 1543 * TAG_NO_TAGFUNC do not call the 'tagfunc' function 1544 */ 1545 int 1546 find_tags( 1547 char_u *pat, // pattern to search for 1548 int *num_matches, // return: number of matches found 1549 char_u ***matchesp, // return: array of matches found 1550 int flags, 1551 int mincount, // MAXCOL: find all matches 1552 // other: minimal number of matches 1553 char_u *buf_ffname) // name of buffer for priority 1554 { 1555 FILE *fp; 1556 char_u *lbuf; // line buffer 1557 int lbuf_size = LSIZE; // length of lbuf 1558 char_u *tag_fname; // name of tag file 1559 tagname_T tn; // info for get_tagfname() 1560 int first_file; // trying first tag file 1561 tagptrs_T tagp; 1562 int did_open = FALSE; // did open a tag file 1563 int stop_searching = FALSE; // stop when match found or error 1564 int retval = FAIL; // return value 1565 int is_static; // current tag line is static 1566 int is_current; // file name matches 1567 int eof = FALSE; // found end-of-file 1568 char_u *p; 1569 char_u *s; 1570 int i; 1571 #ifdef FEAT_TAG_BINS 1572 int tag_file_sorted = NUL; // !_TAG_FILE_SORTED value 1573 struct tag_search_info // Binary search file offsets 1574 { 1575 off_T low_offset; // offset for first char of first line that 1576 // could match 1577 off_T high_offset; // offset of char after last line that could 1578 // match 1579 off_T curr_offset; // Current file offset in search range 1580 off_T curr_offset_used; // curr_offset used when skipping back 1581 off_T match_offset; // Where the binary search found a tag 1582 int low_char; // first char at low_offset 1583 int high_char; // first char at high_offset 1584 } search_info; 1585 off_T filesize; 1586 int tagcmp; 1587 off_T offset; 1588 int round; 1589 #endif 1590 enum 1591 { 1592 TS_START, // at start of file 1593 TS_LINEAR // linear searching forward, till EOF 1594 #ifdef FEAT_TAG_BINS 1595 , TS_BINARY, // binary searching 1596 TS_SKIP_BACK, // skipping backwards 1597 TS_STEP_FORWARD // stepping forwards 1598 #endif 1599 } state; // Current search state 1600 1601 int cmplen; 1602 int match; // matches 1603 int match_no_ic = 0;// matches with rm_ic == FALSE 1604 int match_re; // match with regexp 1605 int matchoff = 0; 1606 int save_emsg_off; 1607 1608 #ifdef FEAT_EMACS_TAGS 1609 /* 1610 * Stack for included emacs-tags file. 1611 * It has a fixed size, to truncate cyclic includes. jw 1612 */ 1613 # define INCSTACK_SIZE 42 1614 struct 1615 { 1616 FILE *fp; 1617 char_u *etag_fname; 1618 } incstack[INCSTACK_SIZE]; 1619 1620 int incstack_idx = 0; // index in incstack 1621 char_u *ebuf; // additional buffer for etag fname 1622 int is_etag; // current file is emaces style 1623 #endif 1624 1625 char_u *mfp; 1626 garray_T ga_match[MT_COUNT]; // stores matches in sequence 1627 hashtab_T ht_match[MT_COUNT]; // stores matches by key 1628 hash_T hash = 0; 1629 int match_count = 0; // number of matches found 1630 char_u **matches; 1631 int mtt; 1632 int help_save; 1633 #ifdef FEAT_MULTI_LANG 1634 int help_pri = 0; 1635 char_u *help_lang_find = NULL; // lang to be found 1636 char_u help_lang[3]; // lang of current tags file 1637 char_u *saved_pat = NULL; // copy of pat[] 1638 int is_txt = FALSE; // flag of file extension 1639 #endif 1640 1641 pat_T orgpat; // holds unconverted pattern info 1642 vimconv_T vimconv; 1643 1644 #ifdef FEAT_TAG_BINS 1645 int findall = (mincount == MAXCOL || mincount == TAG_MANY); 1646 // find all matching tags 1647 int sort_error = FALSE; // tags file not sorted 1648 int linear; // do a linear search 1649 int sortic = FALSE; // tag file sorted in nocase 1650 #endif 1651 int line_error = FALSE; // syntax error 1652 int has_re = (flags & TAG_REGEXP); // regexp used 1653 int help_only = (flags & TAG_HELP); 1654 int name_only = (flags & TAG_NAMES); 1655 int noic = (flags & TAG_NOIC); 1656 int get_it_again = FALSE; 1657 #ifdef FEAT_CSCOPE 1658 int use_cscope = (flags & TAG_CSCOPE); 1659 #endif 1660 int verbose = (flags & TAG_VERBOSE); 1661 #ifdef FEAT_EVAL 1662 int use_tfu = ((flags & TAG_NO_TAGFUNC) == 0); 1663 #endif 1664 int save_p_ic = p_ic; 1665 1666 /* 1667 * Change the value of 'ignorecase' according to 'tagcase' for the 1668 * duration of this function. 1669 */ 1670 switch (curbuf->b_tc_flags ? curbuf->b_tc_flags : tc_flags) 1671 { 1672 case TC_FOLLOWIC: break; 1673 case TC_IGNORE: p_ic = TRUE; break; 1674 case TC_MATCH: p_ic = FALSE; break; 1675 case TC_FOLLOWSCS: p_ic = ignorecase(pat); break; 1676 case TC_SMART: p_ic = ignorecase_opt(pat, TRUE, TRUE); break; 1677 } 1678 1679 help_save = curbuf->b_help; 1680 orgpat.pat = pat; 1681 vimconv.vc_type = CONV_NONE; 1682 1683 /* 1684 * Allocate memory for the buffers that are used 1685 */ 1686 lbuf = alloc(lbuf_size); 1687 tag_fname = alloc(MAXPATHL + 1); 1688 #ifdef FEAT_EMACS_TAGS 1689 ebuf = alloc(LSIZE); 1690 #endif 1691 for (mtt = 0; mtt < MT_COUNT; ++mtt) 1692 { 1693 ga_init2(&ga_match[mtt], (int)sizeof(char_u *), 100); 1694 hash_init(&ht_match[mtt]); 1695 } 1696 1697 // check for out of memory situation 1698 if (lbuf == NULL || tag_fname == NULL 1699 #ifdef FEAT_EMACS_TAGS 1700 || ebuf == NULL 1701 #endif 1702 ) 1703 goto findtag_end; 1704 1705 #ifdef FEAT_CSCOPE 1706 STRCPY(tag_fname, "from cscope"); // for error messages 1707 #endif 1708 1709 /* 1710 * Initialize a few variables 1711 */ 1712 if (help_only) // want tags from help file 1713 curbuf->b_help = TRUE; // will be restored later 1714 #ifdef FEAT_CSCOPE 1715 else if (use_cscope) 1716 { 1717 // Make sure we don't mix help and cscope, confuses Coverity. 1718 help_only = FALSE; 1719 curbuf->b_help = FALSE; 1720 } 1721 #endif 1722 1723 orgpat.len = (int)STRLEN(pat); 1724 #ifdef FEAT_MULTI_LANG 1725 if (curbuf->b_help) 1726 { 1727 // When "@ab" is specified use only the "ab" language, otherwise 1728 // search all languages. 1729 if (orgpat.len > 3 && pat[orgpat.len - 3] == '@' 1730 && ASCII_ISALPHA(pat[orgpat.len - 2]) 1731 && ASCII_ISALPHA(pat[orgpat.len - 1])) 1732 { 1733 saved_pat = vim_strnsave(pat, orgpat.len - 3); 1734 if (saved_pat != NULL) 1735 { 1736 help_lang_find = &pat[orgpat.len - 2]; 1737 orgpat.pat = saved_pat; 1738 orgpat.len -= 3; 1739 } 1740 } 1741 } 1742 #endif 1743 if (p_tl != 0 && orgpat.len > p_tl) // adjust for 'taglength' 1744 orgpat.len = p_tl; 1745 1746 save_emsg_off = emsg_off; 1747 emsg_off = TRUE; // don't want error for invalid RE here 1748 prepare_pats(&orgpat, has_re); 1749 emsg_off = save_emsg_off; 1750 if (has_re && orgpat.regmatch.regprog == NULL) 1751 goto findtag_end; 1752 1753 #ifdef FEAT_TAG_BINS 1754 // This is only to avoid a compiler warning for using search_info 1755 // uninitialised. 1756 CLEAR_FIELD(search_info); 1757 #endif 1758 1759 #ifdef FEAT_EVAL 1760 if (*curbuf->b_p_tfu != NUL && use_tfu && !tfu_in_use) 1761 { 1762 tfu_in_use = TRUE; 1763 retval = find_tagfunc_tags(pat, &ga_match[0], &match_count, 1764 flags, buf_ffname); 1765 tfu_in_use = FALSE; 1766 if (retval != NOTDONE) 1767 goto findtag_end; 1768 } 1769 #endif 1770 1771 /* 1772 * When finding a specified number of matches, first try with matching 1773 * case, so binary search can be used, and try ignore-case matches in a 1774 * second loop. 1775 * When finding all matches, 'tagbsearch' is off, or there is no fixed 1776 * string to look for, ignore case right away to avoid going though the 1777 * tags files twice. 1778 * When the tag file is case-fold sorted, it is either one or the other. 1779 * Only ignore case when TAG_NOIC not used or 'ignorecase' set. 1780 */ 1781 #ifdef FEAT_MULTI_LANG 1782 // Set a flag if the file extension is .txt 1783 if ((flags & TAG_KEEP_LANG) 1784 && help_lang_find == NULL 1785 && curbuf->b_fname != NULL 1786 && (i = (int)STRLEN(curbuf->b_fname)) > 4 1787 && STRICMP(curbuf->b_fname + i - 4, ".txt") == 0) 1788 is_txt = TRUE; 1789 #endif 1790 #ifdef FEAT_TAG_BINS 1791 orgpat.regmatch.rm_ic = ((p_ic || !noic) 1792 && (findall || orgpat.headlen == 0 || !p_tbs)); 1793 for (round = 1; round <= 2; ++round) 1794 { 1795 linear = (orgpat.headlen == 0 || !p_tbs || round == 2); 1796 #else 1797 orgpat.regmatch.rm_ic = (p_ic || !noic); 1798 #endif 1799 1800 /* 1801 * Try tag file names from tags option one by one. 1802 */ 1803 for (first_file = TRUE; 1804 #ifdef FEAT_CSCOPE 1805 use_cscope || 1806 #endif 1807 get_tagfname(&tn, first_file, tag_fname) == OK; 1808 first_file = FALSE) 1809 { 1810 /* 1811 * A file that doesn't exist is silently ignored. Only when not a 1812 * single file is found, an error message is given (further on). 1813 */ 1814 #ifdef FEAT_CSCOPE 1815 if (use_cscope) 1816 fp = NULL; // avoid GCC warning 1817 else 1818 #endif 1819 { 1820 #ifdef FEAT_MULTI_LANG 1821 if (curbuf->b_help) 1822 { 1823 // Keep en if the file extension is .txt 1824 if (is_txt) 1825 STRCPY(help_lang, "en"); 1826 else 1827 { 1828 // Prefer help tags according to 'helplang'. Put the 1829 // two-letter language name in help_lang[]. 1830 i = (int)STRLEN(tag_fname); 1831 if (i > 3 && tag_fname[i - 3] == '-') 1832 STRCPY(help_lang, tag_fname + i - 2); 1833 else 1834 STRCPY(help_lang, "en"); 1835 } 1836 // When searching for a specific language skip tags files 1837 // for other languages. 1838 if (help_lang_find != NULL 1839 && STRICMP(help_lang, help_lang_find) != 0) 1840 continue; 1841 1842 // For CTRL-] in a help file prefer a match with the same 1843 // language. 1844 if ((flags & TAG_KEEP_LANG) 1845 && help_lang_find == NULL 1846 && curbuf->b_fname != NULL 1847 && (i = (int)STRLEN(curbuf->b_fname)) > 4 1848 && curbuf->b_fname[i - 1] == 'x' 1849 && curbuf->b_fname[i - 4] == '.' 1850 && STRNICMP(curbuf->b_fname + i - 3, help_lang, 2) == 0) 1851 help_pri = 0; 1852 else 1853 { 1854 help_pri = 1; 1855 for (s = p_hlg; *s != NUL; ++s) 1856 { 1857 if (STRNICMP(s, help_lang, 2) == 0) 1858 break; 1859 ++help_pri; 1860 if ((s = vim_strchr(s, ',')) == NULL) 1861 break; 1862 } 1863 if (s == NULL || *s == NUL) 1864 { 1865 // Language not in 'helplang': use last, prefer English, 1866 // unless found already. 1867 ++help_pri; 1868 if (STRICMP(help_lang, "en") != 0) 1869 ++help_pri; 1870 } 1871 } 1872 } 1873 #endif 1874 1875 if ((fp = mch_fopen((char *)tag_fname, "r")) == NULL) 1876 continue; 1877 1878 if (p_verbose >= 5) 1879 { 1880 verbose_enter(); 1881 smsg(_("Searching tags file %s"), tag_fname); 1882 verbose_leave(); 1883 } 1884 } 1885 did_open = TRUE; // remember that we found at least one file 1886 1887 state = TS_START; // we're at the start of the file 1888 #ifdef FEAT_EMACS_TAGS 1889 is_etag = 0; // default is: not emacs style 1890 #endif 1891 1892 /* 1893 * Read and parse the lines in the file one by one 1894 */ 1895 for (;;) 1896 { 1897 #ifdef FEAT_TAG_BINS 1898 // check for CTRL-C typed, more often when jumping around 1899 if (state == TS_BINARY || state == TS_SKIP_BACK) 1900 line_breakcheck(); 1901 else 1902 #endif 1903 fast_breakcheck(); 1904 if ((flags & TAG_INS_COMP)) // Double brackets for gcc 1905 ins_compl_check_keys(30, FALSE); 1906 if (got_int || ins_compl_interrupted()) 1907 { 1908 stop_searching = TRUE; 1909 break; 1910 } 1911 // When mincount is TAG_MANY, stop when enough matches have been 1912 // found (for completion). 1913 if (mincount == TAG_MANY && match_count >= TAG_MANY) 1914 { 1915 stop_searching = TRUE; 1916 retval = OK; 1917 break; 1918 } 1919 if (get_it_again) 1920 goto line_read_in; 1921 #ifdef FEAT_TAG_BINS 1922 /* 1923 * For binary search: compute the next offset to use. 1924 */ 1925 if (state == TS_BINARY) 1926 { 1927 offset = search_info.low_offset + ((search_info.high_offset 1928 - search_info.low_offset) / 2); 1929 if (offset == search_info.curr_offset) 1930 break; // End the binary search without a match. 1931 else 1932 search_info.curr_offset = offset; 1933 } 1934 1935 /* 1936 * Skipping back (after a match during binary search). 1937 */ 1938 else if (state == TS_SKIP_BACK) 1939 { 1940 search_info.curr_offset -= lbuf_size * 2; 1941 if (search_info.curr_offset < 0) 1942 { 1943 search_info.curr_offset = 0; 1944 rewind(fp); 1945 state = TS_STEP_FORWARD; 1946 } 1947 } 1948 1949 /* 1950 * When jumping around in the file, first read a line to find the 1951 * start of the next line. 1952 */ 1953 if (state == TS_BINARY || state == TS_SKIP_BACK) 1954 { 1955 // Adjust the search file offset to the correct position 1956 search_info.curr_offset_used = search_info.curr_offset; 1957 vim_fseek(fp, search_info.curr_offset, SEEK_SET); 1958 eof = vim_fgets(lbuf, lbuf_size, fp); 1959 if (!eof && search_info.curr_offset != 0) 1960 { 1961 // The explicit cast is to work around a bug in gcc 3.4.2 1962 // (repeated below). 1963 search_info.curr_offset = vim_ftell(fp); 1964 if (search_info.curr_offset == search_info.high_offset) 1965 { 1966 // oops, gone a bit too far; try from low offset 1967 vim_fseek(fp, search_info.low_offset, SEEK_SET); 1968 search_info.curr_offset = search_info.low_offset; 1969 } 1970 eof = vim_fgets(lbuf, lbuf_size, fp); 1971 } 1972 // skip empty and blank lines 1973 while (!eof && vim_isblankline(lbuf)) 1974 { 1975 search_info.curr_offset = vim_ftell(fp); 1976 eof = vim_fgets(lbuf, lbuf_size, fp); 1977 } 1978 if (eof) 1979 { 1980 // Hit end of file. Skip backwards. 1981 state = TS_SKIP_BACK; 1982 search_info.match_offset = vim_ftell(fp); 1983 search_info.curr_offset = search_info.curr_offset_used; 1984 continue; 1985 } 1986 } 1987 1988 /* 1989 * Not jumping around in the file: Read the next line. 1990 */ 1991 else 1992 #endif 1993 { 1994 // skip empty and blank lines 1995 do 1996 { 1997 #ifdef FEAT_CSCOPE 1998 if (use_cscope) 1999 eof = cs_fgets(lbuf, lbuf_size); 2000 else 2001 #endif 2002 eof = vim_fgets(lbuf, lbuf_size, fp); 2003 } while (!eof && vim_isblankline(lbuf)); 2004 2005 if (eof) 2006 { 2007 #ifdef FEAT_EMACS_TAGS 2008 if (incstack_idx) // this was an included file 2009 { 2010 --incstack_idx; 2011 fclose(fp); // end of this file ... 2012 fp = incstack[incstack_idx].fp; 2013 STRCPY(tag_fname, incstack[incstack_idx].etag_fname); 2014 vim_free(incstack[incstack_idx].etag_fname); 2015 is_etag = 1; // (only etags can include) 2016 continue; // ... continue with parent file 2017 } 2018 else 2019 #endif 2020 break; // end of file 2021 } 2022 } 2023 line_read_in: 2024 2025 if (vimconv.vc_type != CONV_NONE) 2026 { 2027 char_u *conv_line; 2028 int len; 2029 2030 // Convert every line. Converting the pattern from 'enc' to 2031 // the tags file encoding doesn't work, because characters are 2032 // not recognized. 2033 conv_line = string_convert(&vimconv, lbuf, NULL); 2034 if (conv_line != NULL) 2035 { 2036 // Copy or swap lbuf and conv_line. 2037 len = (int)STRLEN(conv_line) + 1; 2038 if (len > lbuf_size) 2039 { 2040 vim_free(lbuf); 2041 lbuf = conv_line; 2042 lbuf_size = len; 2043 } 2044 else 2045 { 2046 STRCPY(lbuf, conv_line); 2047 vim_free(conv_line); 2048 } 2049 } 2050 } 2051 2052 2053 #ifdef FEAT_EMACS_TAGS 2054 /* 2055 * Emacs tags line with CTRL-L: New file name on next line. 2056 * The file name is followed by a ','. 2057 * Remember etag file name in ebuf. 2058 */ 2059 if (*lbuf == Ctrl_L 2060 # ifdef FEAT_CSCOPE 2061 && !use_cscope 2062 # endif 2063 ) 2064 { 2065 is_etag = 1; // in case at the start 2066 state = TS_LINEAR; 2067 if (!vim_fgets(ebuf, LSIZE, fp)) 2068 { 2069 for (p = ebuf; *p && *p != ','; p++) 2070 ; 2071 *p = NUL; 2072 2073 /* 2074 * atoi(p+1) is the number of bytes before the next ^L 2075 * unless it is an include statement. 2076 */ 2077 if (STRNCMP(p + 1, "include", 7) == 0 2078 && incstack_idx < INCSTACK_SIZE) 2079 { 2080 // Save current "fp" and "tag_fname" in the stack. 2081 if ((incstack[incstack_idx].etag_fname = 2082 vim_strsave(tag_fname)) != NULL) 2083 { 2084 char_u *fullpath_ebuf; 2085 2086 incstack[incstack_idx].fp = fp; 2087 fp = NULL; 2088 2089 // Figure out "tag_fname" and "fp" to use for 2090 // included file. 2091 fullpath_ebuf = expand_tag_fname(ebuf, 2092 tag_fname, FALSE); 2093 if (fullpath_ebuf != NULL) 2094 { 2095 fp = mch_fopen((char *)fullpath_ebuf, "r"); 2096 if (fp != NULL) 2097 { 2098 if (STRLEN(fullpath_ebuf) > LSIZE) 2099 semsg(_("E430: Tag file path truncated for %s\n"), ebuf); 2100 vim_strncpy(tag_fname, fullpath_ebuf, 2101 MAXPATHL); 2102 ++incstack_idx; 2103 is_etag = 0; // we can include anything 2104 } 2105 vim_free(fullpath_ebuf); 2106 } 2107 if (fp == NULL) 2108 { 2109 // Can't open the included file, skip it and 2110 // restore old value of "fp". 2111 fp = incstack[incstack_idx].fp; 2112 vim_free(incstack[incstack_idx].etag_fname); 2113 } 2114 } 2115 } 2116 } 2117 continue; 2118 } 2119 #endif 2120 2121 /* 2122 * When still at the start of the file, check for Emacs tags file 2123 * format, and for "not sorted" flag. 2124 */ 2125 if (state == TS_START) 2126 { 2127 // The header ends when the line sorts below "!_TAG_". When 2128 // case is folded lower case letters sort before "_". 2129 if (STRNCMP(lbuf, "!_TAG_", 6) <= 0 2130 || (lbuf[0] == '!' && ASCII_ISLOWER(lbuf[1]))) 2131 { 2132 if (STRNCMP(lbuf, "!_TAG_", 6) != 0) 2133 // Non-header item before the header, e.g. "!" itself. 2134 goto parse_line; 2135 2136 /* 2137 * Read header line. 2138 */ 2139 #ifdef FEAT_TAG_BINS 2140 if (STRNCMP(lbuf, "!_TAG_FILE_SORTED\t", 18) == 0) 2141 tag_file_sorted = lbuf[18]; 2142 #endif 2143 if (STRNCMP(lbuf, "!_TAG_FILE_ENCODING\t", 20) == 0) 2144 { 2145 // Prepare to convert every line from the specified 2146 // encoding to 'encoding'. 2147 for (p = lbuf + 20; *p > ' ' && *p < 127; ++p) 2148 ; 2149 *p = NUL; 2150 convert_setup(&vimconv, lbuf + 20, p_enc); 2151 } 2152 2153 // Read the next line. Unrecognized flags are ignored. 2154 continue; 2155 } 2156 2157 // Headers ends. 2158 2159 #ifdef FEAT_TAG_BINS 2160 /* 2161 * When there is no tag head, or ignoring case, need to do a 2162 * linear search. 2163 * When no "!_TAG_" is found, default to binary search. If 2164 * the tag file isn't sorted, the second loop will find it. 2165 * When "!_TAG_FILE_SORTED" found: start binary search if 2166 * flag set. 2167 * For cscope, it's always linear. 2168 */ 2169 # ifdef FEAT_CSCOPE 2170 if (linear || use_cscope) 2171 # else 2172 if (linear) 2173 # endif 2174 state = TS_LINEAR; 2175 else if (tag_file_sorted == NUL) 2176 state = TS_BINARY; 2177 else if (tag_file_sorted == '1') 2178 state = TS_BINARY; 2179 else if (tag_file_sorted == '2') 2180 { 2181 state = TS_BINARY; 2182 sortic = TRUE; 2183 orgpat.regmatch.rm_ic = (p_ic || !noic); 2184 } 2185 else 2186 state = TS_LINEAR; 2187 2188 if (state == TS_BINARY && orgpat.regmatch.rm_ic && !sortic) 2189 { 2190 // Binary search won't work for ignoring case, use linear 2191 // search. 2192 linear = TRUE; 2193 state = TS_LINEAR; 2194 } 2195 #else 2196 state = TS_LINEAR; 2197 #endif 2198 2199 #ifdef FEAT_TAG_BINS 2200 // When starting a binary search, get the size of the file and 2201 // compute the first offset. 2202 if (state == TS_BINARY) 2203 { 2204 if (vim_fseek(fp, 0L, SEEK_END) != 0) 2205 // can't seek, don't use binary search 2206 state = TS_LINEAR; 2207 else 2208 { 2209 // Get the tag file size (don't use mch_fstat(), it's 2210 // not portable). Don't use lseek(), it doesn't work 2211 // properly on MacOS Catalina. 2212 filesize = vim_ftell(fp); 2213 vim_fseek(fp, 0L, SEEK_SET); 2214 2215 // Calculate the first read offset in the file. Start 2216 // the search in the middle of the file. 2217 search_info.low_offset = 0; 2218 search_info.low_char = 0; 2219 search_info.high_offset = filesize; 2220 search_info.curr_offset = 0; 2221 search_info.high_char = 0xff; 2222 } 2223 continue; 2224 } 2225 #endif 2226 } 2227 2228 parse_line: 2229 // When the line is too long the NUL will not be in the 2230 // last-but-one byte (see vim_fgets()). 2231 // Has been reported for Mozilla JS with extremely long names. 2232 // In that case we need to increase lbuf_size. 2233 if (lbuf[lbuf_size - 2] != NUL 2234 #ifdef FEAT_CSCOPE 2235 && !use_cscope 2236 #endif 2237 ) 2238 { 2239 lbuf_size *= 2; 2240 vim_free(lbuf); 2241 lbuf = alloc(lbuf_size); 2242 if (lbuf == NULL) 2243 goto findtag_end; 2244 #ifdef FEAT_TAG_BINS 2245 // this will try the same thing again, make sure the offset is 2246 // different 2247 search_info.curr_offset = 0; 2248 #endif 2249 continue; 2250 } 2251 2252 /* 2253 * Figure out where the different strings are in this line. 2254 * For "normal" tags: Do a quick check if the tag matches. 2255 * This speeds up tag searching a lot! 2256 */ 2257 if (orgpat.headlen 2258 #ifdef FEAT_EMACS_TAGS 2259 && !is_etag 2260 #endif 2261 ) 2262 { 2263 CLEAR_FIELD(tagp); 2264 tagp.tagname = lbuf; 2265 tagp.tagname_end = vim_strchr(lbuf, TAB); 2266 if (tagp.tagname_end == NULL) 2267 { 2268 // Corrupted tag line. 2269 line_error = TRUE; 2270 break; 2271 } 2272 2273 /* 2274 * Skip this line if the length of the tag is different and 2275 * there is no regexp, or the tag is too short. 2276 */ 2277 cmplen = (int)(tagp.tagname_end - tagp.tagname); 2278 if (p_tl != 0 && cmplen > p_tl) // adjust for 'taglength' 2279 cmplen = p_tl; 2280 if (has_re && orgpat.headlen < cmplen) 2281 cmplen = orgpat.headlen; 2282 else if (state == TS_LINEAR && orgpat.headlen != cmplen) 2283 continue; 2284 2285 #ifdef FEAT_TAG_BINS 2286 if (state == TS_BINARY) 2287 { 2288 /* 2289 * Simplistic check for unsorted tags file. 2290 */ 2291 i = (int)tagp.tagname[0]; 2292 if (sortic) 2293 i = (int)TOUPPER_ASC(tagp.tagname[0]); 2294 if (i < search_info.low_char || i > search_info.high_char) 2295 sort_error = TRUE; 2296 2297 /* 2298 * Compare the current tag with the searched tag. 2299 */ 2300 if (sortic) 2301 tagcmp = tag_strnicmp(tagp.tagname, orgpat.head, 2302 (size_t)cmplen); 2303 else 2304 tagcmp = STRNCMP(tagp.tagname, orgpat.head, cmplen); 2305 2306 /* 2307 * A match with a shorter tag means to search forward. 2308 * A match with a longer tag means to search backward. 2309 */ 2310 if (tagcmp == 0) 2311 { 2312 if (cmplen < orgpat.headlen) 2313 tagcmp = -1; 2314 else if (cmplen > orgpat.headlen) 2315 tagcmp = 1; 2316 } 2317 2318 if (tagcmp == 0) 2319 { 2320 // We've located the tag, now skip back and search 2321 // forward until the first matching tag is found. 2322 state = TS_SKIP_BACK; 2323 search_info.match_offset = search_info.curr_offset; 2324 continue; 2325 } 2326 if (tagcmp < 0) 2327 { 2328 search_info.curr_offset = vim_ftell(fp); 2329 if (search_info.curr_offset < search_info.high_offset) 2330 { 2331 search_info.low_offset = search_info.curr_offset; 2332 if (sortic) 2333 search_info.low_char = 2334 TOUPPER_ASC(tagp.tagname[0]); 2335 else 2336 search_info.low_char = tagp.tagname[0]; 2337 continue; 2338 } 2339 } 2340 if (tagcmp > 0 2341 && search_info.curr_offset != search_info.high_offset) 2342 { 2343 search_info.high_offset = search_info.curr_offset; 2344 if (sortic) 2345 search_info.high_char = 2346 TOUPPER_ASC(tagp.tagname[0]); 2347 else 2348 search_info.high_char = tagp.tagname[0]; 2349 continue; 2350 } 2351 2352 // No match yet and are at the end of the binary search. 2353 break; 2354 } 2355 else if (state == TS_SKIP_BACK) 2356 { 2357 if (MB_STRNICMP(tagp.tagname, orgpat.head, cmplen) != 0) 2358 state = TS_STEP_FORWARD; 2359 else 2360 // Have to skip back more. Restore the curr_offset 2361 // used, otherwise we get stuck at a long line. 2362 search_info.curr_offset = search_info.curr_offset_used; 2363 continue; 2364 } 2365 else if (state == TS_STEP_FORWARD) 2366 { 2367 if (MB_STRNICMP(tagp.tagname, orgpat.head, cmplen) != 0) 2368 { 2369 if ((off_T)vim_ftell(fp) > search_info.match_offset) 2370 break; // past last match 2371 else 2372 continue; // before first match 2373 } 2374 } 2375 else 2376 #endif 2377 // skip this match if it can't match 2378 if (MB_STRNICMP(tagp.tagname, orgpat.head, cmplen) != 0) 2379 continue; 2380 2381 /* 2382 * Can be a matching tag, isolate the file name and command. 2383 */ 2384 tagp.fname = tagp.tagname_end + 1; 2385 tagp.fname_end = vim_strchr(tagp.fname, TAB); 2386 tagp.command = tagp.fname_end + 1; 2387 if (tagp.fname_end == NULL) 2388 i = FAIL; 2389 else 2390 i = OK; 2391 } 2392 else 2393 i = parse_tag_line(lbuf, 2394 #ifdef FEAT_EMACS_TAGS 2395 is_etag, 2396 #endif 2397 &tagp); 2398 if (i == FAIL) 2399 { 2400 line_error = TRUE; 2401 break; 2402 } 2403 2404 #ifdef FEAT_EMACS_TAGS 2405 if (is_etag) 2406 tagp.fname = ebuf; 2407 #endif 2408 /* 2409 * First try matching with the pattern literally (also when it is 2410 * a regexp). 2411 */ 2412 cmplen = (int)(tagp.tagname_end - tagp.tagname); 2413 if (p_tl != 0 && cmplen > p_tl) // adjust for 'taglength' 2414 cmplen = p_tl; 2415 // if tag length does not match, don't try comparing 2416 if (orgpat.len != cmplen) 2417 match = FALSE; 2418 else 2419 { 2420 if (orgpat.regmatch.rm_ic) 2421 { 2422 match = (MB_STRNICMP(tagp.tagname, orgpat.pat, cmplen) == 0); 2423 if (match) 2424 match_no_ic = (STRNCMP(tagp.tagname, orgpat.pat, 2425 cmplen) == 0); 2426 } 2427 else 2428 match = (STRNCMP(tagp.tagname, orgpat.pat, cmplen) == 0); 2429 } 2430 2431 /* 2432 * Has a regexp: Also find tags matching regexp. 2433 */ 2434 match_re = FALSE; 2435 if (!match && orgpat.regmatch.regprog != NULL) 2436 { 2437 int cc; 2438 2439 cc = *tagp.tagname_end; 2440 *tagp.tagname_end = NUL; 2441 match = vim_regexec(&orgpat.regmatch, tagp.tagname, (colnr_T)0); 2442 if (match) 2443 { 2444 matchoff = (int)(orgpat.regmatch.startp[0] - tagp.tagname); 2445 if (orgpat.regmatch.rm_ic) 2446 { 2447 orgpat.regmatch.rm_ic = FALSE; 2448 match_no_ic = vim_regexec(&orgpat.regmatch, tagp.tagname, 2449 (colnr_T)0); 2450 orgpat.regmatch.rm_ic = TRUE; 2451 } 2452 } 2453 *tagp.tagname_end = cc; 2454 match_re = TRUE; 2455 } 2456 2457 /* 2458 * If a match is found, add it to ht_match[] and ga_match[]. 2459 */ 2460 if (match) 2461 { 2462 int len = 0; 2463 2464 #ifdef FEAT_CSCOPE 2465 if (use_cscope) 2466 { 2467 // Don't change the ordering, always use the same table. 2468 mtt = MT_GL_OTH; 2469 } 2470 else 2471 #endif 2472 { 2473 // Decide in which array to store this match. 2474 is_current = test_for_current( 2475 #ifdef FEAT_EMACS_TAGS 2476 is_etag, 2477 #endif 2478 tagp.fname, tagp.fname_end, tag_fname, 2479 buf_ffname); 2480 #ifdef FEAT_EMACS_TAGS 2481 is_static = FALSE; 2482 if (!is_etag) // emacs tags are never static 2483 #endif 2484 is_static = test_for_static(&tagp); 2485 2486 // decide in which of the sixteen tables to store this 2487 // match 2488 if (is_static) 2489 { 2490 if (is_current) 2491 mtt = MT_ST_CUR; 2492 else 2493 mtt = MT_ST_OTH; 2494 } 2495 else 2496 { 2497 if (is_current) 2498 mtt = MT_GL_CUR; 2499 else 2500 mtt = MT_GL_OTH; 2501 } 2502 if (orgpat.regmatch.rm_ic && !match_no_ic) 2503 mtt += MT_IC_OFF; 2504 if (match_re) 2505 mtt += MT_RE_OFF; 2506 } 2507 2508 /* 2509 * Add the found match in ht_match[mtt] and ga_match[mtt]. 2510 * Store the info we need later, which depends on the kind of 2511 * tags we are dealing with. 2512 */ 2513 if (help_only) 2514 { 2515 #ifdef FEAT_MULTI_LANG 2516 # define ML_EXTRA 3 2517 #else 2518 # define ML_EXTRA 0 2519 #endif 2520 /* 2521 * Append the help-heuristic number after the tagname, for 2522 * sorting it later. The heuristic is ignored for 2523 * detecting duplicates. 2524 * The format is {tagname}@{lang}NUL{heuristic}NUL 2525 */ 2526 *tagp.tagname_end = NUL; 2527 len = (int)(tagp.tagname_end - tagp.tagname); 2528 mfp = alloc(sizeof(char_u) + len + 10 + ML_EXTRA + 1); 2529 if (mfp != NULL) 2530 { 2531 int heuristic; 2532 2533 p = mfp; 2534 STRCPY(p, tagp.tagname); 2535 #ifdef FEAT_MULTI_LANG 2536 p[len] = '@'; 2537 STRCPY(p + len + 1, help_lang); 2538 #endif 2539 2540 heuristic = help_heuristic(tagp.tagname, 2541 match_re ? matchoff : 0, !match_no_ic); 2542 #ifdef FEAT_MULTI_LANG 2543 heuristic += help_pri; 2544 #endif 2545 sprintf((char *)p + len + 1 + ML_EXTRA, "%06d", 2546 heuristic); 2547 } 2548 *tagp.tagname_end = TAB; 2549 } 2550 else if (name_only) 2551 { 2552 if (get_it_again) 2553 { 2554 char_u *temp_end = tagp.command; 2555 2556 if (*temp_end == '/') 2557 while (*temp_end && *temp_end != '\r' 2558 && *temp_end != '\n' 2559 && *temp_end != '$') 2560 temp_end++; 2561 2562 if (tagp.command + 2 < temp_end) 2563 { 2564 len = (int)(temp_end - tagp.command - 2); 2565 mfp = alloc(len + 2); 2566 if (mfp != NULL) 2567 vim_strncpy(mfp, tagp.command + 2, len); 2568 } 2569 else 2570 mfp = NULL; 2571 get_it_again = FALSE; 2572 } 2573 else 2574 { 2575 len = (int)(tagp.tagname_end - tagp.tagname); 2576 mfp = alloc(sizeof(char_u) + len + 1); 2577 if (mfp != NULL) 2578 vim_strncpy(mfp, tagp.tagname, len); 2579 2580 // if wanted, re-read line to get long form too 2581 if (State & INSERT) 2582 get_it_again = p_sft; 2583 } 2584 } 2585 else 2586 { 2587 size_t tag_fname_len = STRLEN(tag_fname); 2588 #ifdef FEAT_EMACS_TAGS 2589 size_t ebuf_len = 0; 2590 #endif 2591 2592 // Save the tag in a buffer. 2593 // Use 0x02 to separate fields (Can't use NUL because the 2594 // hash key is terminated by NUL, or Ctrl_A because that is 2595 // part of some Emacs tag files -- see parse_tag_line). 2596 // Emacs tag: <mtt><tag_fname><0x02><ebuf><0x02><lbuf><NUL> 2597 // other tag: <mtt><tag_fname><0x02><0x02><lbuf><NUL> 2598 // without Emacs tags: <mtt><tag_fname><0x02><lbuf><NUL> 2599 // Here <mtt> is the "mtt" value plus 1 to avoid NUL. 2600 len = (int)tag_fname_len + (int)STRLEN(lbuf) + 3; 2601 #ifdef FEAT_EMACS_TAGS 2602 if (is_etag) 2603 { 2604 ebuf_len = STRLEN(ebuf); 2605 len += (int)ebuf_len + 1; 2606 } 2607 else 2608 ++len; 2609 #endif 2610 mfp = alloc(sizeof(char_u) + len + 1); 2611 if (mfp != NULL) 2612 { 2613 p = mfp; 2614 p[0] = mtt + 1; 2615 STRCPY(p + 1, tag_fname); 2616 #ifdef BACKSLASH_IN_FILENAME 2617 // Ignore differences in slashes, avoid adding 2618 // both path/file and path\file. 2619 slash_adjust(p + 1); 2620 #endif 2621 p[tag_fname_len + 1] = TAG_SEP; 2622 s = p + 1 + tag_fname_len + 1; 2623 #ifdef FEAT_EMACS_TAGS 2624 if (is_etag) 2625 { 2626 STRCPY(s, ebuf); 2627 s[ebuf_len] = TAG_SEP; 2628 s += ebuf_len + 1; 2629 } 2630 else 2631 *s++ = TAG_SEP; 2632 #endif 2633 STRCPY(s, lbuf); 2634 } 2635 } 2636 2637 if (mfp != NULL) 2638 { 2639 hashitem_T *hi; 2640 2641 /* 2642 * Don't add identical matches. 2643 * Add all cscope tags, because they are all listed. 2644 * "mfp" is used as a hash key, there is a NUL byte to end 2645 * the part that matters for comparing, more bytes may 2646 * follow after it. E.g. help tags store the priority 2647 * after the NUL. 2648 */ 2649 #ifdef FEAT_CSCOPE 2650 if (use_cscope) 2651 hash++; 2652 else 2653 #endif 2654 hash = hash_hash(mfp); 2655 hi = hash_lookup(&ht_match[mtt], mfp, hash); 2656 if (HASHITEM_EMPTY(hi)) 2657 { 2658 if (hash_add_item(&ht_match[mtt], hi, mfp, hash) 2659 == FAIL 2660 || ga_grow(&ga_match[mtt], 1) != OK) 2661 { 2662 // Out of memory! Just forget about the rest. 2663 retval = OK; 2664 stop_searching = TRUE; 2665 break; 2666 } 2667 else 2668 { 2669 ((char_u **)(ga_match[mtt].ga_data)) 2670 [ga_match[mtt].ga_len++] = mfp; 2671 ++match_count; 2672 } 2673 } 2674 else 2675 // duplicate tag, drop it 2676 vim_free(mfp); 2677 } 2678 } 2679 #ifdef FEAT_CSCOPE 2680 if (use_cscope && eof) 2681 break; 2682 #endif 2683 } // forever 2684 2685 if (line_error) 2686 { 2687 semsg(_("E431: Format error in tags file \"%s\""), tag_fname); 2688 #ifdef FEAT_CSCOPE 2689 if (!use_cscope) 2690 #endif 2691 semsg(_("Before byte %ld"), (long)vim_ftell(fp)); 2692 stop_searching = TRUE; 2693 line_error = FALSE; 2694 } 2695 2696 #ifdef FEAT_CSCOPE 2697 if (!use_cscope) 2698 #endif 2699 fclose(fp); 2700 #ifdef FEAT_EMACS_TAGS 2701 while (incstack_idx) 2702 { 2703 --incstack_idx; 2704 fclose(incstack[incstack_idx].fp); 2705 vim_free(incstack[incstack_idx].etag_fname); 2706 } 2707 #endif 2708 if (vimconv.vc_type != CONV_NONE) 2709 convert_setup(&vimconv, NULL, NULL); 2710 2711 #ifdef FEAT_TAG_BINS 2712 tag_file_sorted = NUL; 2713 if (sort_error) 2714 { 2715 semsg(_("E432: Tags file not sorted: %s"), tag_fname); 2716 sort_error = FALSE; 2717 } 2718 #endif 2719 2720 /* 2721 * Stop searching if sufficient tags have been found. 2722 */ 2723 if (match_count >= mincount) 2724 { 2725 retval = OK; 2726 stop_searching = TRUE; 2727 } 2728 2729 #ifdef FEAT_CSCOPE 2730 if (stop_searching || use_cscope) 2731 #else 2732 if (stop_searching) 2733 #endif 2734 break; 2735 2736 } // end of for-each-file loop 2737 2738 #ifdef FEAT_CSCOPE 2739 if (!use_cscope) 2740 #endif 2741 tagname_free(&tn); 2742 2743 #ifdef FEAT_TAG_BINS 2744 // stop searching when already did a linear search, or when TAG_NOIC 2745 // used, and 'ignorecase' not set or already did case-ignore search 2746 if (stop_searching || linear || (!p_ic && noic) || orgpat.regmatch.rm_ic) 2747 break; 2748 # ifdef FEAT_CSCOPE 2749 if (use_cscope) 2750 break; 2751 # endif 2752 orgpat.regmatch.rm_ic = TRUE; // try another time while ignoring case 2753 } 2754 #endif 2755 2756 if (!stop_searching) 2757 { 2758 if (!did_open && verbose) // never opened any tags file 2759 emsg(_("E433: No tags file")); 2760 retval = OK; // It's OK even when no tag found 2761 } 2762 2763 findtag_end: 2764 vim_free(lbuf); 2765 vim_regfree(orgpat.regmatch.regprog); 2766 vim_free(tag_fname); 2767 #ifdef FEAT_EMACS_TAGS 2768 vim_free(ebuf); 2769 #endif 2770 2771 /* 2772 * Move the matches from the ga_match[] arrays into one list of 2773 * matches. When retval == FAIL, free the matches. 2774 */ 2775 if (retval == FAIL) 2776 match_count = 0; 2777 2778 if (match_count > 0) 2779 matches = ALLOC_MULT(char_u *, match_count); 2780 else 2781 matches = NULL; 2782 match_count = 0; 2783 for (mtt = 0; mtt < MT_COUNT; ++mtt) 2784 { 2785 for (i = 0; i < ga_match[mtt].ga_len; ++i) 2786 { 2787 mfp = ((char_u **)(ga_match[mtt].ga_data))[i]; 2788 if (matches == NULL) 2789 vim_free(mfp); 2790 else 2791 { 2792 if (!name_only) 2793 { 2794 // Change mtt back to zero-based. 2795 *mfp = *mfp - 1; 2796 2797 // change the TAG_SEP back to NUL 2798 for (p = mfp + 1; *p != NUL; ++p) 2799 if (*p == TAG_SEP) 2800 *p = NUL; 2801 } 2802 matches[match_count++] = (char_u *)mfp; 2803 } 2804 } 2805 2806 ga_clear(&ga_match[mtt]); 2807 hash_clear(&ht_match[mtt]); 2808 } 2809 2810 *matchesp = matches; 2811 *num_matches = match_count; 2812 2813 curbuf->b_help = help_save; 2814 #ifdef FEAT_MULTI_LANG 2815 vim_free(saved_pat); 2816 #endif 2817 2818 p_ic = save_p_ic; 2819 2820 return retval; 2821 } 2822 2823 static garray_T tag_fnames = GA_EMPTY; 2824 2825 /* 2826 * Callback function for finding all "tags" and "tags-??" files in 2827 * 'runtimepath' doc directories. 2828 */ 2829 static void 2830 found_tagfile_cb(char_u *fname, void *cookie UNUSED) 2831 { 2832 if (ga_grow(&tag_fnames, 1) == OK) 2833 { 2834 char_u *tag_fname = vim_strsave(fname); 2835 2836 #ifdef BACKSLASH_IN_FILENAME 2837 slash_adjust(tag_fname); 2838 #endif 2839 simplify_filename(tag_fname); 2840 ((char_u **)(tag_fnames.ga_data))[tag_fnames.ga_len++] = tag_fname; 2841 } 2842 } 2843 2844 #if defined(EXITFREE) || defined(PROTO) 2845 void 2846 free_tag_stuff(void) 2847 { 2848 ga_clear_strings(&tag_fnames); 2849 if (curwin != NULL) 2850 do_tag(NULL, DT_FREE, 0, 0, 0); 2851 tag_freematch(); 2852 2853 # if defined(FEAT_QUICKFIX) 2854 tagstack_clear_entry(&ptag_entry); 2855 # endif 2856 } 2857 #endif 2858 2859 /* 2860 * Get the next name of a tag file from the tag file list. 2861 * For help files, use "tags" file only. 2862 * 2863 * Return FAIL if no more tag file names, OK otherwise. 2864 */ 2865 int 2866 get_tagfname( 2867 tagname_T *tnp, // holds status info 2868 int first, // TRUE when first file name is wanted 2869 char_u *buf) // pointer to buffer of MAXPATHL chars 2870 { 2871 char_u *fname = NULL; 2872 char_u *r_ptr; 2873 int i; 2874 2875 if (first) 2876 CLEAR_POINTER(tnp); 2877 2878 if (curbuf->b_help) 2879 { 2880 /* 2881 * For help files it's done in a completely different way: 2882 * Find "doc/tags" and "doc/tags-??" in all directories in 2883 * 'runtimepath'. 2884 */ 2885 if (first) 2886 { 2887 ga_clear_strings(&tag_fnames); 2888 ga_init2(&tag_fnames, (int)sizeof(char_u *), 10); 2889 do_in_runtimepath((char_u *) 2890 #ifdef FEAT_MULTI_LANG 2891 # ifdef VMS 2892 // Functions decc$to_vms() and decc$translate_vms() crash 2893 // on some VMS systems with wildcards "??". Seems ECO 2894 // patches do fix the problem in C RTL, but we can't use 2895 // an #ifdef for that. 2896 "doc/tags doc/tags-*" 2897 # else 2898 "doc/tags doc/tags-??" 2899 # endif 2900 #else 2901 "doc/tags" 2902 #endif 2903 , DIP_ALL, found_tagfile_cb, NULL); 2904 } 2905 2906 if (tnp->tn_hf_idx >= tag_fnames.ga_len) 2907 { 2908 // Not found in 'runtimepath', use 'helpfile', if it exists and 2909 // wasn't used yet, replacing "help.txt" with "tags". 2910 if (tnp->tn_hf_idx > tag_fnames.ga_len || *p_hf == NUL) 2911 return FAIL; 2912 ++tnp->tn_hf_idx; 2913 STRCPY(buf, p_hf); 2914 STRCPY(gettail(buf), "tags"); 2915 #ifdef BACKSLASH_IN_FILENAME 2916 slash_adjust(buf); 2917 #endif 2918 simplify_filename(buf); 2919 2920 for (i = 0; i < tag_fnames.ga_len; ++i) 2921 if (STRCMP(buf, ((char_u **)(tag_fnames.ga_data))[i]) == 0) 2922 return FAIL; // avoid duplicate file names 2923 } 2924 else 2925 vim_strncpy(buf, ((char_u **)(tag_fnames.ga_data))[ 2926 tnp->tn_hf_idx++], MAXPATHL - 1); 2927 return OK; 2928 } 2929 2930 if (first) 2931 { 2932 // Init. We make a copy of 'tags', because autocommands may change 2933 // the value without notifying us. 2934 tnp->tn_tags = vim_strsave((*curbuf->b_p_tags != NUL) 2935 ? curbuf->b_p_tags : p_tags); 2936 if (tnp->tn_tags == NULL) 2937 return FAIL; 2938 tnp->tn_np = tnp->tn_tags; 2939 } 2940 2941 /* 2942 * Loop until we have found a file name that can be used. 2943 * There are two states: 2944 * tnp->tn_did_filefind_init == FALSE: setup for next part in 'tags'. 2945 * tnp->tn_did_filefind_init == TRUE: find next file in this part. 2946 */ 2947 for (;;) 2948 { 2949 if (tnp->tn_did_filefind_init) 2950 { 2951 fname = vim_findfile(tnp->tn_search_ctx); 2952 if (fname != NULL) 2953 break; 2954 2955 tnp->tn_did_filefind_init = FALSE; 2956 } 2957 else 2958 { 2959 char_u *filename = NULL; 2960 2961 // Stop when used all parts of 'tags'. 2962 if (*tnp->tn_np == NUL) 2963 { 2964 vim_findfile_cleanup(tnp->tn_search_ctx); 2965 tnp->tn_search_ctx = NULL; 2966 return FAIL; 2967 } 2968 2969 /* 2970 * Copy next file name into buf. 2971 */ 2972 buf[0] = NUL; 2973 (void)copy_option_part(&tnp->tn_np, buf, MAXPATHL - 1, " ,"); 2974 2975 #ifdef FEAT_PATH_EXTRA 2976 r_ptr = vim_findfile_stopdir(buf); 2977 #else 2978 r_ptr = NULL; 2979 #endif 2980 // move the filename one char forward and truncate the 2981 // filepath with a NUL 2982 filename = gettail(buf); 2983 STRMOVE(filename + 1, filename); 2984 *filename++ = NUL; 2985 2986 tnp->tn_search_ctx = vim_findfile_init(buf, filename, 2987 r_ptr, 100, 2988 FALSE, // don't free visited list 2989 FINDFILE_FILE, // we search for a file 2990 tnp->tn_search_ctx, TRUE, curbuf->b_ffname); 2991 if (tnp->tn_search_ctx != NULL) 2992 tnp->tn_did_filefind_init = TRUE; 2993 } 2994 } 2995 2996 STRCPY(buf, fname); 2997 vim_free(fname); 2998 return OK; 2999 } 3000 3001 /* 3002 * Free the contents of a tagname_T that was filled by get_tagfname(). 3003 */ 3004 void 3005 tagname_free(tagname_T *tnp) 3006 { 3007 vim_free(tnp->tn_tags); 3008 vim_findfile_cleanup(tnp->tn_search_ctx); 3009 tnp->tn_search_ctx = NULL; 3010 ga_clear_strings(&tag_fnames); 3011 } 3012 3013 /* 3014 * Parse one line from the tags file. Find start/end of tag name, start/end of 3015 * file name and start of search pattern. 3016 * 3017 * If is_etag is TRUE, tagp->fname and tagp->fname_end are not set. 3018 * 3019 * Return FAIL if there is a format error in this line, OK otherwise. 3020 */ 3021 static int 3022 parse_tag_line( 3023 char_u *lbuf, // line to be parsed 3024 #ifdef FEAT_EMACS_TAGS 3025 int is_etag, 3026 #endif 3027 tagptrs_T *tagp) 3028 { 3029 char_u *p; 3030 3031 #ifdef FEAT_EMACS_TAGS 3032 char_u *p_7f; 3033 3034 if (is_etag) 3035 { 3036 /* 3037 * There are two formats for an emacs tag line: 3038 * 1: struct EnvBase ^?EnvBase^A139,4627 3039 * 2: #define ARPB_WILD_WORLD ^?153,5194 3040 */ 3041 p_7f = vim_strchr(lbuf, 0x7f); 3042 if (p_7f == NULL) 3043 { 3044 etag_fail: 3045 if (vim_strchr(lbuf, '\n') == NULL) 3046 { 3047 // Truncated line. Ignore it. 3048 if (p_verbose >= 5) 3049 { 3050 verbose_enter(); 3051 msg(_("Ignoring long line in tags file")); 3052 verbose_leave(); 3053 } 3054 tagp->command = lbuf; 3055 tagp->tagname = lbuf; 3056 tagp->tagname_end = lbuf; 3057 return OK; 3058 } 3059 return FAIL; 3060 } 3061 3062 // Find ^A. If not found the line number is after the 0x7f 3063 p = vim_strchr(p_7f, Ctrl_A); 3064 if (p == NULL) 3065 p = p_7f + 1; 3066 else 3067 ++p; 3068 3069 if (!VIM_ISDIGIT(*p)) // check for start of line number 3070 goto etag_fail; 3071 tagp->command = p; 3072 3073 3074 if (p[-1] == Ctrl_A) // first format: explicit tagname given 3075 { 3076 tagp->tagname = p_7f + 1; 3077 tagp->tagname_end = p - 1; 3078 } 3079 else // second format: isolate tagname 3080 { 3081 // find end of tagname 3082 for (p = p_7f - 1; !vim_iswordc(*p); --p) 3083 if (p == lbuf) 3084 goto etag_fail; 3085 tagp->tagname_end = p + 1; 3086 while (p >= lbuf && vim_iswordc(*p)) 3087 --p; 3088 tagp->tagname = p + 1; 3089 } 3090 } 3091 else // not an Emacs tag 3092 { 3093 #endif 3094 // Isolate the tagname, from lbuf up to the first white 3095 tagp->tagname = lbuf; 3096 p = vim_strchr(lbuf, TAB); 3097 if (p == NULL) 3098 return FAIL; 3099 tagp->tagname_end = p; 3100 3101 // Isolate file name, from first to second white space 3102 if (*p != NUL) 3103 ++p; 3104 tagp->fname = p; 3105 p = vim_strchr(p, TAB); 3106 if (p == NULL) 3107 return FAIL; 3108 tagp->fname_end = p; 3109 3110 // find start of search command, after second white space 3111 if (*p != NUL) 3112 ++p; 3113 if (*p == NUL) 3114 return FAIL; 3115 tagp->command = p; 3116 #ifdef FEAT_EMACS_TAGS 3117 } 3118 #endif 3119 3120 return OK; 3121 } 3122 3123 /* 3124 * Check if tagname is a static tag 3125 * 3126 * Static tags produced by the older ctags program have the format: 3127 * 'file:tag file /pattern'. 3128 * This is only recognized when both occurrence of 'file' are the same, to 3129 * avoid recognizing "string::string" or ":exit". 3130 * 3131 * Static tags produced by the new ctags program have the format: 3132 * 'tag file /pattern/;"<Tab>file:' " 3133 * 3134 * Return TRUE if it is a static tag and adjust *tagname to the real tag. 3135 * Return FALSE if it is not a static tag. 3136 */ 3137 static int 3138 test_for_static(tagptrs_T *tagp) 3139 { 3140 char_u *p; 3141 3142 /* 3143 * Check for new style static tag ":...<Tab>file:[<Tab>...]" 3144 */ 3145 p = tagp->command; 3146 while ((p = vim_strchr(p, '\t')) != NULL) 3147 { 3148 ++p; 3149 if (STRNCMP(p, "file:", 5) == 0) 3150 return TRUE; 3151 } 3152 3153 return FALSE; 3154 } 3155 3156 /* 3157 * Returns the length of a matching tag line. 3158 */ 3159 static size_t 3160 matching_line_len(char_u *lbuf) 3161 { 3162 char_u *p = lbuf + 1; 3163 3164 // does the same thing as parse_match() 3165 p += STRLEN(p) + 1; 3166 #ifdef FEAT_EMACS_TAGS 3167 p += STRLEN(p) + 1; 3168 #endif 3169 return (p - lbuf) + STRLEN(p); 3170 } 3171 3172 /* 3173 * Parse a line from a matching tag. Does not change the line itself. 3174 * 3175 * The line that we get looks like this: 3176 * Emacs tag: <mtt><tag_fname><NUL><ebuf><NUL><lbuf> 3177 * other tag: <mtt><tag_fname><NUL><NUL><lbuf> 3178 * without Emacs tags: <mtt><tag_fname><NUL><lbuf> 3179 * 3180 * Return OK or FAIL. 3181 */ 3182 static int 3183 parse_match( 3184 char_u *lbuf, // input: matching line 3185 tagptrs_T *tagp) // output: pointers into the line 3186 { 3187 int retval; 3188 char_u *p; 3189 char_u *pc, *pt; 3190 3191 tagp->tag_fname = lbuf + 1; 3192 lbuf += STRLEN(tagp->tag_fname) + 2; 3193 #ifdef FEAT_EMACS_TAGS 3194 if (*lbuf) 3195 { 3196 tagp->is_etag = TRUE; 3197 tagp->fname = lbuf; 3198 lbuf += STRLEN(lbuf); 3199 tagp->fname_end = lbuf++; 3200 } 3201 else 3202 { 3203 tagp->is_etag = FALSE; 3204 ++lbuf; 3205 } 3206 #endif 3207 3208 // Find search pattern and the file name for non-etags. 3209 retval = parse_tag_line(lbuf, 3210 #ifdef FEAT_EMACS_TAGS 3211 tagp->is_etag, 3212 #endif 3213 tagp); 3214 3215 tagp->tagkind = NULL; 3216 tagp->user_data = NULL; 3217 tagp->tagline = 0; 3218 tagp->command_end = NULL; 3219 3220 if (retval == OK) 3221 { 3222 // Try to find a kind field: "kind:<kind>" or just "<kind>" 3223 p = tagp->command; 3224 if (find_extra(&p) == OK) 3225 { 3226 if (p > tagp->command && p[-1] == '|') 3227 tagp->command_end = p - 1; // drop trailing bar 3228 else 3229 tagp->command_end = p; 3230 p += 2; // skip ";\"" 3231 if (*p++ == TAB) 3232 // Accept ASCII alphabetic kind characters and any multi-byte 3233 // character. 3234 while (ASCII_ISALPHA(*p) || mb_ptr2len(p) > 1) 3235 { 3236 if (STRNCMP(p, "kind:", 5) == 0) 3237 tagp->tagkind = p + 5; 3238 else if (STRNCMP(p, "user_data:", 10) == 0) 3239 tagp->user_data = p + 10; 3240 else if (STRNCMP(p, "line:", 5) == 0) 3241 tagp->tagline = atoi((char *)p + 5); 3242 if (tagp->tagkind != NULL && tagp->user_data != NULL) 3243 break; 3244 pc = vim_strchr(p, ':'); 3245 pt = vim_strchr(p, '\t'); 3246 if (pc == NULL || (pt != NULL && pc > pt)) 3247 tagp->tagkind = p; 3248 if (pt == NULL) 3249 break; 3250 p = pt; 3251 MB_PTR_ADV(p); 3252 } 3253 } 3254 if (tagp->tagkind != NULL) 3255 { 3256 for (p = tagp->tagkind; 3257 *p && *p != '\t' && *p != '\r' && *p != '\n'; MB_PTR_ADV(p)) 3258 ; 3259 tagp->tagkind_end = p; 3260 } 3261 if (tagp->user_data != NULL) 3262 { 3263 for (p = tagp->user_data; 3264 *p && *p != '\t' && *p != '\r' && *p != '\n'; MB_PTR_ADV(p)) 3265 ; 3266 tagp->user_data_end = p; 3267 } 3268 } 3269 return retval; 3270 } 3271 3272 /* 3273 * Find out the actual file name of a tag. Concatenate the tags file name 3274 * with the matching tag file name. 3275 * Returns an allocated string or NULL (out of memory). 3276 */ 3277 static char_u * 3278 tag_full_fname(tagptrs_T *tagp) 3279 { 3280 char_u *fullname; 3281 int c; 3282 3283 #ifdef FEAT_EMACS_TAGS 3284 if (tagp->is_etag) 3285 c = 0; // to shut up GCC 3286 else 3287 #endif 3288 { 3289 c = *tagp->fname_end; 3290 *tagp->fname_end = NUL; 3291 } 3292 fullname = expand_tag_fname(tagp->fname, tagp->tag_fname, FALSE); 3293 3294 #ifdef FEAT_EMACS_TAGS 3295 if (!tagp->is_etag) 3296 #endif 3297 *tagp->fname_end = c; 3298 3299 return fullname; 3300 } 3301 3302 /* 3303 * Jump to a tag that has been found in one of the tag files 3304 * 3305 * returns OK for success, NOTAGFILE when file not found, FAIL otherwise. 3306 */ 3307 static int 3308 jumpto_tag( 3309 char_u *lbuf_arg, // line from the tags file for this tag 3310 int forceit, // :ta with ! 3311 int keep_help) // keep help flag (FALSE for cscope) 3312 { 3313 int save_secure; 3314 int save_magic; 3315 int save_p_ws, save_p_scs, save_p_ic; 3316 linenr_T save_lnum; 3317 char_u *str; 3318 char_u *pbuf; // search pattern buffer 3319 char_u *pbuf_end; 3320 char_u *tofree_fname = NULL; 3321 char_u *fname; 3322 tagptrs_T tagp; 3323 int retval = FAIL; 3324 int getfile_result = GETFILE_UNUSED; 3325 int search_options; 3326 #ifdef FEAT_SEARCH_EXTRA 3327 int save_no_hlsearch; 3328 #endif 3329 #if defined(FEAT_QUICKFIX) 3330 win_T *curwin_save = NULL; 3331 #endif 3332 char_u *full_fname = NULL; 3333 #ifdef FEAT_FOLDING 3334 int old_KeyTyped = KeyTyped; // getting the file may reset it 3335 #endif 3336 size_t len; 3337 char_u *lbuf; 3338 3339 // Make a copy of the line, it can become invalid when an autocommand calls 3340 // back here recursively. 3341 len = matching_line_len(lbuf_arg) + 1; 3342 lbuf = alloc(len); 3343 if (lbuf != NULL) 3344 mch_memmove(lbuf, lbuf_arg, len); 3345 3346 pbuf = alloc(LSIZE); 3347 3348 // parse the match line into the tagp structure 3349 if (pbuf == NULL || lbuf == NULL || parse_match(lbuf, &tagp) == FAIL) 3350 { 3351 tagp.fname_end = NULL; 3352 goto erret; 3353 } 3354 3355 // truncate the file name, so it can be used as a string 3356 *tagp.fname_end = NUL; 3357 fname = tagp.fname; 3358 3359 // copy the command to pbuf[], remove trailing CR/NL 3360 str = tagp.command; 3361 for (pbuf_end = pbuf; *str && *str != '\n' && *str != '\r'; ) 3362 { 3363 #ifdef FEAT_EMACS_TAGS 3364 if (tagp.is_etag && *str == ',')// stop at ',' after line number 3365 break; 3366 #endif 3367 *pbuf_end++ = *str++; 3368 if (pbuf_end - pbuf + 1 >= LSIZE) 3369 break; 3370 } 3371 *pbuf_end = NUL; 3372 3373 #ifdef FEAT_EMACS_TAGS 3374 if (!tagp.is_etag) 3375 #endif 3376 { 3377 /* 3378 * Remove the "<Tab>fieldname:value" stuff; we don't need it here. 3379 */ 3380 str = pbuf; 3381 if (find_extra(&str) == OK) 3382 { 3383 pbuf_end = str; 3384 *pbuf_end = NUL; 3385 } 3386 } 3387 3388 /* 3389 * Expand file name, when needed (for environment variables). 3390 * If 'tagrelative' option set, may change file name. 3391 */ 3392 fname = expand_tag_fname(fname, tagp.tag_fname, TRUE); 3393 if (fname == NULL) 3394 goto erret; 3395 tofree_fname = fname; // free() it later 3396 3397 /* 3398 * Check if the file with the tag exists before abandoning the current 3399 * file. Also accept a file name for which there is a matching BufReadCmd 3400 * autocommand event (e.g., http://sys/file). 3401 */ 3402 if (mch_getperm(fname) < 0 && !has_autocmd(EVENT_BUFREADCMD, fname, NULL)) 3403 { 3404 retval = NOTAGFILE; 3405 vim_free(nofile_fname); 3406 nofile_fname = vim_strsave(fname); 3407 if (nofile_fname == NULL) 3408 nofile_fname = empty_option; 3409 goto erret; 3410 } 3411 3412 ++RedrawingDisabled; 3413 3414 #ifdef FEAT_GUI 3415 need_mouse_correct = TRUE; 3416 #endif 3417 3418 #if defined(FEAT_QUICKFIX) 3419 if (g_do_tagpreview != 0) 3420 { 3421 postponed_split = 0; // don't split again below 3422 curwin_save = curwin; // Save current window 3423 3424 /* 3425 * If we are reusing a window, we may change dir when 3426 * entering it (autocommands) so turn the tag filename 3427 * into a fullpath 3428 */ 3429 if (!curwin->w_p_pvw) 3430 { 3431 full_fname = FullName_save(fname, FALSE); 3432 fname = full_fname; 3433 3434 /* 3435 * Make the preview window the current window. 3436 * Open a preview window when needed. 3437 */ 3438 prepare_tagpreview(TRUE, TRUE, FALSE); 3439 } 3440 } 3441 3442 // If it was a CTRL-W CTRL-] command split window now. For ":tab tag" 3443 // open a new tab page. 3444 if (postponed_split && (swb_flags & (SWB_USEOPEN | SWB_USETAB))) 3445 { 3446 buf_T *existing_buf = buflist_findname_exp(fname); 3447 3448 if (existing_buf != NULL) 3449 { 3450 win_T *wp = NULL; 3451 3452 if (swb_flags & SWB_USEOPEN) 3453 wp = buf_jump_open_win(existing_buf); 3454 3455 // If 'switchbuf' contains "usetab": jump to first window in any tab 3456 // page containing "existing_buf" if one exists 3457 if (wp == NULL && (swb_flags & SWB_USETAB)) 3458 wp = buf_jump_open_tab(existing_buf); 3459 // We've switched to the buffer, the usual loading of the file must 3460 // be skipped. 3461 if (wp != NULL) 3462 getfile_result = GETFILE_SAME_FILE; 3463 } 3464 } 3465 if (getfile_result == GETFILE_UNUSED 3466 && (postponed_split || cmdmod.tab != 0)) 3467 { 3468 if (win_split(postponed_split > 0 ? postponed_split : 0, 3469 postponed_split_flags) == FAIL) 3470 { 3471 --RedrawingDisabled; 3472 goto erret; 3473 } 3474 RESET_BINDING(curwin); 3475 } 3476 #endif 3477 3478 if (keep_help) 3479 { 3480 // A :ta from a help file will keep the b_help flag set. For ":ptag" 3481 // we need to use the flag from the window where we came from. 3482 #if defined(FEAT_QUICKFIX) 3483 if (g_do_tagpreview != 0) 3484 keep_help_flag = bt_help(curwin_save->w_buffer); 3485 else 3486 #endif 3487 keep_help_flag = curbuf->b_help; 3488 } 3489 3490 if (getfile_result == GETFILE_UNUSED) 3491 // Careful: getfile() may trigger autocommands and call jumpto_tag() 3492 // recursively. 3493 getfile_result = getfile(0, fname, NULL, TRUE, (linenr_T)0, forceit); 3494 keep_help_flag = FALSE; 3495 3496 if (GETFILE_SUCCESS(getfile_result)) // got to the right file 3497 { 3498 curwin->w_set_curswant = TRUE; 3499 postponed_split = 0; 3500 3501 save_secure = secure; 3502 secure = 1; 3503 #ifdef HAVE_SANDBOX 3504 ++sandbox; 3505 #endif 3506 save_magic = p_magic; 3507 p_magic = FALSE; // always execute with 'nomagic' 3508 #ifdef FEAT_SEARCH_EXTRA 3509 // Save value of no_hlsearch, jumping to a tag is not a real search 3510 save_no_hlsearch = no_hlsearch; 3511 #endif 3512 3513 /* 3514 * If 'cpoptions' contains 't', store the search pattern for the "n" 3515 * command. If 'cpoptions' does not contain 't', the search pattern 3516 * is not stored. 3517 */ 3518 if (vim_strchr(p_cpo, CPO_TAGPAT) != NULL) 3519 search_options = 0; 3520 else 3521 search_options = SEARCH_KEEP; 3522 3523 /* 3524 * If the command is a search, try here. 3525 * 3526 * Reset 'smartcase' for the search, since the search pattern was not 3527 * typed by the user. 3528 * Only use do_search() when there is a full search command, without 3529 * anything following. 3530 */ 3531 str = pbuf; 3532 if (pbuf[0] == '/' || pbuf[0] == '?') 3533 str = skip_regexp(pbuf + 1, pbuf[0], FALSE) + 1; 3534 if (str > pbuf_end - 1) // search command with nothing following 3535 { 3536 save_p_ws = p_ws; 3537 save_p_ic = p_ic; 3538 save_p_scs = p_scs; 3539 p_ws = TRUE; // need 'wrapscan' for backward searches 3540 p_ic = FALSE; // don't ignore case now 3541 p_scs = FALSE; 3542 save_lnum = curwin->w_cursor.lnum; 3543 if (tagp.tagline > 0) 3544 // start search before line from "line:" field 3545 curwin->w_cursor.lnum = tagp.tagline - 1; 3546 else 3547 // start search before first line 3548 curwin->w_cursor.lnum = 0; 3549 if (do_search(NULL, pbuf[0], pbuf[0], pbuf + 1, (long)1, 3550 search_options, NULL)) 3551 retval = OK; 3552 else 3553 { 3554 int found = 1; 3555 int cc; 3556 3557 /* 3558 * try again, ignore case now 3559 */ 3560 p_ic = TRUE; 3561 if (!do_search(NULL, pbuf[0], pbuf[0], pbuf + 1, (long)1, 3562 search_options, NULL)) 3563 { 3564 /* 3565 * Failed to find pattern, take a guess: "^func (" 3566 */ 3567 found = 2; 3568 (void)test_for_static(&tagp); 3569 cc = *tagp.tagname_end; 3570 *tagp.tagname_end = NUL; 3571 sprintf((char *)pbuf, "^%s\\s\\*(", tagp.tagname); 3572 if (!do_search(NULL, '/', '/', pbuf, (long)1, 3573 search_options, NULL)) 3574 { 3575 // Guess again: "^char * \<func (" 3576 sprintf((char *)pbuf, "^\\[#a-zA-Z_]\\.\\*\\<%s\\s\\*(", 3577 tagp.tagname); 3578 if (!do_search(NULL, '/', '/', pbuf, (long)1, 3579 search_options, NULL)) 3580 found = 0; 3581 } 3582 *tagp.tagname_end = cc; 3583 } 3584 if (found == 0) 3585 { 3586 emsg(_("E434: Can't find tag pattern")); 3587 curwin->w_cursor.lnum = save_lnum; 3588 } 3589 else 3590 { 3591 /* 3592 * Only give a message when really guessed, not when 'ic' 3593 * is set and match found while ignoring case. 3594 */ 3595 if (found == 2 || !save_p_ic) 3596 { 3597 msg(_("E435: Couldn't find tag, just guessing!")); 3598 if (!msg_scrolled && msg_silent == 0) 3599 { 3600 out_flush(); 3601 ui_delay(1010L, TRUE); 3602 } 3603 } 3604 retval = OK; 3605 } 3606 } 3607 p_ws = save_p_ws; 3608 p_ic = save_p_ic; 3609 p_scs = save_p_scs; 3610 3611 // A search command may have positioned the cursor beyond the end 3612 // of the line. May need to correct that here. 3613 check_cursor(); 3614 } 3615 else 3616 { 3617 curwin->w_cursor.lnum = 1; // start command in line 1 3618 do_cmdline_cmd(pbuf); 3619 retval = OK; 3620 } 3621 3622 /* 3623 * When the command has done something that is not allowed make sure 3624 * the error message can be seen. 3625 */ 3626 if (secure == 2) 3627 wait_return(TRUE); 3628 secure = save_secure; 3629 p_magic = save_magic; 3630 #ifdef HAVE_SANDBOX 3631 --sandbox; 3632 #endif 3633 #ifdef FEAT_SEARCH_EXTRA 3634 // restore no_hlsearch when keeping the old search pattern 3635 if (search_options) 3636 set_no_hlsearch(save_no_hlsearch); 3637 #endif 3638 3639 // Return OK if jumped to another file (at least we found the file!). 3640 if (getfile_result == GETFILE_OPEN_OTHER) 3641 retval = OK; 3642 3643 if (retval == OK) 3644 { 3645 /* 3646 * For a help buffer: Put the cursor line at the top of the window, 3647 * the help subject will be below it. 3648 */ 3649 if (curbuf->b_help) 3650 set_topline(curwin, curwin->w_cursor.lnum); 3651 #ifdef FEAT_FOLDING 3652 if ((fdo_flags & FDO_TAG) && old_KeyTyped) 3653 foldOpenCursor(); 3654 #endif 3655 } 3656 3657 #if defined(FEAT_QUICKFIX) 3658 if (g_do_tagpreview != 0 3659 && curwin != curwin_save && win_valid(curwin_save)) 3660 { 3661 // Return cursor to where we were 3662 validate_cursor(); 3663 redraw_later(VALID); 3664 win_enter(curwin_save, TRUE); 3665 } 3666 #endif 3667 3668 --RedrawingDisabled; 3669 } 3670 else 3671 { 3672 --RedrawingDisabled; 3673 got_int = FALSE; // don't want entering window to fail 3674 3675 if (postponed_split) // close the window 3676 { 3677 win_close(curwin, FALSE); 3678 postponed_split = 0; 3679 } 3680 #if defined(FEAT_QUICKFIX) && defined(FEAT_PROP_POPUP) 3681 else if (WIN_IS_POPUP(curwin)) 3682 { 3683 win_T *wp = curwin; 3684 3685 if (win_valid(curwin_save)) 3686 win_enter(curwin_save, TRUE); 3687 popup_close(wp->w_id, FALSE); 3688 } 3689 #endif 3690 } 3691 #if defined(FEAT_QUICKFIX) && defined(FEAT_PROP_POPUP) 3692 if (WIN_IS_POPUP(curwin)) 3693 // something went wrong, still in popup, but it can't have focus 3694 win_enter(firstwin, TRUE); 3695 #endif 3696 3697 erret: 3698 #if defined(FEAT_QUICKFIX) 3699 g_do_tagpreview = 0; // For next time 3700 #endif 3701 vim_free(lbuf); 3702 vim_free(pbuf); 3703 vim_free(tofree_fname); 3704 vim_free(full_fname); 3705 3706 return retval; 3707 } 3708 3709 /* 3710 * If "expand" is TRUE, expand wildcards in fname. 3711 * If 'tagrelative' option set, change fname (name of file containing tag) 3712 * according to tag_fname (name of tag file containing fname). 3713 * Returns a pointer to allocated memory (or NULL when out of memory). 3714 */ 3715 static char_u * 3716 expand_tag_fname(char_u *fname, char_u *tag_fname, int expand) 3717 { 3718 char_u *p; 3719 char_u *retval; 3720 char_u *expanded_fname = NULL; 3721 expand_T xpc; 3722 3723 /* 3724 * Expand file name (for environment variables) when needed. 3725 */ 3726 if (expand && mch_has_wildcard(fname)) 3727 { 3728 ExpandInit(&xpc); 3729 xpc.xp_context = EXPAND_FILES; 3730 expanded_fname = ExpandOne(&xpc, (char_u *)fname, NULL, 3731 WILD_LIST_NOTFOUND|WILD_SILENT, WILD_EXPAND_FREE); 3732 if (expanded_fname != NULL) 3733 fname = expanded_fname; 3734 } 3735 3736 if ((p_tr || curbuf->b_help) 3737 && !vim_isAbsName(fname) 3738 && (p = gettail(tag_fname)) != tag_fname) 3739 { 3740 retval = alloc(MAXPATHL); 3741 if (retval != NULL) 3742 { 3743 STRCPY(retval, tag_fname); 3744 vim_strncpy(retval + (p - tag_fname), fname, 3745 MAXPATHL - (p - tag_fname) - 1); 3746 /* 3747 * Translate names like "src/a/../b/file.c" into "src/b/file.c". 3748 */ 3749 simplify_filename(retval); 3750 } 3751 } 3752 else 3753 retval = vim_strsave(fname); 3754 3755 vim_free(expanded_fname); 3756 3757 return retval; 3758 } 3759 3760 /* 3761 * Check if we have a tag for the buffer with name "buf_ffname". 3762 * This is a bit slow, because of the full path compare in fullpathcmp(). 3763 * Return TRUE if tag for file "fname" if tag file "tag_fname" is for current 3764 * file. 3765 */ 3766 static int 3767 test_for_current( 3768 #ifdef FEAT_EMACS_TAGS 3769 int is_etag, 3770 #endif 3771 char_u *fname, 3772 char_u *fname_end, 3773 char_u *tag_fname, 3774 char_u *buf_ffname) 3775 { 3776 int c; 3777 int retval = FALSE; 3778 char_u *fullname; 3779 3780 if (buf_ffname != NULL) // if the buffer has a name 3781 { 3782 #ifdef FEAT_EMACS_TAGS 3783 if (is_etag) 3784 c = 0; // to shut up GCC 3785 else 3786 #endif 3787 { 3788 c = *fname_end; 3789 *fname_end = NUL; 3790 } 3791 fullname = expand_tag_fname(fname, tag_fname, TRUE); 3792 if (fullname != NULL) 3793 { 3794 retval = (fullpathcmp(fullname, buf_ffname, TRUE, TRUE) & FPC_SAME); 3795 vim_free(fullname); 3796 } 3797 #ifdef FEAT_EMACS_TAGS 3798 if (!is_etag) 3799 #endif 3800 *fname_end = c; 3801 } 3802 3803 return retval; 3804 } 3805 3806 /* 3807 * Find the end of the tagaddress. 3808 * Return OK if ";\"" is following, FAIL otherwise. 3809 */ 3810 static int 3811 find_extra(char_u **pp) 3812 { 3813 char_u *str = *pp; 3814 char_u first_char = **pp; 3815 3816 // Repeat for addresses separated with ';' 3817 for (;;) 3818 { 3819 if (VIM_ISDIGIT(*str)) 3820 str = skipdigits(str); 3821 else if (*str == '/' || *str == '?') 3822 { 3823 str = skip_regexp(str + 1, *str, FALSE); 3824 if (*str != first_char) 3825 str = NULL; 3826 else 3827 ++str; 3828 } 3829 else 3830 { 3831 // not a line number or search string, look for terminator. 3832 str = (char_u *)strstr((char *)str, "|;\""); 3833 if (str != NULL) 3834 { 3835 ++str; 3836 break; 3837 } 3838 3839 } 3840 if (str == NULL || *str != ';' 3841 || !(VIM_ISDIGIT(str[1]) || str[1] == '/' || str[1] == '?')) 3842 break; 3843 ++str; // skip ';' 3844 first_char = *str; 3845 } 3846 3847 if (str != NULL && STRNCMP(str, ";\"", 2) == 0) 3848 { 3849 *pp = str; 3850 return OK; 3851 } 3852 return FAIL; 3853 } 3854 3855 /* 3856 * Free a single entry in a tag stack 3857 */ 3858 static void 3859 tagstack_clear_entry(taggy_T *item) 3860 { 3861 VIM_CLEAR(item->tagname); 3862 VIM_CLEAR(item->user_data); 3863 } 3864 3865 int 3866 expand_tags( 3867 int tagnames, // expand tag names 3868 char_u *pat, 3869 int *num_file, 3870 char_u ***file) 3871 { 3872 int i; 3873 int c; 3874 int tagnmflag; 3875 char_u tagnm[100]; 3876 tagptrs_T t_p; 3877 int ret; 3878 3879 if (tagnames) 3880 tagnmflag = TAG_NAMES; 3881 else 3882 tagnmflag = 0; 3883 if (pat[0] == '/') 3884 ret = find_tags(pat + 1, num_file, file, 3885 TAG_REGEXP | tagnmflag | TAG_VERBOSE | TAG_NO_TAGFUNC, 3886 TAG_MANY, curbuf->b_ffname); 3887 else 3888 ret = find_tags(pat, num_file, file, 3889 TAG_REGEXP | tagnmflag | TAG_VERBOSE | TAG_NO_TAGFUNC | TAG_NOIC, 3890 TAG_MANY, curbuf->b_ffname); 3891 if (ret == OK && !tagnames) 3892 { 3893 // Reorganize the tags for display and matching as strings of: 3894 // "<tagname>\0<kind>\0<filename>\0" 3895 for (i = 0; i < *num_file; i++) 3896 { 3897 parse_match((*file)[i], &t_p); 3898 c = (int)(t_p.tagname_end - t_p.tagname); 3899 mch_memmove(tagnm, t_p.tagname, (size_t)c); 3900 tagnm[c++] = 0; 3901 tagnm[c++] = (t_p.tagkind != NULL && *t_p.tagkind) 3902 ? *t_p.tagkind : 'f'; 3903 tagnm[c++] = 0; 3904 mch_memmove((*file)[i] + c, t_p.fname, t_p.fname_end - t_p.fname); 3905 (*file)[i][c + (t_p.fname_end - t_p.fname)] = 0; 3906 mch_memmove((*file)[i], tagnm, (size_t)c); 3907 } 3908 } 3909 return ret; 3910 } 3911 3912 #if defined(FEAT_EVAL) || defined(PROTO) 3913 /* 3914 * Add a tag field to the dictionary "dict". 3915 * Return OK or FAIL. 3916 */ 3917 static int 3918 add_tag_field( 3919 dict_T *dict, 3920 char *field_name, 3921 char_u *start, // start of the value 3922 char_u *end) // after the value; can be NULL 3923 { 3924 char_u *buf; 3925 int len = 0; 3926 int retval; 3927 3928 // check that the field name doesn't exist yet 3929 if (dict_find(dict, (char_u *)field_name, -1) != NULL) 3930 { 3931 if (p_verbose > 0) 3932 { 3933 verbose_enter(); 3934 smsg(_("Duplicate field name: %s"), field_name); 3935 verbose_leave(); 3936 } 3937 return FAIL; 3938 } 3939 buf = alloc(MAXPATHL); 3940 if (buf == NULL) 3941 return FAIL; 3942 if (start != NULL) 3943 { 3944 if (end == NULL) 3945 { 3946 end = start + STRLEN(start); 3947 while (end > start && (end[-1] == '\r' || end[-1] == '\n')) 3948 --end; 3949 } 3950 len = (int)(end - start); 3951 if (len > MAXPATHL - 1) 3952 len = MAXPATHL - 1; 3953 vim_strncpy(buf, start, len); 3954 } 3955 buf[len] = NUL; 3956 retval = dict_add_string(dict, field_name, buf); 3957 vim_free(buf); 3958 return retval; 3959 } 3960 3961 /* 3962 * Add the tags matching the specified pattern "pat" to the list "list" 3963 * as a dictionary. Use "buf_fname" for priority, unless NULL. 3964 */ 3965 int 3966 get_tags(list_T *list, char_u *pat, char_u *buf_fname) 3967 { 3968 int num_matches, i, ret; 3969 char_u **matches, *p; 3970 char_u *full_fname; 3971 dict_T *dict; 3972 tagptrs_T tp; 3973 long is_static; 3974 3975 ret = find_tags(pat, &num_matches, &matches, 3976 TAG_REGEXP | TAG_NOIC, (int)MAXCOL, buf_fname); 3977 if (ret == OK && num_matches > 0) 3978 { 3979 for (i = 0; i < num_matches; ++i) 3980 { 3981 parse_match(matches[i], &tp); 3982 is_static = test_for_static(&tp); 3983 3984 // Skip pseudo-tag lines. 3985 if (STRNCMP(tp.tagname, "!_TAG_", 6) == 0) 3986 { 3987 vim_free(matches[i]); 3988 continue; 3989 } 3990 3991 if ((dict = dict_alloc()) == NULL) 3992 ret = FAIL; 3993 if (list_append_dict(list, dict) == FAIL) 3994 ret = FAIL; 3995 3996 full_fname = tag_full_fname(&tp); 3997 if (add_tag_field(dict, "name", tp.tagname, tp.tagname_end) == FAIL 3998 || add_tag_field(dict, "filename", full_fname, 3999 NULL) == FAIL 4000 || add_tag_field(dict, "cmd", tp.command, 4001 tp.command_end) == FAIL 4002 || add_tag_field(dict, "kind", tp.tagkind, 4003 tp.tagkind_end) == FAIL 4004 || dict_add_number(dict, "static", is_static) == FAIL) 4005 ret = FAIL; 4006 4007 vim_free(full_fname); 4008 4009 if (tp.command_end != NULL) 4010 { 4011 for (p = tp.command_end + 3; 4012 *p != NUL && *p != '\n' && *p != '\r'; MB_PTR_ADV(p)) 4013 { 4014 if (p == tp.tagkind || (p + 5 == tp.tagkind 4015 && STRNCMP(p, "kind:", 5) == 0)) 4016 // skip "kind:<kind>" and "<kind>" 4017 p = tp.tagkind_end - 1; 4018 else if (STRNCMP(p, "file:", 5) == 0) 4019 // skip "file:" (static tag) 4020 p += 4; 4021 else if (!VIM_ISWHITE(*p)) 4022 { 4023 char_u *s, *n; 4024 int len; 4025 4026 // Add extra field as a dict entry. Fields are 4027 // separated by Tabs. 4028 n = p; 4029 while (*p != NUL && *p >= ' ' && *p < 127 && *p != ':') 4030 ++p; 4031 len = (int)(p - n); 4032 if (*p == ':' && len > 0) 4033 { 4034 s = ++p; 4035 while (*p != NUL && *p >= ' ') 4036 ++p; 4037 n[len] = NUL; 4038 if (add_tag_field(dict, (char *)n, s, p) == FAIL) 4039 ret = FAIL; 4040 n[len] = ':'; 4041 } 4042 else 4043 // Skip field without colon. 4044 while (*p != NUL && *p >= ' ') 4045 ++p; 4046 if (*p == NUL) 4047 break; 4048 } 4049 } 4050 } 4051 4052 vim_free(matches[i]); 4053 } 4054 vim_free(matches); 4055 } 4056 return ret; 4057 } 4058 4059 /* 4060 * Return information about 'tag' in dict 'retdict'. 4061 */ 4062 static void 4063 get_tag_details(taggy_T *tag, dict_T *retdict) 4064 { 4065 list_T *pos; 4066 fmark_T *fmark; 4067 4068 dict_add_string(retdict, "tagname", tag->tagname); 4069 dict_add_number(retdict, "matchnr", tag->cur_match + 1); 4070 dict_add_number(retdict, "bufnr", tag->cur_fnum); 4071 if (tag->user_data) 4072 dict_add_string(retdict, "user_data", tag->user_data); 4073 4074 if ((pos = list_alloc_id(aid_tagstack_from)) == NULL) 4075 return; 4076 dict_add_list(retdict, "from", pos); 4077 4078 fmark = &tag->fmark; 4079 list_append_number(pos, 4080 (varnumber_T)(fmark->fnum != -1 ? fmark->fnum : 0)); 4081 list_append_number(pos, (varnumber_T)fmark->mark.lnum); 4082 list_append_number(pos, (varnumber_T)(fmark->mark.col == MAXCOL ? 4083 MAXCOL : fmark->mark.col + 1)); 4084 list_append_number(pos, (varnumber_T)fmark->mark.coladd); 4085 } 4086 4087 /* 4088 * Return the tag stack entries of the specified window 'wp' in dictionary 4089 * 'retdict'. 4090 */ 4091 void 4092 get_tagstack(win_T *wp, dict_T *retdict) 4093 { 4094 list_T *l; 4095 int i; 4096 dict_T *d; 4097 4098 dict_add_number(retdict, "length", wp->w_tagstacklen); 4099 dict_add_number(retdict, "curidx", wp->w_tagstackidx + 1); 4100 l = list_alloc_id(aid_tagstack_items); 4101 if (l == NULL) 4102 return; 4103 dict_add_list(retdict, "items", l); 4104 4105 for (i = 0; i < wp->w_tagstacklen; i++) 4106 { 4107 if ((d = dict_alloc_id(aid_tagstack_details)) == NULL) 4108 return; 4109 list_append_dict(l, d); 4110 4111 get_tag_details(&wp->w_tagstack[i], d); 4112 } 4113 } 4114 4115 /* 4116 * Free all the entries in the tag stack of the specified window 4117 */ 4118 static void 4119 tagstack_clear(win_T *wp) 4120 { 4121 int i; 4122 4123 // Free the current tag stack 4124 for (i = 0; i < wp->w_tagstacklen; ++i) 4125 tagstack_clear_entry(&wp->w_tagstack[i]); 4126 wp->w_tagstacklen = 0; 4127 wp->w_tagstackidx = 0; 4128 } 4129 4130 /* 4131 * Remove the oldest entry from the tag stack and shift the rest of 4132 * the entries to free up the top of the stack. 4133 */ 4134 static void 4135 tagstack_shift(win_T *wp) 4136 { 4137 taggy_T *tagstack = wp->w_tagstack; 4138 int i; 4139 4140 tagstack_clear_entry(&tagstack[0]); 4141 for (i = 1; i < wp->w_tagstacklen; ++i) 4142 tagstack[i - 1] = tagstack[i]; 4143 wp->w_tagstacklen--; 4144 } 4145 4146 /* 4147 * Push a new item to the tag stack 4148 */ 4149 static void 4150 tagstack_push_item( 4151 win_T *wp, 4152 char_u *tagname, 4153 int cur_fnum, 4154 int cur_match, 4155 pos_T mark, 4156 int fnum, 4157 char_u *user_data) 4158 { 4159 taggy_T *tagstack = wp->w_tagstack; 4160 int idx = wp->w_tagstacklen; // top of the stack 4161 4162 // if the tagstack is full: remove the oldest entry 4163 if (idx >= TAGSTACKSIZE) 4164 { 4165 tagstack_shift(wp); 4166 idx = TAGSTACKSIZE - 1; 4167 } 4168 4169 wp->w_tagstacklen++; 4170 tagstack[idx].tagname = tagname; 4171 tagstack[idx].cur_fnum = cur_fnum; 4172 tagstack[idx].cur_match = cur_match; 4173 if (tagstack[idx].cur_match < 0) 4174 tagstack[idx].cur_match = 0; 4175 tagstack[idx].fmark.mark = mark; 4176 tagstack[idx].fmark.fnum = fnum; 4177 tagstack[idx].user_data = user_data; 4178 } 4179 4180 /* 4181 * Add a list of items to the tag stack in the specified window 4182 */ 4183 static void 4184 tagstack_push_items(win_T *wp, list_T *l) 4185 { 4186 listitem_T *li; 4187 dictitem_T *di; 4188 dict_T *itemdict; 4189 char_u *tagname; 4190 pos_T mark; 4191 int fnum; 4192 4193 // Add one entry at a time to the tag stack 4194 FOR_ALL_LIST_ITEMS(l, li) 4195 { 4196 if (li->li_tv.v_type != VAR_DICT || li->li_tv.vval.v_dict == NULL) 4197 continue; // Skip non-dict items 4198 itemdict = li->li_tv.vval.v_dict; 4199 4200 // parse 'from' for the cursor position before the tag jump 4201 if ((di = dict_find(itemdict, (char_u *)"from", -1)) == NULL) 4202 continue; 4203 if (list2fpos(&di->di_tv, &mark, &fnum, NULL) != OK) 4204 continue; 4205 if ((tagname = 4206 dict_get_string(itemdict, (char_u *)"tagname", TRUE)) == NULL) 4207 continue; 4208 4209 if (mark.col > 0) 4210 mark.col--; 4211 tagstack_push_item(wp, tagname, 4212 (int)dict_get_number(itemdict, (char_u *)"bufnr"), 4213 (int)dict_get_number(itemdict, (char_u *)"matchnr") - 1, 4214 mark, fnum, 4215 dict_get_string(itemdict, (char_u *)"user_data", TRUE)); 4216 } 4217 } 4218 4219 /* 4220 * Set the current index in the tag stack. Valid values are between 0 4221 * and the stack length (inclusive). 4222 */ 4223 static void 4224 tagstack_set_curidx(win_T *wp, int curidx) 4225 { 4226 wp->w_tagstackidx = curidx; 4227 if (wp->w_tagstackidx < 0) // sanity check 4228 wp->w_tagstackidx = 0; 4229 if (wp->w_tagstackidx > wp->w_tagstacklen) 4230 wp->w_tagstackidx = wp->w_tagstacklen; 4231 } 4232 4233 /* 4234 * Set the tag stack entries of the specified window. 4235 * 'action' is set to one of: 4236 * 'a' for append 4237 * 'r' for replace 4238 * 't' for truncate 4239 */ 4240 int 4241 set_tagstack(win_T *wp, dict_T *d, int action) 4242 { 4243 dictitem_T *di; 4244 list_T *l = NULL; 4245 4246 #ifdef FEAT_EVAL 4247 // not allowed to alter the tag stack entries from inside tagfunc 4248 if (tfu_in_use) 4249 { 4250 emsg(_(recurmsg)); 4251 return FAIL; 4252 } 4253 #endif 4254 4255 if ((di = dict_find(d, (char_u *)"items", -1)) != NULL) 4256 { 4257 if (di->di_tv.v_type != VAR_LIST) 4258 { 4259 emsg(_(e_listreq)); 4260 return FAIL; 4261 } 4262 l = di->di_tv.vval.v_list; 4263 } 4264 4265 if ((di = dict_find(d, (char_u *)"curidx", -1)) != NULL) 4266 tagstack_set_curidx(wp, (int)tv_get_number(&di->di_tv) - 1); 4267 4268 if (action == 't') // truncate the stack 4269 { 4270 taggy_T *tagstack = wp->w_tagstack; 4271 int tagstackidx = wp->w_tagstackidx; 4272 int tagstacklen = wp->w_tagstacklen; 4273 4274 // delete all the tag stack entries above the current entry 4275 while (tagstackidx < tagstacklen) 4276 tagstack_clear_entry(&tagstack[--tagstacklen]); 4277 wp->w_tagstacklen = tagstacklen; 4278 } 4279 4280 if (l != NULL) 4281 { 4282 if (action == 'r') // replace the stack 4283 tagstack_clear(wp); 4284 4285 tagstack_push_items(wp, l); 4286 // set the current index after the last entry 4287 wp->w_tagstackidx = wp->w_tagstacklen; 4288 } 4289 4290 return OK; 4291 } 4292 #endif 4293