comparison src/tag.c @ 692:a28f83d37113

updated for version 7.0208
author vimboss
date Mon, 27 Feb 2006 00:08:02 +0000
parents d7e33248b9c8
children e402b0af6083
comparison
equal deleted inserted replaced
691:8106f3da02d0 692:a28f83d37113
354 #endif 354 #endif
355 num_matches = 0; 355 num_matches = 0;
356 goto end_do_tag; 356 goto end_do_tag;
357 } 357 }
358 358
359 if (type == DT_TAG) 359 if (type == DT_TAG
360 #if defined(FEAT_QUICKFIX)
361 || type == DT_LTAG
362 #endif
363 )
360 { 364 {
361 #if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX) 365 #if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
362 if (g_do_tagpreview) 366 if (g_do_tagpreview)
363 { 367 {
364 cur_match = ptag_entry.cur_match; 368 cur_match = ptag_entry.cur_match;
411 cur_fnum = tagstack[tagstackidx].cur_fnum; 415 cur_fnum = tagstack[tagstackidx].cur_fnum;
412 } 416 }
413 switch (type) 417 switch (type)
414 { 418 {
415 case DT_FIRST: cur_match = count - 1; break; 419 case DT_FIRST: cur_match = count - 1; break;
416 #ifdef FEAT_QUICKFIX
417 case DT_LTAG: cur_match = 0; break;
418 #endif
419 case DT_SELECT: 420 case DT_SELECT:
420 case DT_JUMP: 421 case DT_JUMP:
421 #ifdef FEAT_CSCOPE 422 #ifdef FEAT_CSCOPE
422 case DT_CSCOPE: 423 case DT_CSCOPE:
423 #endif 424 #endif
514 * jump to count'th matching tag. 515 * jump to count'th matching tag.
515 */ 516 */
516 if (type == DT_TAG && count > 0) 517 if (type == DT_TAG && count > 0)
517 cur_match = count - 1; 518 cur_match = count - 1;
518 519
519 if (type == DT_SELECT || type == DT_JUMP) 520 if (type == DT_SELECT || type == DT_JUMP
521 #if defined(FEAT_QUICKFIX)
522 || type == DT_LTAG
523 #endif
524 )
520 cur_match = MAXCOL - 1; 525 cur_match = MAXCOL - 1;
521 max_num_matches = cur_match + 1; 526 max_num_matches = cur_match + 1;
522 527
523 /* when the argument starts with '/', use it as a regexp */ 528 /* when the argument starts with '/', use it as a regexp */
524 if (!no_regexp && *name == '/') 529 if (!no_regexp && *name == '/')
761 } 766 }
762 } 767 }
763 ask_for_selection = TRUE; 768 ask_for_selection = TRUE;
764 } 769 }
765 #if defined(FEAT_QUICKFIX) && defined(FEAT_EVAL) 770 #if defined(FEAT_QUICKFIX) && defined(FEAT_EVAL)
766 else 771 else if (type == DT_LTAG)
767 if (type == DT_LTAG)
768 { 772 {
769 list_T *list; 773 list_T *list;
770 char_u tag_name[128 + 1]; 774 char_u tag_name[128 + 1];
771 char_u fname[MAXPATHL + 1]; 775 char_u fname[MAXPATHL + 1];
772 char_u cmd[CMDBUFFSIZE + 1]; 776 char_u cmd[CMDBUFFSIZE + 1];
824 for (p = tagp.command; 828 for (p = tagp.command;
825 *p && *p != '\r' && *p != '\n'; ++p) 829 *p && *p != '\r' && *p != '\n'; ++p)
826 ; 830 ;
827 cmd_end = p; 831 cmd_end = p;
828 } 832 }
833
829 /* 834 /*
830 * Now, cmd_end points to the character after the 835 * Now, cmd_end points to the character after the
831 * command. Adjust it to point to the last 836 * command. Adjust it to point to the last
832 * character of the command. 837 * character of the command.
833 */ 838 */
870 STRNCAT(cmd, cmd_start, cmd_len); 875 STRNCAT(cmd, cmd_start, cmd_len);
871 len += cmd_len; 876 len += cmd_len;
872 877
873 if (cmd[len - 1] == '$') 878 if (cmd[len - 1] == '$')
874 { 879 {
875 /* 880 /*
876 * Replace '$' at the end of the search pattern 881 * Replace '$' at the end of the search pattern
877 * with '\$' 882 * with '\$'
878 */ 883 */
879 cmd[len - 1] = '\\'; 884 cmd[len - 1] = '\\';
880 cmd[len] = '$'; 885 cmd[len] = '$';
900 } 905 }
901 906
902 set_errorlist(curwin, list, ' '); 907 set_errorlist(curwin, list, ' ');
903 908
904 list_free(list); 909 list_free(list);
910
911 cur_match = 0; /* Jump to the first tag */
905 } 912 }
906 #endif 913 #endif
907 914
908 if (ask_for_selection == TRUE) 915 if (ask_for_selection == TRUE)
909 { 916 {
1256 char_u *buf_ffname; /* name of buffer for priority */ 1263 char_u *buf_ffname; /* name of buffer for priority */
1257 { 1264 {
1258 FILE *fp; 1265 FILE *fp;
1259 char_u *lbuf; /* line buffer */ 1266 char_u *lbuf; /* line buffer */
1260 char_u *tag_fname; /* name of tag file */ 1267 char_u *tag_fname; /* name of tag file */
1268 tagname_T tn; /* info for get_tagfname() */
1261 int first_file; /* trying first tag file */ 1269 int first_file; /* trying first tag file */
1262 tagptrs_T tagp; 1270 tagptrs_T tagp;
1263 int did_open = FALSE; /* did open a tag file */ 1271 int did_open = FALSE; /* did open a tag file */
1264 int stop_searching = FALSE; /* stop when match found or error */ 1272 int stop_searching = FALSE; /* stop when match found or error */
1265 int retval = FAIL; /* return value */ 1273 int retval = FAIL; /* return value */
1459 */ 1467 */
1460 for (first_file = TRUE; 1468 for (first_file = TRUE;
1461 #ifdef FEAT_CSCOPE 1469 #ifdef FEAT_CSCOPE
1462 use_cscope || 1470 use_cscope ||
1463 #endif 1471 #endif
1464 get_tagfname(first_file, tag_fname) == OK; first_file = FALSE) 1472 get_tagfname(&tn, first_file, tag_fname) == OK;
1473 first_file = FALSE)
1465 { 1474 {
1466 /* 1475 /*
1467 * A file that doesn't exist is silently ignored. Only when not a 1476 * A file that doesn't exist is silently ignored. Only when not a
1468 * single file is found, an error message is given (further on). 1477 * single file is found, an error message is given (further on).
1469 */ 1478 */
2427 #endif 2436 #endif
2428 break; 2437 break;
2429 2438
2430 } /* end of for-each-file loop */ 2439 } /* end of for-each-file loop */
2431 2440
2441 #ifdef FEAT_CSCOPE
2442 if (!use_cscope)
2443 #endif
2444 tagname_free(&tn);
2445
2432 #ifdef FEAT_TAG_BINS 2446 #ifdef FEAT_TAG_BINS
2433 /* stop searching when already did a linear search, or when TAG_NOIC 2447 /* stop searching when already did a linear search, or when TAG_NOIC
2434 * used, and 'ignorecase' not set or already did case-ignore search */ 2448 * used, and 'ignorecase' not set or already did case-ignore search */
2435 if (stop_searching || linear || (!p_ic && noic) || pats->regmatch.rm_ic) 2449 if (stop_searching || linear || (!p_ic && noic) || pats->regmatch.rm_ic)
2436 break; 2450 break;
2517 if (ga_grow(&tag_fnames, 1) == OK) 2531 if (ga_grow(&tag_fnames, 1) == OK)
2518 ((char_u **)(tag_fnames.ga_data))[tag_fnames.ga_len++] = 2532 ((char_u **)(tag_fnames.ga_data))[tag_fnames.ga_len++] =
2519 vim_strsave(fname); 2533 vim_strsave(fname);
2520 } 2534 }
2521 2535
2522 static void *search_ctx = NULL;
2523
2524 #if defined(EXITFREE) || defined(PROTO) 2536 #if defined(EXITFREE) || defined(PROTO)
2525 void 2537 void
2526 free_tag_stuff() 2538 free_tag_stuff()
2527 { 2539 {
2528 vim_findfile_cleanup(search_ctx); 2540 ga_clear_strings(&tag_fnames);
2529 do_tag(NULL, DT_FREE, 0, 0, 0); 2541 do_tag(NULL, DT_FREE, 0, 0, 0);
2530 } 2542 }
2531 #endif 2543 #endif
2532 2544
2533 /* 2545 /*
2535 * For help files, use "tags" file only. 2547 * For help files, use "tags" file only.
2536 * 2548 *
2537 * Return FAIL if no more tag file names, OK otherwise. 2549 * Return FAIL if no more tag file names, OK otherwise.
2538 */ 2550 */
2539 int 2551 int
2540 get_tagfname(first, buf) 2552 get_tagfname(tnp, first, buf)
2553 tagname_T *tnp; /* holds status info */
2541 int first; /* TRUE when first file name is wanted */ 2554 int first; /* TRUE when first file name is wanted */
2542 char_u *buf; /* pointer to buffer of MAXPATHL chars */ 2555 char_u *buf; /* pointer to buffer of MAXPATHL chars */
2543 { 2556 {
2544 static char_u *np = NULL;
2545 static int did_filefind_init;
2546 static int hf_idx = 0;
2547 char_u *fname = NULL; 2557 char_u *fname = NULL;
2548 char_u *r_ptr; 2558 char_u *r_ptr;
2559
2560 if (first)
2561 vim_memset(tnp, 0, sizeof(tagname_T));
2549 2562
2550 if (curbuf->b_help) 2563 if (curbuf->b_help)
2551 { 2564 {
2552 /* 2565 /*
2553 * For help files it's done in a completely different way: 2566 * For help files it's done in a completely different way:
2571 # endif 2584 # endif
2572 #else 2585 #else
2573 "doc/tags" 2586 "doc/tags"
2574 #endif 2587 #endif
2575 , TRUE, found_tagfile_cb, NULL); 2588 , TRUE, found_tagfile_cb, NULL);
2576 hf_idx = 0; 2589 }
2577 } 2590
2578 2591 if (tnp->tn_hf_idx >= tag_fnames.ga_len)
2579 if (hf_idx >= tag_fnames.ga_len)
2580 { 2592 {
2581 /* Not found in 'runtimepath', use 'helpfile', if it exists and 2593 /* Not found in 'runtimepath', use 'helpfile', if it exists and
2582 * wasn't used yet, replacing "help.txt" with "tags". */ 2594 * wasn't used yet, replacing "help.txt" with "tags". */
2583 if (hf_idx > tag_fnames.ga_len || *p_hf == NUL) 2595 if (tnp->tn_hf_idx > tag_fnames.ga_len || *p_hf == NUL)
2584 return FAIL; 2596 return FAIL;
2585 ++hf_idx; 2597 ++tnp->tn_hf_idx;
2586 STRCPY(buf, p_hf); 2598 STRCPY(buf, p_hf);
2587 STRCPY(gettail(buf), "tags"); 2599 STRCPY(gettail(buf), "tags");
2588 } 2600 }
2589 else 2601 else
2590 vim_strncpy(buf, ((char_u **)(tag_fnames.ga_data))[hf_idx++], 2602 vim_strncpy(buf, ((char_u **)(tag_fnames.ga_data))[
2591 MAXPATHL - 1); 2603 tnp->tn_hf_idx++], MAXPATHL - 1);
2592 return OK; 2604 return OK;
2593 } 2605 }
2594 2606
2595 if (first) 2607 if (first)
2596 { 2608 {
2597 /* Init. */ 2609 /* Init. We make a copy of 'tags', because autocommands may change
2598 if (*curbuf->b_p_tags != NUL) 2610 * the value without notifying us. */
2599 np = curbuf->b_p_tags; 2611 tnp->tn_tags = vim_strsave((*curbuf->b_p_tags != NUL)
2612 ? curbuf->b_p_tags : p_tags);
2613 if (tnp->tn_tags == NULL)
2614 return FAIL;
2615 tnp->tn_np = tnp->tn_tags;
2616 }
2617
2618 /*
2619 * Loop until we have found a file name that can be used.
2620 * There are two states:
2621 * tnp->tn_did_filefind_init == FALSE: setup for next part in 'tags'.
2622 * tnp->tn_did_filefind_init == TRUE: find next file in this part.
2623 */
2624 for (;;)
2625 {
2626 if (tnp->tn_did_filefind_init)
2627 {
2628 fname = vim_findfile(tnp->tn_search_ctx);
2629 if (fname != NULL)
2630 break;
2631
2632 tnp->tn_did_filefind_init = FALSE;
2633 }
2600 else 2634 else
2601 np = p_tags; 2635 {
2602 vim_findfile_free_visited(search_ctx); 2636 char_u *filename = NULL;
2603 did_filefind_init = FALSE; 2637
2604 } 2638 /* Stop when used all parts of 'tags'. */
2605 else 2639 if (*tnp->tn_np == NUL)
2606 { 2640 {
2607 if (np == NULL) 2641 vim_findfile_cleanup(tnp->tn_search_ctx);
2608 return FAIL; /* tried already (or bogus call) */ 2642 tnp->tn_search_ctx = NULL;
2609 2643 return FAIL;
2610 /* 2644 }
2611 * Loop until we have found a file name that can be used. 2645
2612 * There are two states: 2646 /*
2613 * did_filefind_init == FALSE: setup for next part in 'tags'. 2647 * Copy next file name into buf.
2614 * did_filefind_init == TRUE: find next file in this part. 2648 */
2615 */ 2649 buf[0] = NUL;
2616 for (;;) 2650 (void)copy_option_part(&tnp->tn_np, buf, MAXPATHL - 1, " ,");
2617 {
2618 if (did_filefind_init)
2619 {
2620 fname = vim_findfile(search_ctx);
2621 if (fname != NULL)
2622 break;
2623
2624 did_filefind_init = FALSE;
2625 }
2626 else
2627 {
2628 char_u *filename = NULL;
2629
2630 /* Stop when used all parts of 'tags'. */
2631 if (*np == NUL)
2632 {
2633 vim_findfile_cleanup(search_ctx);
2634 search_ctx = NULL;
2635 return FAIL;
2636 }
2637
2638 /*
2639 * Copy next file name into buf.
2640 */
2641 buf[0] = NUL;
2642 (void)copy_option_part(&np, buf, MAXPATHL - 1, " ,");
2643 2651
2644 #ifdef FEAT_PATH_EXTRA 2652 #ifdef FEAT_PATH_EXTRA
2645 r_ptr = vim_findfile_stopdir(buf); 2653 r_ptr = vim_findfile_stopdir(buf);
2646 #else 2654 #else
2647 r_ptr = NULL; 2655 r_ptr = NULL;
2648 #endif 2656 #endif
2649 /* move the filename one char forward and truncate the 2657 /* move the filename one char forward and truncate the
2650 * filepath with a NUL */ 2658 * filepath with a NUL */
2651 filename = gettail(buf); 2659 filename = gettail(buf);
2652 mch_memmove(filename + 1, filename, STRLEN(filename) + 1); 2660 mch_memmove(filename + 1, filename, STRLEN(filename) + 1);
2653 *filename++ = NUL; 2661 *filename++ = NUL;
2654 2662
2655 search_ctx = vim_findfile_init(buf, filename, r_ptr, 100, 2663 tnp->tn_search_ctx = vim_findfile_init(buf, filename,
2656 FALSE, /* don't free visited list */ 2664 r_ptr, 100,
2657 FALSE, /* we search for a file */ 2665 FALSE, /* don't free visited list */
2658 search_ctx, TRUE, curbuf->b_ffname); 2666 FALSE, /* we search for a file */
2659 if (search_ctx != NULL) 2667 tnp->tn_search_ctx, TRUE, curbuf->b_ffname);
2660 did_filefind_init = TRUE; 2668 if (tnp->tn_search_ctx != NULL)
2661 } 2669 tnp->tn_did_filefind_init = TRUE;
2662 } 2670 }
2663 STRCPY(buf, fname); 2671 }
2664 vim_free(fname); 2672
2665 } 2673 STRCPY(buf, fname);
2666 2674 vim_free(fname);
2667 return OK; 2675 return OK;
2676 }
2677
2678 /*
2679 * Free the contents of a tagname_T that was filled by get_tagfname().
2680 */
2681 void
2682 tagname_free(tnp)
2683 tagname_T *tnp;
2684 {
2685 vim_free(tnp->tn_tags);
2686 vim_findfile_cleanup(tnp->tn_search_ctx);
2687 ga_clear_strings(&tag_fnames);
2668 } 2688 }
2669 2689
2670 /* 2690 /*
2671 * Parse one line from the tags file. Find start/end of tag name, start/end of 2691 * Parse one line from the tags file. Find start/end of tag name, start/end of
2672 * file name and start of search pattern. 2692 * file name and start of search pattern.