Mercurial > vim
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. |