tag.c
上传用户:gddssl
上传日期:2007-01-06
资源大小:1003k
文件大小:63k
源码类别:

编辑器/阅读器

开发平台:

DOS

  1. /* vi:set ts=8 sts=4 sw=4:
  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.  */
  8. /*
  9.  * Code to handle tags and the tag stack
  10.  */
  11. #if defined MSDOS || defined WIN32
  12. # include <io.h> /* for lseek(), must be before vim.h */
  13. #endif
  14. #include "vim.h"
  15. #ifdef HAVE_FCNTL_H
  16. # include <fcntl.h> /* for lseek() */
  17. #endif
  18. struct tag_pointers
  19. {
  20.     /* filled in by parse_tag_line(): */
  21.     char_u *tagname; /* start of tag name (skip "file:") */
  22.     char_u *tagname_end; /* char after tag name */
  23.     char_u *fname; /* first char of file name */
  24.     char_u *fname_end; /* char after file name */
  25.     char_u *command; /* first char of command */
  26.     /* filled in by parse_match(): */
  27.     char_u *command_end; /* first char of command */
  28.     char_u *tag_fname; /* file name of the tags file */
  29. #ifdef EMACS_TAGS
  30.     int is_etag; /* TRUE for emacs tag */
  31. #endif
  32.     char_u *tagkind; /* "kind:" value */
  33.     char_u *tagkind_end; /* end of tagkind */
  34. };
  35. /*
  36.  * The matching tags are first stored in ga_match[].  In which one depends on
  37.  * the priority of the match.
  38.  * At the end, the matches from ga_match[] are concatenated, to make a list
  39.  * sorted on priority.
  40.  */
  41. #define MT_ST_CUR 0 /* static match in current file */
  42. #define MT_GL_CUR 1 /* global match in current file */
  43. #define MT_GL_OTH 2 /* global match in other file */
  44. #define MT_ST_OTH 3 /* static match in other file */
  45. #define MT_IC_ST_CUR 4 /* icase static match in current file */
  46. #define MT_IC_GL_CUR 5 /* icase global match in current file */
  47. #define MT_IC_GL_OTH 6 /* icase global match in other file */
  48. #define MT_IC_ST_OTH 7 /* icase static match in other file */
  49. #define MT_IC_OFF 4 /* add for icase match */
  50. #define MT_RE_OFF 8 /* add for regexp match */
  51. #define MT_MASK 7 /* mask for printing priority */
  52. #define MT_COUNT 16
  53. static char *mt_names[MT_COUNT/2] =
  54. {"FSC", "F C", "F  ", "FS ", " SC", "  C", "   ", " S "};
  55. #define NOTAGFILE 99 /* return value for jumpto_tag */
  56. static char_u *nofile_fname = NULL; /* fname for NOTAGFILE error */
  57. static void taglen_advance __ARGS((int l));
  58. static int get_tagfname __ARGS((int first, char_u *buf));
  59. static int jumpto_tag __ARGS((char_u *lbuf, int forceit));
  60. #ifdef EMACS_TAGS
  61. static int parse_tag_line __ARGS((char_u *lbuf, int is_etag, struct tag_pointers *tagp));
  62. #else
  63. static int parse_tag_line __ARGS((char_u *lbuf, struct tag_pointers *tagp));
  64. #endif
  65. static int test_for_static __ARGS((struct tag_pointers *));
  66. static int parse_match __ARGS((char_u *lbuf, struct tag_pointers *tagp));
  67. static char_u *expand_rel_name __ARGS((char_u *fname, char_u *tag_fname));
  68. #ifdef EMACS_TAGS
  69. static int test_for_current __ARGS((int, char_u *, char_u *, char_u *));
  70. #else
  71. static int test_for_current __ARGS((char_u *, char_u *, char_u *));
  72. #endif
  73. static int find_extra __ARGS((char_u **pp));
  74. static char_u *bottommsg = (char_u *)"at bottom of tag stack";
  75. static char_u *topmsg = (char_u *)"at top of tag stack";
  76. /*
  77.  * Jump to tag; handling of tag commands and tag stack
  78.  *
  79.  * *tag != NUL: ":tag {tag}", jump to new tag, add to tag stack
  80.  *
  81.  * type == DT_TAG: ":tag [tag]", jump to newer position or same tag again
  82.  * type == DT_HELP: like DT_TAG, but don't use regexp.
  83.  * type == DT_POP: ":pop" or CTRL-T, jump to old position
  84.  * type == DT_NEXT: jump to next match of same tag
  85.  * type == DT_PREV: jump to previous match of same tag
  86.  * type == DT_FIRST: jump to first match of same tag
  87.  * type == DT_LAST: jump to last match of same tag
  88.  * type == DT_SELECT: ":tselect [tag]", select tag from a list of all matches
  89.  * type == DT_JUMP: ":tjump [tag]", jump to tag or select tag from a list
  90.  *
  91.  * for cscope, returns TRUE if we jumped to tag or aborted, FALSE otherwise
  92.  */
  93.     int
  94. do_tag(tag, type, count, forceit, verbose)
  95.     char_u *tag; /* tag (pattern) to jump to */
  96.     int type;
  97.     int count;
  98.     int forceit; /* :ta with ! */
  99.     int verbose; /* print "tag not found" message */
  100. {
  101.     struct taggy *tagstack = curwin->w_tagstack;
  102.     int tagstackidx = curwin->w_tagstackidx;
  103.     int tagstacklen = curwin->w_tagstacklen;
  104.     int cur_match = 0;
  105.     int oldtagstackidx = tagstackidx;
  106.     int prev_num_matches;
  107.     int new_tag = FALSE;
  108.     int other_name;
  109.     int i, j, k;
  110.     int idx;
  111.     int ic;
  112.     char_u *p;
  113.     char_u *name;
  114.     int no_regexp = FALSE;
  115.     int error_cur_match = 0;
  116.     char_u *command_end;
  117.     int save_pos = FALSE;
  118.     struct filemark saved_fmark;
  119.     int taglen;
  120. #ifdef USE_CSCOPE
  121.     int jumped_to_tag = FALSE;
  122. #endif
  123.     struct tag_pointers tagp, tagp2;
  124.     int new_num_matches;
  125.     char_u **new_matches;
  126.     /* remember the matches for the last used tag */
  127.     static int num_matches = 0;
  128.     static int max_num_matches = 0;  /* limit used for match search */
  129.     static char_u **matches = NULL;
  130.     static int flags;
  131.     static char_u *matchname = NULL;
  132.     if (type == DT_HELP)
  133.     {
  134. type = DT_TAG;
  135. no_regexp = TRUE;
  136.     }
  137.     prev_num_matches = num_matches;
  138.     nofile_fname = NULL;
  139.     /* new pattern, add to the tag stack */
  140. #ifdef USE_CSCOPE
  141.     if ((type == DT_TAG || type == DT_SELECT || type == DT_JUMP ||
  142. type == DT_CSCOPE) && *tag)
  143. #else
  144.     if ((type == DT_TAG || type == DT_SELECT || type == DT_JUMP) && *tag)
  145. #endif
  146.     {
  147. /*
  148.  * If the last used entry is not at the top, delete all tag stack
  149.  * entries above it.
  150.  */
  151. while (tagstackidx < tagstacklen)
  152.     vim_free(tagstack[--tagstacklen].tagname);
  153. /* if the tagstack is full: remove oldest entry */
  154. if (++tagstacklen > TAGSTACKSIZE)
  155. {
  156.     tagstacklen = TAGSTACKSIZE;
  157.     vim_free(tagstack[0].tagname);
  158.     for (i = 1; i < tagstacklen; ++i)
  159. tagstack[i - 1] = tagstack[i];
  160.     --tagstackidx;
  161. }
  162. /*
  163.  * put the tag name in the tag stack
  164.  */
  165. if ((tagstack[tagstackidx].tagname = vim_strsave(tag)) == NULL)
  166. {
  167.     --tagstacklen;
  168.     goto end_do_tag;
  169. }
  170. new_tag = TRUE;
  171. save_pos = TRUE; /* save the cursor position below */
  172.     }
  173.     else
  174.     {
  175. if (tagstacklen == 0) /* empty stack */
  176. {
  177.     EMSG(e_tagstack);
  178.     goto end_do_tag;
  179. }
  180. if (type == DT_POP) /* go to older position */
  181. {
  182.     if ((tagstackidx -= count) < 0)
  183.     {
  184. emsg(bottommsg);
  185. if (tagstackidx + count == 0)
  186. {
  187.     /* We did [num]^T from the bottom of the stack */
  188.     tagstackidx = 0;
  189.     goto end_do_tag;
  190. }
  191. /* We weren't at the bottom of the stack, so jump all the
  192.  * way to the bottom now.
  193.  */
  194. tagstackidx = 0;
  195.     }
  196.     else if (tagstackidx >= tagstacklen)    /* count == 0? */
  197.     {
  198. emsg(topmsg);
  199. goto end_do_tag;
  200.     }
  201.     if (tagstack[tagstackidx].fmark.fnum != curbuf->b_fnum)
  202.     {
  203. /*
  204.  * Jump to other file. If this fails (e.g. because the
  205.  * file was changed) keep original position in tag stack.
  206.  */
  207. if (buflist_getfile(tagstack[tagstackidx].fmark.fnum,
  208. tagstack[tagstackidx].fmark.mark.lnum,
  209. GETF_SETMARK, forceit) == FAIL)
  210. {
  211.     tagstackidx = oldtagstackidx;  /* back to old posn */
  212.     goto end_do_tag;
  213. }
  214.     }
  215.     else
  216. curwin->w_cursor.lnum = tagstack[tagstackidx].fmark.mark.lnum;
  217.     curwin->w_cursor.col = tagstack[tagstackidx].fmark.mark.col;
  218.     curwin->w_set_curswant = TRUE;
  219.     /* remove the old list of matches */
  220.     FreeWild(num_matches, matches);
  221. #ifdef USE_CSCOPE
  222.     cs_free_tags();
  223. #endif
  224.     num_matches = 0;
  225.     goto end_do_tag;
  226. }
  227. if (type == DT_TAG) /* go to newer pattern */
  228. {
  229.     save_pos = TRUE; /* save the cursor position below */
  230.     if ((tagstackidx += count - 1) >= tagstacklen)
  231.     {
  232. /*
  233.  * Beyond the last one, just give an error message and go to
  234.  * the last one.  Don't store the cursor postition.
  235.  */
  236. tagstackidx = tagstacklen - 1;
  237. emsg(topmsg);
  238. save_pos = FALSE;
  239.     }
  240.     else if (tagstackidx < 0)     /* must have been count == 0 */
  241.     {
  242. emsg(bottommsg);
  243. tagstackidx = 0;
  244. goto end_do_tag;
  245.     }
  246.     cur_match = tagstack[tagstackidx].cur_match;
  247.     new_tag = TRUE;
  248. }
  249. else /* go to other matching tag */
  250. {
  251.     if (--tagstackidx < 0)
  252. tagstackidx = 0;
  253.     cur_match = tagstack[tagstackidx].cur_match;
  254.     switch (type)
  255.     {
  256. case DT_FIRST: cur_match = count - 1; break;
  257. case DT_SELECT:
  258. case DT_JUMP:
  259. #ifdef USE_CSCOPE
  260. case DT_CSCOPE:
  261. #endif
  262. case DT_LAST:  cur_match = MAXCOL - 1; break;
  263. case DT_NEXT:  cur_match += count; break;
  264. case DT_PREV:  cur_match -= count; break;
  265.     }
  266.     if (cur_match >= MAXCOL)
  267. cur_match = MAXCOL - 1;
  268.     else if (cur_match < 0)
  269. cur_match = 0;
  270. }
  271.     }
  272.     /*
  273.      * For ":tag [arg]" or ":tselect" remember position before the jump.
  274.      */
  275.     saved_fmark = tagstack[tagstackidx].fmark;
  276.     if (save_pos)
  277.     {
  278. tagstack[tagstackidx].fmark.mark = curwin->w_cursor;
  279. tagstack[tagstackidx].fmark.fnum = curbuf->b_fnum;
  280.     }
  281.     /* curwin will change in the call to jumpto_tag() if ":stag" was used */
  282.     curwin->w_tagstackidx = tagstackidx;
  283.     curwin->w_tagstacklen = tagstacklen;
  284.     if (type != DT_SELECT && type != DT_JUMP)
  285. curwin->w_tagstack[tagstackidx].cur_match = cur_match;
  286.     /*
  287.      * Repeat searching for tags, when a file has not been found.
  288.      */
  289.     for (;;)
  290.     {
  291. /*
  292.  * When desired match not found yet, try to find it (and others).
  293.  */
  294. name = tagstack[tagstackidx].tagname;
  295. other_name = (matchname == NULL || STRCMP(matchname, name) != 0);
  296. if (new_tag
  297. || (cur_match >= num_matches && max_num_matches != MAXCOL)
  298. || other_name)
  299. {
  300.     if (other_name)
  301.     {
  302. vim_free(matchname);
  303. matchname = vim_strsave(name);
  304.     }
  305.     if (type == DT_SELECT || type == DT_JUMP)
  306. cur_match = MAXCOL - 1;
  307.     max_num_matches = cur_match + 1;
  308.     /* when the argument starts with '/', use it as a regexp */
  309.     if (!no_regexp && *name == '/')
  310.     {
  311. flags = TAG_REGEXP;
  312. ++name;
  313.     }
  314.     else
  315. flags = TAG_NOIC;
  316. #ifdef USE_CSCOPE
  317.     if (type == DT_CSCOPE)
  318. flags = TAG_CSCOPE;
  319. #endif
  320.     if (verbose)
  321. flags |= TAG_VERBOSE;
  322.     if (find_tags(name, &new_num_matches, &new_matches, flags,
  323. max_num_matches) == OK
  324.     && num_matches < max_num_matches)
  325. max_num_matches = MAXCOL; /* If less than max_num_matches
  326.      found: all matches found. */
  327.     /* If there already were some matches for the same name, move them
  328.      * to the start.  Avoids that the order changes when using
  329.      * ":tnext" and jumping to another file. */
  330.     if (!new_tag && !other_name)
  331.     {
  332. /* Find the position of each old match in the new list.  Need
  333.  * to use parse_match() to find the tag line. */
  334. idx = 0;
  335. for (j = 0; j < num_matches; ++j)
  336. {
  337.     parse_match(matches[j], &tagp);
  338.     for (i = idx; i < new_num_matches; ++i)
  339.     {
  340. parse_match(new_matches[i], &tagp2);
  341. if (STRCMP(tagp.tagname, tagp2.tagname) == 0)
  342. {
  343.     p = new_matches[i];
  344.     for (k = i; k > idx; --k)
  345. new_matches[k] = new_matches[k - 1];
  346.     new_matches[idx++] = p;
  347.     break;
  348. }
  349.     }
  350. }
  351.     }
  352.     FreeWild(num_matches, matches);
  353.     num_matches = new_num_matches;
  354.     matches = new_matches;
  355. }
  356. if (num_matches <= 0)
  357. {
  358.     if (verbose)
  359. EMSG("tag not found");
  360. }
  361. else
  362. {
  363.     int ask_for_selection = FALSE;
  364. #ifdef USE_CSCOPE
  365.     if (type == DT_CSCOPE && num_matches > 1)
  366.     {
  367. cs_print_tags();
  368. ask_for_selection = TRUE;
  369.     }
  370.     else
  371. #endif
  372.     if (type == DT_SELECT || (type == DT_JUMP && num_matches > 1))
  373.     {
  374. /*
  375.  * List all the matching tags.
  376.  * Assume that the first match indicates how long the tags can
  377.  * be, and align the file names to that.
  378.  */
  379. parse_match(matches[0], &tagp);
  380. taglen = tagp.tagname_end - tagp.tagname + 2;
  381. if (taglen < 18)
  382.     taglen = 18;
  383. if (taglen > Columns - 25)
  384.     taglen = MAXCOL;
  385. MSG_PUTS_ATTR("  # pri kind tag", hl_attr(HLF_T));
  386. msg_clr_eos();
  387. taglen_advance(taglen);
  388. MSG_PUTS_ATTR("filen", hl_attr(HLF_T));
  389. for (i = 0; i < num_matches; ++i)
  390. {
  391.     parse_match(matches[i], &tagp);
  392.     if (!new_tag && i == tagstack[tagstackidx].cur_match)
  393. *IObuff = '>';
  394.     else
  395. *IObuff = ' ';
  396.     sprintf((char *)IObuff + 1, "%2d %s ", i + 1,
  397.    mt_names[matches[i][0] & MT_MASK]);
  398.     msg_puts(IObuff);
  399.     if (tagp.tagkind != NULL)
  400. msg_outtrans_len(tagp.tagkind,
  401.       (int)(tagp.tagkind_end - tagp.tagkind));
  402.     msg_advance(13);
  403.     msg_outtrans_len_attr(tagp.tagname,
  404.        (int)(tagp.tagname_end - tagp.tagname),
  405.       hl_attr(HLF_D));
  406.     msg_putchar(' ');
  407.     taglen_advance(taglen);
  408.     /* If the file name is long, truncate it and put "..." in
  409.      * the middle */
  410.     msg_puts_long_len_attr(tagp.fname,
  411.   (int)(tagp.fname_end - tagp.fname), hl_attr(HLF_D));
  412.     if (msg_col > 0)
  413. msg_putchar('n');
  414.     msg_advance(15);
  415.     /* print any extra fields */
  416.     command_end = tagp.command_end;
  417.     if (command_end != NULL)
  418.     {
  419. p = command_end + 3;
  420. while (*p && *p != 'r' && *p != 'n')
  421. {
  422.     while (*p == TAB)
  423. ++p;
  424.     /* skip "file:" without a value (static tag) */
  425.     if (STRNCMP(p, "file:", 5) == 0
  426.  && vim_isspace(p[5]))
  427.     {
  428. p += 5;
  429. continue;
  430.     }
  431.     /* skip "kind:<kind>" and "<kind>" */
  432.     if (p == tagp.tagkind
  433.     || (p + 5 == tagp.tagkind
  434.     && STRNCMP(p, "kind:", 5) == 0))
  435.     {
  436. p = tagp.tagkind_end;
  437. continue;
  438.     }
  439.     /* print all other extra fields */
  440.     while (*p && *p != 'r' && *p != 'n')
  441.     {
  442. if (msg_col + charsize(*p) >= Columns)
  443. {
  444.     msg_putchar('n');
  445.     msg_advance(15);
  446. }
  447. msg_puts_attr(transchar(*p), hl_attr(HLF_CM));
  448. ++p;
  449. if (*p == TAB)
  450. {
  451.     msg_puts_attr((char_u *)" ",
  452.      hl_attr(HLF_CM));
  453.     break;
  454. }
  455.     }
  456. }
  457. if (msg_col > 15)
  458. {
  459.     msg_putchar('n');
  460.     msg_advance(15);
  461. }
  462.     }
  463.     else
  464.     {
  465. for (p = tagp.command;
  466.   *p && *p != 'r' && *p != 'n'; ++p)
  467.     ;
  468. command_end = p;
  469.     }
  470.     /*
  471.      * Put the info (in several lines) at column 15.
  472.      * Don't display "/^" and "?^".
  473.      */
  474.     p = tagp.command;
  475.     if (*p == '/' || *p == '?')
  476.     {
  477. ++p;
  478. if (*p == '^')
  479.     ++p;
  480.     }
  481.     /* Remove leading whitespace from pattern */
  482.     while (p != command_end && vim_isspace(*p))
  483. ++p;
  484.     while (p != command_end)
  485.     {
  486. if (msg_col + (*p == TAB ? 1 : charsize(*p)) > Columns)
  487.     msg_putchar('n');
  488. msg_advance(15);
  489. /* skip backslash used for escaping command char */
  490. if (*p == '\' && *(p + 1) == *tagp.command)
  491.     ++p;
  492. if (*p == TAB)
  493.     msg_putchar(' ');
  494. else
  495.     msg_puts(transchar(*p));
  496. ++p;
  497. /* don't display the "$/;"" and "$?;"" */
  498. if (p == command_end - 2 && *p == '$'
  499.  && *(p + 1) == *tagp.command)
  500.     break;
  501. if (p == command_end - 1 && *p == *tagp.command)
  502.     break;
  503.     }
  504.     if (msg_col)
  505. msg_putchar('n');
  506.     ui_breakcheck();
  507.     if (got_int)
  508.     {
  509. got_int = FALSE; /* only stop the listing */
  510. break;
  511.     }
  512. }
  513. ask_for_selection = TRUE;
  514.     }
  515.     if (ask_for_selection == TRUE)
  516.     {
  517. /*
  518.  * Ask to select a tag from the list.
  519.  */
  520. MSG_PUTS("Enter nr of choice (<CR> to abort): ");
  521. i = get_number(TRUE);
  522. if (KeyTyped) /* don't call wait_return() now */
  523. {
  524.     msg_putchar('n');
  525.     dont_wait_return = TRUE;
  526.     need_wait_return = FALSE;
  527.     msg_didany = FALSE;
  528.     cmdline_row = msg_row;
  529.     msg_scrolled = 0;
  530.     redraw_all_later(NOT_VALID);
  531. }
  532. if (i <= 0 || i > num_matches || got_int)
  533. {
  534.     /* no valid choice: don't change anything */
  535.     tagstack[tagstackidx].fmark = saved_fmark;
  536.     ++tagstackidx;
  537. #ifdef USE_CSCOPE
  538.     cs_free_tags();
  539.     jumped_to_tag = TRUE;
  540. #endif
  541.     break;
  542. }
  543. cur_match = i - 1;
  544.     }
  545.     if (cur_match >= num_matches)
  546. cur_match = num_matches - 1;
  547.     curwin->w_tagstack[tagstackidx].cur_match = cur_match;
  548.     ++tagstackidx;
  549.     /*
  550.      * Only when going to try the next match, report that the previous
  551.      * file didn't exist.  Otherwise an EMSG() is given below.
  552.      */
  553.     if (nofile_fname != NULL && error_cur_match != cur_match)
  554. smsg((char_u *)"File "%s" does not exist", nofile_fname);
  555.     ic = (matches[cur_match][0] & MT_IC_OFF);
  556.     if (type != DT_SELECT && type != DT_JUMP
  557. #ifdef USE_CSCOPE
  558. && type != DT_CSCOPE
  559. #endif
  560. && (num_matches > 1 || ic))
  561.     {
  562. /* Give an indication of the number of matching tags */
  563. sprintf((char *)msg_buf, "tag %d of %d%s",
  564. cur_match + 1,
  565. num_matches,
  566. max_num_matches != MAXCOL ? " or more" : "");
  567. if (ic)
  568.     STRCAT(msg_buf, "  Using tag with different case!");
  569. if ((num_matches > prev_num_matches || new_tag)
  570.    && num_matches > 1)
  571. {
  572.     if (ic)
  573. msg_attr(msg_buf, hl_attr(HLF_W));
  574.     else
  575. msg(msg_buf);
  576.     msg_scroll = TRUE; /* don't overwrite this message */
  577. }
  578. else
  579.     give_warning(msg_buf, ic);
  580. if (ic && !msg_scrolled)
  581. {
  582.     out_flush();
  583.     ui_delay(1000L, TRUE);
  584. }
  585.     }
  586.     /*
  587.      * Jump to the desired match.
  588.      */
  589.     if (jumpto_tag(matches[cur_match], forceit) == NOTAGFILE)
  590.     {
  591. /* File not found: try again with another matching tag */
  592. if ((type == DT_PREV && cur_match > 0)
  593. || ((type == DT_TAG || type == DT_NEXT
  594.   || type == DT_FIRST)
  595.     && (max_num_matches != MAXCOL
  596.      || cur_match < num_matches - 1)))
  597. {
  598.     error_cur_match = cur_match;
  599.     --tagstackidx;
  600.     if (type == DT_PREV)
  601. --cur_match;
  602.     else
  603.     {
  604. type = DT_NEXT;
  605. ++cur_match;
  606.     }
  607.     continue;
  608. }
  609. EMSG2("File "%s" does not exist", nofile_fname);
  610.     }
  611. #ifdef USE_CSCOPE
  612.     else
  613. jumped_to_tag = TRUE;
  614. #endif
  615. }
  616. break;
  617.     }
  618. end_do_tag:
  619.     curwin->w_tagstackidx = tagstackidx;
  620.     curwin->w_tagstacklen = tagstacklen;
  621.     postponed_split = 0; /* don't split next time */
  622. #ifdef USE_CSCOPE
  623.     return jumped_to_tag;
  624. #else
  625.     return FALSE;
  626. #endif
  627. }
  628.     static void
  629. taglen_advance(l)
  630.     int l;
  631. {
  632.     if (l == MAXCOL)
  633.     {
  634. msg_putchar('n');
  635. msg_advance(24);
  636.     }
  637.     else
  638. msg_advance(13 + l);
  639. }
  640. /*
  641.  * Print the tag stack
  642.  */
  643.     void
  644. do_tags()
  645. {
  646.     int     i;
  647.     char_u     *name;
  648.     struct taggy    *tagstack = curwin->w_tagstack;
  649.     int     tagstackidx = curwin->w_tagstackidx;
  650.     int     tagstacklen = curwin->w_tagstacklen;
  651.     /* Highlight title */
  652.     MSG_PUTS_TITLE("n  # TO tag         FROM line  in file");
  653.     for (i = 0; i < tagstacklen; ++i)
  654.     {
  655. if (tagstack[i].tagname != NULL)
  656. {
  657.     name = fm_getname(&(tagstack[i].fmark));
  658.     if (name == NULL)     /* file name not available */
  659. continue;
  660.     msg_putchar('n');
  661.     sprintf((char *)IObuff, "%c%2d %2d %-15s %5ld  %s",
  662. i == tagstackidx ? '>' : ' ',
  663. i + 1,
  664. tagstack[i].cur_match + 1,
  665. tagstack[i].tagname,
  666. tagstack[i].fmark.mark.lnum,
  667. name);
  668.     msg_outtrans(IObuff);
  669.     vim_free(name);
  670. }
  671. out_flush();     /* show one line at a time */
  672.     }
  673.     if (tagstackidx == tagstacklen) /* idx at top of stack */
  674. MSG_PUTS("n>");
  675. }
  676. /*
  677.  * find_tags() - search for tags in tags files
  678.  *
  679.  * Return FAIL if search completely failed (*num_matches will be 0, *matchesp
  680.  * will be NULL), OK otherwise.
  681.  *
  682.  * There is a priority in which type of tag is recognized.
  683.  *
  684.  *  6. A static or global tag with a full matching tag for the current file.
  685.  *  5. A global tag with a full matching tag for another file.
  686.  *  4. A static tag with a full matching tag for another file.
  687.  *  3. A static or global tag with an ignore-case matching tag for the
  688.  * current file.
  689.  *  2. A global tag with an ignore-case matching tag for another file.
  690.  *  1. A static tag with an ignore-case matching tag for another file.
  691.  *
  692.  * Tags in an emacs-style tags file are always global.
  693.  *
  694.  * flags:
  695.  * TAG_HELP only search for help tags
  696.  * TAG_NAMES only return name of tag
  697.  * TAG_REGEXP use "pat" as a regexp
  698.  * TAG_NOIC don't always ignore case
  699.  */
  700.     int
  701. find_tags(pat, num_matches, matchesp, flags, mincount)
  702.     char_u *pat; /* pattern to search for */
  703.     int *num_matches; /* return: number of matches found */
  704.     char_u ***matchesp; /* return: array of matches found */
  705.     int flags;
  706.     int mincount; /*  MAXCOL: find all matches
  707.      other: minimal number of matches */
  708. {
  709.     FILE       *fp;
  710.     char_u     *lbuf; /* line buffer */
  711.     char_u     *tag_fname; /* name of tag file */
  712.     int first_file; /* trying first tag file */
  713.     struct tag_pointers tagp;
  714.     int did_open = FALSE; /* did open a tag file */
  715.     int stop_searching = FALSE; /* stop when match found or error */
  716.     int retval = FAIL; /* return value */
  717.     int is_static; /* current tag line is static */
  718.     int is_current; /* file name matches */
  719.     int eof = FALSE; /* found end-of-file */
  720.     char_u *p;
  721.     char_u *s;
  722.     int i;
  723.     vim_regexp *prog = NULL; /* regexp program or NULL */
  724. #ifdef BINARY_TAGS
  725.     struct tag_search_info /* Binary search file offsets */
  726.     {
  727. long low_offset; /* offset for first char of first line that
  728.    could match */
  729. long high_offset; /* offset of char after last line that could
  730.    match */
  731. long curr_offset; /* Current file offset in search range */
  732. long match_offset; /* Where the binary search found a tag */
  733. int low_char; /* first char at low_offset */
  734. int high_char; /* first char at high_offset */
  735.     } search_info;
  736.     off_t filesize;
  737.     int tagcmp;
  738.     long offset;
  739. #endif
  740.     enum
  741.     {
  742. TS_START, /* at start of file */
  743. TS_LINEAR, /* linear searching forward, till EOF */
  744. #ifdef BINARY_TAGS
  745. TS_BINARY, /* binary searching */
  746. TS_SKIP_BACK, /* skipping backwards */
  747. TS_STEP_FORWARD /* stepping forwards */
  748. #endif
  749.     } state; /* Current search state */
  750.     int cmplen;
  751.     int match; /* matches */
  752.     int match_no_ic = 0;/* matches with reg_ic == FALSE */
  753.     int match_re; /* match with regexp */
  754.     int matchoff = 0;
  755. #ifdef EMACS_TAGS
  756.     /*
  757.      * Stack for included emacs-tags file.
  758.      * It has a fixed size, to truncate cyclic includes. jw
  759.      */
  760. # define INCSTACK_SIZE 42
  761.     struct
  762.     {
  763. FILE *fp;
  764. char_u *etag_fname;
  765.     } incstack[INCSTACK_SIZE];
  766.     int incstack_idx = 0; /* index in incstack */
  767.     char_u     *ebuf; /* aditional buffer for etag fname */
  768.     int is_etag; /* current file is emaces style */
  769. #endif
  770.     struct growarray ga_match[MT_COUNT];
  771.     int match_count = 0; /* number of matches found */
  772.     char_u **matches;
  773.     int mtt;
  774.     int len;
  775.     int help_save;
  776.     int patlen; /* length of pat[] */
  777.     char_u *pathead; /* start of pattern head */
  778.     int patheadlen; /* length of pathead[] */
  779. #ifdef BINARY_TAGS
  780.     int findall = (mincount == MAXCOL); /* find all matching tags */
  781.     int sort_error = FALSE; /* tags file not sorted */
  782.     int linear; /* do a linear search */
  783. #endif
  784.     int has_re = (flags & TAG_REGEXP); /* regexp used */
  785.     int help_only = (flags & TAG_HELP);
  786.     int name_only = (flags & TAG_NAMES);
  787.     int noic = (flags & TAG_NOIC);
  788.     int get_it_again = FALSE;
  789. #ifdef USE_CSCOPE
  790.     int use_cscope = (flags & TAG_CSCOPE);
  791. #endif
  792.     int verbose = (flags & TAG_VERBOSE);
  793.     help_save = curbuf->b_help;
  794. /*
  795.  * Allocate memory for the buffers that are used
  796.  */
  797.     if (has_re)
  798. prog = vim_regcomp(pat, p_magic);
  799.     lbuf = alloc(LSIZE);
  800.     tag_fname = alloc(LSIZE + 1);
  801. #ifdef EMACS_TAGS
  802.     ebuf = alloc(LSIZE);
  803. #endif
  804.     for (mtt = 0; mtt < MT_COUNT; ++mtt)
  805.     {
  806. ga_init2(&ga_match[mtt], (int)sizeof(char_u *), 100);
  807.     }
  808.     /* check for out of memory situation */
  809.     if (lbuf == NULL || tag_fname == NULL
  810. #ifdef EMACS_TAGS
  811.  || ebuf == NULL
  812. #endif
  813. )
  814. goto findtag_end;
  815. /*
  816.  * Initialize a few variables
  817.  */
  818.     if (help_only) /* want tags from help file */
  819. curbuf->b_help = TRUE; /* will be restored later */
  820.     patlen = STRLEN(pat);
  821.     if (p_tl != 0 && patlen > p_tl) /* adjust for 'taglength' */
  822. patlen = p_tl;
  823.     pathead = pat;
  824.     patheadlen = patlen;
  825.     if (has_re)
  826.     {
  827. /* When the pattern starts with '^' or "\<", binary searching can be
  828.  * used (much faster). */
  829. if (pat[0] == '^')
  830.     pathead = pat + 1;
  831. else if (pat[0] == '\' && pat[1] == '<')
  832.     pathead = pat + 2;
  833. if (pathead == pat)
  834.     patheadlen = 0;
  835. else
  836.     for (patheadlen = 0; pathead[patheadlen] != NUL; ++patheadlen)
  837. if (vim_strchr((char_u *)(p_magic ? ".[~*\$" : "\$"),
  838.  pathead[patheadlen]) != NULL)
  839.     break;
  840. if (p_tl != 0 && patheadlen > p_tl) /* adjust for 'taglength' */
  841.     patheadlen = p_tl;
  842.     }
  843. /*
  844.  * When finding a specified number of matches, first try with matching case,
  845.  * so binary search can be used, and try ignore-case matches in a second loop.
  846.  * When finding all matches, 'tagbsearch' is off, or there is no fixed string
  847.  * to look for, ignore case right away to avoid going though the tags files
  848.  * twice.
  849.  * Only ignore case when TAG_NOIC not used or 'ignorecase' set.
  850.  */
  851. #ifdef BINARY_TAGS
  852.     reg_ic = ((p_ic || !noic) && (findall || patheadlen == 0 || !p_tbs));
  853.     for (;;)
  854.     {
  855.       linear = (reg_ic || patheadlen == 0 || !p_tbs);
  856. #else
  857.       reg_ic = (p_ic || !noic);
  858. #endif
  859.       /*
  860.        * Try tag file names from tags option one by one.
  861.        */
  862.     for (first_file = TRUE;
  863. #ifdef USE_CSCOPE
  864.     use_cscope ||
  865. #endif
  866. get_tagfname(first_file, tag_fname) == OK; first_file = FALSE)
  867.     {
  868. /*
  869.  * A file that doesn't exist is silently ignored.  Only when not a
  870.  * single file is found, an error message is given (further on).
  871.  */
  872. #ifdef USE_CSCOPE
  873. if (use_cscope)
  874.     fp = NULL;     /* avoid GCC warning */
  875. else
  876. #endif
  877.     if ((fp = fopen((char *)tag_fname, "r")) == NULL)
  878. continue;
  879. did_open = TRUE;    /* remember that we found at least one file */
  880. state = TS_START;   /* we're at the start of the file */
  881. #ifdef EMACS_TAGS
  882. is_etag = 0;     /* default is: not emacs style */
  883. #endif
  884. /*
  885.  * Read and parse the lines in the file one by one
  886.  */
  887. while (!got_int)
  888. {
  889.     line_breakcheck();     /* check for CTRL-C typed */
  890.     if (get_it_again)
  891. goto line_read_in;
  892. #ifdef BINARY_TAGS
  893.     /*
  894.      * For binary search: compute the next offset to use.
  895.      */
  896.     if (state == TS_BINARY)
  897.     {
  898. offset = search_info.low_offset + ((search_info.high_offset
  899.        - search_info.low_offset) / 2);
  900. if (offset == search_info.curr_offset)
  901.     break; /* End the binary search without a match. */
  902. else
  903.     search_info.curr_offset = offset;
  904.     }
  905.     /*
  906.      * Skipping back (after a match during binary search).
  907.      */
  908.     else if (state == TS_SKIP_BACK)
  909.     {
  910. search_info.curr_offset -= LSIZE * 2;
  911. if (search_info.curr_offset < 0)
  912. {
  913.     search_info.curr_offset = 0;
  914.     rewind(fp);
  915.     state = TS_STEP_FORWARD;
  916. }
  917.     }
  918.     /*
  919.      * When jumping around in the file, first read a line to find the
  920.      * start of the next line.
  921.      */
  922.     if (state == TS_BINARY || state == TS_SKIP_BACK)
  923.     {
  924. /* Adjust the search file offset to the correct position */
  925. fseek(fp, search_info.curr_offset, SEEK_SET);
  926. eof = vim_fgets(lbuf, LSIZE, fp);
  927. if (!eof && search_info.curr_offset)
  928. {
  929.     search_info.curr_offset = ftell(fp);
  930.     if (search_info.curr_offset == search_info.high_offset)
  931.     {
  932. /* oops, gone a bit too far; try from low offset */
  933. fseek(fp, search_info.low_offset, SEEK_SET);
  934. search_info.curr_offset = search_info.low_offset;
  935.     }
  936.     eof = vim_fgets(lbuf, LSIZE, fp);
  937. }
  938. /* skip empty and blank lines */
  939. while (!eof && vim_isblankline(lbuf))
  940. {
  941.     search_info.curr_offset = ftell(fp);
  942.     eof = vim_fgets(lbuf, LSIZE, fp);
  943. }
  944. if (eof)
  945. {
  946.     /* Hit end of file.  Skip backwards. */
  947.     state = TS_SKIP_BACK;
  948.     search_info.match_offset = ftell(fp);
  949.     continue;
  950. }
  951.     }
  952.     /*
  953.      * Not jumping around in the file: Read the next line.
  954.      */
  955.     else
  956. #endif
  957.     {
  958. /* skip empty and blank lines */
  959. do
  960. {
  961. #ifdef USE_CSCOPE
  962.     if (use_cscope)
  963. eof = cs_fgets(lbuf, LSIZE);
  964.     else
  965. #endif
  966. eof = vim_fgets(lbuf, LSIZE, fp);
  967. } while (!eof && vim_isblankline(lbuf));
  968. if (eof
  969. #ifdef USE_CSCOPE
  970. && !use_cscope
  971. #endif
  972.        )
  973. #ifdef EMACS_TAGS
  974.     if (incstack_idx) /* this was an included file */
  975.     {
  976. --incstack_idx;
  977. fclose(fp); /* end of this file ... */
  978. fp = incstack[incstack_idx].fp;
  979. STRCPY(tag_fname, incstack[incstack_idx].etag_fname);
  980. vim_free(incstack[incstack_idx].etag_fname);
  981. is_etag = 1; /* (only etags can include) */
  982. continue; /* ... continue with parent file */
  983.     }
  984.     else
  985. #endif
  986. break;     /* end of file */
  987.     }
  988. line_read_in:
  989. #ifdef EMACS_TAGS
  990.     /*
  991.      * Emacs tags line with CTRL-L: New file name on next line.
  992.      * The file name is followed by a ','.
  993.      */
  994.     if (*lbuf == Ctrl('L')) /* remember etag file name in ebuf */
  995.     {
  996. is_etag = 1; /* in case at the start */
  997. state = TS_LINEAR;
  998. if (!vim_fgets(ebuf, LSIZE, fp))
  999. {
  1000.     for (p = ebuf; *p && *p != ','; p++)
  1001. ;
  1002.     *p = NUL;
  1003.     /*
  1004.      * atoi(p+1) is the number of bytes before the next ^L
  1005.      * unless it is an include statement.
  1006.      */
  1007.     if (STRNCMP(p + 1, "include", 7) == 0
  1008.       && incstack_idx < INCSTACK_SIZE)
  1009.     {
  1010. if ((incstack[incstack_idx].etag_fname =
  1011.       vim_strsave(tag_fname)) != NULL)
  1012. {
  1013.     incstack[incstack_idx].fp = fp;
  1014.     if ((fp = fopen((char *)ebuf, "r")) == NULL)
  1015.     {
  1016. fp = incstack[incstack_idx].fp;
  1017. vim_free(incstack[incstack_idx].etag_fname);
  1018.     }
  1019.     else
  1020.     {
  1021. STRCPY(tag_fname, ebuf);
  1022. ++incstack_idx;
  1023.     }
  1024.     is_etag = 0; /* we can include anything */
  1025. }
  1026.     }
  1027. }
  1028. continue;
  1029.     }
  1030. #endif
  1031.     /*
  1032.      * When still at the start of the file, check for Emacs tags file
  1033.      * format, and for "not sorted" flag.
  1034.      */
  1035.     if (state == TS_START)
  1036.     {
  1037. #ifdef BINARY_TAGS
  1038. /*
  1039.  * When there is no tag head, or ignoring case, need to do a
  1040.  * linear search.
  1041.  * When no "!_TAG_" is found, default to binary search.  If
  1042.  * the tag file isn't sorted, the second loop will find it.
  1043.  * When "!_TAG_FILE_SORTED" found: start binary search if
  1044.  * flag set.
  1045.  * For cscope, it's always linear.
  1046.  */
  1047. #ifdef USE_CSCOPE
  1048. if (linear || use_cscope)
  1049. #else
  1050. if (linear)
  1051. #endif
  1052.     state = TS_LINEAR;
  1053. else if (STRNCMP(lbuf, "!_TAG_", 6) > 0)
  1054.     state = TS_BINARY;
  1055. else if (STRNCMP(lbuf, "!_TAG_FILE_SORTEDt", 18) == 0)
  1056. {
  1057.     /* Check sorted flag */
  1058.     if (lbuf[18] == '1')
  1059. state = TS_BINARY;
  1060.     else
  1061. state = TS_LINEAR;
  1062. }
  1063. #else
  1064. state = TS_LINEAR;
  1065. #endif
  1066. #ifdef BINARY_TAGS
  1067. /*
  1068.  * When starting a binary search, get the size of the file and
  1069.  * compute the first offset.
  1070.  */
  1071. if (state == TS_BINARY)
  1072. {
  1073.     /* Get the tag file size (don't use fstat(), it's not
  1074.      * portable). */
  1075.     if ((filesize = lseek(fileno(fp),
  1076.    (off_t)0L, SEEK_END)) <= 0)
  1077. state = TS_LINEAR;
  1078.     else
  1079.     {
  1080. lseek(fileno(fp), (off_t)0L, SEEK_SET);
  1081. /* Calculate the first read offset in the file.  Start
  1082.  * the search in the middle of the file.
  1083.  */
  1084. search_info.low_offset = 0;
  1085. search_info.low_char = 0;
  1086. search_info.high_offset = filesize;
  1087. search_info.high_char = 0xff;
  1088.     }
  1089.     continue;
  1090. }
  1091. #endif
  1092.     }
  1093.     /*
  1094.      * Figure out where the different strings are in this line.
  1095.      * For "normal" tags: Do a quick check if the tag matches.
  1096.      * This speeds up tag searching a lot!
  1097.      */
  1098.     if (patheadlen
  1099. #ifdef EMACS_TAGS
  1100.     && !is_etag
  1101. #endif
  1102. )
  1103.     {
  1104. tagp.tagname = lbuf;
  1105. #ifdef TAG_ANY_WHITE
  1106. tagp.tagname_end = skiptowhite(lbuf);
  1107. if (*tagp.tagname_end == NUL)     /* corrupted tag line */
  1108. #else
  1109. tagp.tagname_end = vim_strchr(lbuf, TAB);
  1110. if (tagp.tagname_end == NULL)     /* corrupted tag line */
  1111. #endif
  1112. {
  1113.     EMSG2(e_tagformat, tag_fname);
  1114.     stop_searching = TRUE;
  1115.     break;
  1116. }
  1117. #ifdef OLD_STATIC_TAGS
  1118. /*
  1119.  * Check for old style static tag: "file:tag file .."
  1120.  */
  1121. tagp.fname = NULL;
  1122. for (p = lbuf; p < tagp.tagname_end; ++p)
  1123. {
  1124.     if (*p == ':')
  1125.     {
  1126. if (tagp.fname == NULL)
  1127. #ifdef TAG_ANY_WHITE
  1128.     tagp.fname = skipwhite(tagp.tagname_end);
  1129. #else
  1130.     tagp.fname = tagp.tagname_end + 1;
  1131. #endif
  1132. if (    fnamencmp(lbuf, tagp.fname, p - lbuf) == 0
  1133. #ifdef TAG_ANY_WHITE
  1134. && vim_iswhite(tagp.fname[p - lbuf])
  1135. #else
  1136. && tagp.fname[p - lbuf] == TAB
  1137. #endif
  1138.     )
  1139. {
  1140.     /* found one */
  1141.     tagp.tagname = p + 1;
  1142.     break;
  1143. }
  1144.     }
  1145. }
  1146. #endif
  1147. /*
  1148.  * Skip this line if the length of the tag is different and
  1149.  * there is no regexp, or the tag is too short.
  1150.  */
  1151. cmplen = tagp.tagname_end - tagp.tagname;
  1152. if (p_tl != 0 && cmplen > p_tl)     /* adjust for 'taglength' */
  1153.     cmplen = p_tl;
  1154. if (has_re && patheadlen < cmplen)
  1155.     cmplen = patheadlen;
  1156. else if (state == TS_LINEAR && patheadlen != cmplen)
  1157.     continue;
  1158. #ifdef BINARY_TAGS
  1159. if (state == TS_BINARY)
  1160. {
  1161.     /*
  1162.      * Simplistic check for unsorted tags file.
  1163.      */
  1164.     if ((int)tagp.tagname[0] < search_info.low_char
  1165.     || (int)tagp.tagname[0] > search_info.high_char)
  1166. sort_error = TRUE;
  1167.     /*
  1168.      * Compare the current tag with the searched tag.
  1169.      */
  1170.     tagcmp = STRNCMP(tagp.tagname, pathead, cmplen);
  1171.     /*
  1172.      * A match with a shorter tag means to search forward.
  1173.      * A match with a longer tag means to search backward.
  1174.      */
  1175.     if (tagcmp == 0)
  1176.     {
  1177. if (cmplen < patheadlen)
  1178.     tagcmp = -1;
  1179. else if (cmplen > patheadlen)
  1180.     tagcmp = 1;
  1181.     }
  1182.     if (tagcmp == 0)
  1183.     {
  1184. /* We've located the tag, now skip back and search
  1185.  * forward until the first matching tag is found.
  1186.  */
  1187. state = TS_SKIP_BACK;
  1188. search_info.match_offset = search_info.curr_offset;
  1189. continue;
  1190.     }
  1191.     if (tagcmp < 0)
  1192.     {
  1193. search_info.curr_offset = ftell(fp);
  1194. if (search_info.curr_offset < search_info.high_offset)
  1195. {
  1196.     search_info.low_offset = search_info.curr_offset;
  1197.     search_info.low_char = tagp.tagname[0];
  1198.     continue;
  1199. }
  1200.     }
  1201.     if (tagcmp > 0
  1202. && search_info.curr_offset != search_info.high_offset)
  1203.     {
  1204. search_info.high_offset = search_info.curr_offset;
  1205. search_info.high_char = tagp.tagname[0];
  1206. continue;
  1207.     }
  1208.     /* No match yet and are at the end of the binary search. */
  1209.     break;
  1210. }
  1211. else if (state == TS_SKIP_BACK)
  1212. {
  1213.     if (STRNICMP(tagp.tagname, pathead, cmplen) != 0)
  1214. state = TS_STEP_FORWARD;
  1215.     continue;
  1216. }
  1217. else if (state == TS_STEP_FORWARD)
  1218. {
  1219.     if (STRNICMP(tagp.tagname, pathead, cmplen))
  1220.     {
  1221. if (ftell(fp) > search_info.match_offset)
  1222.     break; /* past last match */
  1223. else
  1224.     continue; /* before first match */
  1225.     }
  1226. }
  1227. else
  1228. #endif
  1229.     /* skip this match if it can't match */
  1230.     if (STRNICMP(tagp.tagname, pathead, cmplen))
  1231.     continue;
  1232. /*
  1233.  * Can be a matching tag, isolate the file name and command.
  1234.  */
  1235. #ifdef OLD_STATIC_TAGS
  1236. if (tagp.fname == NULL)
  1237. #endif
  1238. #ifdef TAG_ANY_WHITE
  1239.     tagp.fname = skipwhite(tagp.tagname_end);
  1240. #else
  1241.     tagp.fname = tagp.tagname_end + 1;
  1242. #endif
  1243. #ifdef TAG_ANY_WHITE
  1244. tagp.fname_end = skiptowhite(tagp.fname);
  1245. tagp.command = skipwhite(tagp.fname_end);
  1246. if (*tagp.command == NUL)
  1247. #else
  1248. tagp.fname_end = vim_strchr(tagp.fname, TAB);
  1249. tagp.command = tagp.fname_end + 1;
  1250. if (tagp.fname_end == NULL)
  1251. #endif
  1252.     i = FAIL;
  1253. else
  1254.     i = OK;
  1255.     }
  1256.     else
  1257. i = parse_tag_line(lbuf,
  1258. #ifdef EMACS_TAGS
  1259.        is_etag,
  1260. #endif
  1261.        &tagp);
  1262.     if (i == FAIL)
  1263.     {
  1264. EMSG2(e_tagformat, tag_fname);
  1265. stop_searching = TRUE;
  1266. break;
  1267.     }
  1268. #ifdef EMACS_TAGS
  1269.     if (is_etag)
  1270. tagp.fname = ebuf;
  1271. #endif
  1272.     /*
  1273.      * First try matching with the pattern literally (also when it is
  1274.      * a regexp).
  1275.      */
  1276.     cmplen = tagp.tagname_end - tagp.tagname;
  1277.     if (p_tl != 0 && cmplen > p_tl)     /* adjust for 'taglength' */
  1278. cmplen = p_tl;
  1279.     /* if tag length does not match, don't try comparing */
  1280.     if (patlen != cmplen)
  1281. match = FALSE;
  1282.     else
  1283.     {
  1284. if (reg_ic)
  1285. {
  1286.     match = (STRNICMP(tagp.tagname, pat, cmplen) == 0);
  1287.     if (match)
  1288. match_no_ic = (STRNCMP(tagp.tagname, pat, cmplen) == 0);
  1289. }
  1290. else
  1291.     match = (STRNCMP(tagp.tagname, pat, cmplen) == 0);
  1292.     }
  1293.     /*
  1294.      * Has a regexp: Also find tags matching regexp "prog".
  1295.      */
  1296.     match_re = FALSE;
  1297.     if (!match && prog != NULL)
  1298.     {
  1299. int cc;
  1300. cc = *tagp.tagname_end;
  1301. *tagp.tagname_end = NUL;
  1302. match = vim_regexec(prog, tagp.tagname, TRUE);
  1303. matchoff = (int)(prog->startp[0] - tagp.tagname);
  1304. if (match && reg_ic)
  1305. {
  1306.     reg_ic = FALSE;
  1307.     match_no_ic = vim_regexec(prog, tagp.tagname, TRUE);
  1308.     reg_ic = TRUE;
  1309. }
  1310. *tagp.tagname_end = cc;
  1311. match_re = TRUE;
  1312.     }
  1313.     /*
  1314.      * If a match is found, add it to ga_match[].
  1315.      */
  1316.     if (match)
  1317.     {
  1318. /* Decide in which array to store this match. */
  1319. is_current = test_for_current(
  1320. #ifdef EMACS_TAGS
  1321. is_etag,
  1322. #endif
  1323.  tagp.fname, tagp.fname_end, tag_fname);
  1324. #ifdef EMACS_TAGS
  1325. is_static = FALSE;
  1326. if (!is_etag) /* emacs tags are never static */
  1327. #endif
  1328. {
  1329. #ifdef OLD_STATIC_TAGS
  1330.     if (tagp.tagname != lbuf) /* detected static tag before */
  1331. is_static = TRUE;
  1332.     else
  1333. #endif
  1334. is_static = test_for_static(&tagp);
  1335. }
  1336. /* decide in which of the six table to store this match */
  1337. if (is_static)
  1338. {
  1339.     if (is_current)
  1340. mtt = MT_ST_CUR;
  1341.     else
  1342. mtt = MT_ST_OTH;
  1343. }
  1344. else
  1345. {
  1346.     if (is_current)
  1347. mtt = MT_GL_CUR;
  1348.     else
  1349. mtt = MT_GL_OTH;
  1350. }
  1351. if (reg_ic && !match_no_ic)
  1352.     mtt += MT_IC_OFF;
  1353. if (match_re)
  1354.     mtt += MT_RE_OFF;
  1355. if (ga_grow(&ga_match[mtt], 1) == OK)
  1356. {
  1357.     if (help_only)
  1358.     {
  1359. /*
  1360.  * Append the help-heuristic number after the
  1361.  * tagname, for sorting it later.
  1362.  */
  1363. *tagp.tagname_end = NUL;
  1364. len = tagp.tagname_end - tagp.tagname;
  1365. p = vim_strnsave(tagp.tagname, len + 10);
  1366. if (p != NULL)
  1367.     sprintf((char *)p + len + 1, "%06d",
  1368.     help_heuristic(tagp.tagname,
  1369.     match_re ? matchoff : 0, !match_no_ic));
  1370. *tagp.tagname_end = TAB;
  1371. ++len; /* compare one more char */
  1372.     }
  1373.     else if (name_only)
  1374.     {
  1375. p = NULL;
  1376. len = 0;
  1377. if (get_it_again)
  1378. {
  1379.     char_u *temp_end = tagp.command;
  1380.     if ((*temp_end) == '/')
  1381. while ( *temp_end && (*temp_end != 'r')
  1382. && (*temp_end != 'n')
  1383. && (*temp_end != '$'))
  1384.     temp_end++;
  1385.     if ((tagp.command + 2) < temp_end)
  1386.     {
  1387. len = temp_end - tagp.command - 2;
  1388. p = vim_strnsave(tagp.command + 2, len);
  1389.     }
  1390.     get_it_again = FALSE;
  1391. }
  1392. else
  1393. {
  1394.     len = tagp.tagname_end - tagp.tagname;
  1395.     p = vim_strnsave(tagp.tagname, len);
  1396.     /* if wanted, re-read line to get long form too*/
  1397.     if (State & INSERT)
  1398. get_it_again = p_sft;
  1399. }
  1400. ++len; /* compare one more char */
  1401.     }
  1402.     else
  1403.     {
  1404. /* Save the tag in a buffer.
  1405.  * Emacs tag: <mtt><tag_fname><NUL><ebuf><NUL><lbuf>
  1406.  * other tag: <mtt><tag_fname><NUL><NUL><lbuf>
  1407.  * without Emacs tags: <mtt><tag_fname><NUL><lbuf>
  1408.  */
  1409. len = STRLEN(tag_fname) + STRLEN(lbuf) + 3;
  1410. #ifdef EMACS_TAGS
  1411. if (is_etag)
  1412.     len += STRLEN(ebuf) + 1;
  1413. else
  1414.     ++len;
  1415. #endif
  1416. p = alloc(len);
  1417. if (p != NULL)
  1418. {
  1419.     p[0] = mtt;
  1420.     STRCPY(p + 1, tag_fname);
  1421.     s = p + 1 + STRLEN(tag_fname) + 1;
  1422. #ifdef EMACS_TAGS
  1423.     if (is_etag)
  1424.     {
  1425. STRCPY(s, ebuf);
  1426. s += STRLEN(ebuf) + 1;
  1427.     }
  1428.     else
  1429. *s++ = NUL;
  1430. #endif
  1431.     STRCPY(s, lbuf);
  1432. }
  1433.     }
  1434.     if (p != NULL)
  1435.     {
  1436. /*
  1437.  * Don't add identical matches.
  1438.  */
  1439. for (i = ga_match[mtt].ga_len; --i >= 0; )
  1440.     if (vim_memcmp(
  1441.       ((char_u **)(ga_match[mtt].ga_data))[i],
  1442.  p, (size_t)len) == 0)
  1443. break;
  1444. if (i < 0)
  1445. {
  1446.     ((char_u **)(ga_match[mtt].ga_data))
  1447.  [ga_match[mtt].ga_len++] = p;
  1448.     ga_match[mtt].ga_room--;
  1449.     ++match_count;
  1450. }
  1451. else
  1452.     vim_free(p);
  1453.     }
  1454. }
  1455. else    /* Out of memory! Just forget about the rest. */
  1456. {
  1457.     retval = OK;
  1458.     stop_searching = TRUE;
  1459.     break;
  1460. }
  1461.     }
  1462. #ifdef USE_CSCOPE
  1463.     if (use_cscope && eof)
  1464. break;
  1465. #endif
  1466. } /* not got_int */
  1467. #ifdef USE_CSCOPE
  1468. if (!use_cscope)
  1469. #endif
  1470.     fclose(fp);
  1471. #ifdef EMACS_TAGS
  1472. while (incstack_idx)
  1473. {
  1474.     --incstack_idx;
  1475.     fclose(incstack[incstack_idx].fp);
  1476.     vim_free(incstack[incstack_idx].etag_fname);
  1477. }
  1478. #endif
  1479. #ifdef BINARY_TAGS
  1480. if (sort_error)
  1481. {
  1482.     EMSG2("Tags file not sorted: %s", tag_fname);
  1483.     sort_error = FALSE;
  1484. }
  1485. #endif
  1486. /*
  1487.  * Stop searching if sufficient tags have been found.
  1488.  */
  1489. if (match_count >= mincount)
  1490. {
  1491.     retval = OK;
  1492.     stop_searching = TRUE;
  1493. }
  1494. #ifdef USE_CSCOPE
  1495. if (stop_searching || use_cscope)
  1496. #else
  1497. if (stop_searching)
  1498. #endif
  1499.     break;
  1500.     } /* end of for-each-file loop */
  1501. #ifdef BINARY_TAGS
  1502.       /* stop searching when already did a linear search, or when
  1503.        * TAG_NOIC used, and 'ignorecase' not set */
  1504.       if (stop_searching || linear || (!p_ic && noic))
  1505.   break;
  1506. # ifdef USE_CSCOPE
  1507.       if (use_cscope)
  1508.   break;
  1509. # endif
  1510.       reg_ic = TRUE; /* try another time while ignoring case */
  1511.     }
  1512. #endif
  1513.     if (!stop_searching)
  1514.     {
  1515. if (!did_open && verbose) /* never opened any tags file */
  1516.     EMSG("No tags file");
  1517. retval = OK; /* It's OK even when no tag found */
  1518.     }
  1519. findtag_end:
  1520.     vim_free(lbuf);
  1521.     vim_free(prog);
  1522.     vim_free(tag_fname);
  1523. #ifdef EMACS_TAGS
  1524.     vim_free(ebuf);
  1525. #endif
  1526.     /*
  1527.      * Move the matches from the ga_match[] arrays into one list of
  1528.      * matches.  When retval == FAIL, free the matches.
  1529.      */
  1530.     if (retval == FAIL)
  1531. match_count = 0;
  1532.     if (match_count > 0)
  1533. matches = (char_u **)lalloc((long_u)(match_count * sizeof(char_u *)),
  1534. TRUE);
  1535.     else
  1536. matches = NULL;
  1537.     match_count = 0;
  1538.     for (mtt = 0; mtt < MT_COUNT; ++mtt)
  1539.     {
  1540. for (i = 0; i < ga_match[mtt].ga_len; ++i)
  1541. {
  1542.     p = ((char_u **)(ga_match[mtt].ga_data))[i];
  1543.     if (matches == NULL)
  1544. vim_free(p);
  1545.     else
  1546. matches[match_count++] = p;
  1547. }
  1548. ga_clear(&ga_match[mtt]);
  1549.     }
  1550.     *matchesp = matches;
  1551.     *num_matches = match_count;
  1552.     curbuf->b_help = help_save;
  1553.     return retval;
  1554. }
  1555. /*
  1556.  * Get the next name of a tag file from the tag file list.
  1557.  * For help files, use "tags" file only.
  1558.  *
  1559.  * Return FAIL if no more tag file names, OK otherwise.
  1560.  */
  1561.     static int
  1562. get_tagfname(first, buf)
  1563.     int     first;     /* TRUE when first file name is wanted */
  1564.     char_u  *buf;     /* pointer to buffer of LSIZE chars */
  1565. {
  1566.     static char_u   *np = NULL;
  1567.     char_u     *fname;
  1568.     size_t     path_len, fname_len;
  1569.     /*
  1570.      * A list is kept of the files that have been visited.
  1571.      */
  1572.     struct visited
  1573.     {
  1574. struct visited *v_next;
  1575. #if defined(UNIX)
  1576. struct stat v_st;
  1577. #else
  1578. char_u v_fname[1]; /* actually longer */
  1579. #endif
  1580.     };
  1581.     static struct visited   *first_visited = NULL;
  1582.     struct visited     *vp;
  1583. #ifdef UNIX
  1584.     struct stat     st;
  1585. #else
  1586.     char_u     *expand_buf;
  1587. #endif
  1588.     if (first)
  1589.     {
  1590. np = p_tags;
  1591. while (first_visited != NULL)
  1592. {
  1593.     vp = first_visited->v_next;
  1594.     vim_free(first_visited);
  1595.     first_visited = vp;
  1596. }
  1597.     }
  1598.     if (np == NULL)     /* tried allready (or bogus call) */
  1599. return FAIL;
  1600.     /*
  1601.      * For a help window only try the file 'tags' in the same
  1602.      * directory as 'helpfile'.
  1603.      */
  1604.     if (curbuf->b_help)
  1605.     {
  1606. path_len = gettail(p_hf) - p_hf;
  1607. if (path_len + 9 >= LSIZE)
  1608.     return FAIL;
  1609. mch_memmove(buf, p_hf, path_len);
  1610. STRCPY(buf + path_len, "tags");
  1611. np = NULL; /* try only once */
  1612.     }
  1613.     else
  1614.     {
  1615. #ifndef UNIX
  1616. expand_buf = alloc(MAXPATHL);
  1617. if (expand_buf == NULL)
  1618.     return FAIL;
  1619. #endif
  1620. /*
  1621.  * Loop until we have found a file name that can be used.
  1622.  */
  1623. for (;;)
  1624. {
  1625.     if (*np == NUL)     /* tried all possibilities */
  1626.     {
  1627. #ifndef UNIX
  1628. vim_free(expand_buf);
  1629. #endif
  1630. return FAIL;
  1631.     }
  1632.     /*
  1633.      * Copy next file name into buf.
  1634.      */
  1635.     (void)copy_option_part(&np, buf, LSIZE, " ,");
  1636.     /*
  1637.      * Tag file name starting with "./": Replace '.' with path of
  1638.      * current file.
  1639.      * Only do this when 't' flag not included in 'cpo'.
  1640.      */
  1641.     if (buf[0] == '.' && vim_ispathsep(buf[1])
  1642.      && vim_strchr(p_cpo, CPO_DOTTAG) == NULL)
  1643.     {
  1644. if (curbuf->b_fname == NULL) /* skip if no file name */
  1645.     continue;
  1646. path_len = gettail(curbuf->b_fname) - curbuf->b_fname;
  1647. fname = buf + 1;
  1648. while (vim_ispathsep(*fname)) /* skip '/' and the like */
  1649.     ++fname;
  1650. fname_len = STRLEN(fname);
  1651. if (fname_len + path_len + 1 > LSIZE)
  1652.     continue;
  1653. mch_memmove(buf + path_len, fname, fname_len + 1);
  1654. mch_memmove(buf, curbuf->b_fname, path_len);
  1655.     }
  1656.     /*
  1657.      * Check if this tags file has been used already.
  1658.      * If file doesn't exist, skip it.
  1659.      */
  1660. #if defined(UNIX)
  1661.     if (stat((char *)buf, &st) < 0)
  1662. #else
  1663.     if (mch_FullName(buf, expand_buf, MAXPATHL, TRUE) == FAIL)
  1664. #endif
  1665. continue;
  1666.     for (vp = first_visited; vp != NULL; vp = vp->v_next)
  1667. #if defined(UNIX)
  1668. if (vp->v_st.st_dev == st.st_dev &&
  1669.  vp->v_st.st_ino == st.st_ino)
  1670. #else
  1671. if (fnamecmp(vp->v_fname, expand_buf) == 0)
  1672. #endif
  1673.     break;
  1674.     if (vp != NULL)     /* already visited, skip it */
  1675. continue;
  1676.     /*
  1677.      * Found the next name.  Add it to the list of visited files.
  1678.      */
  1679. #ifdef UNIX
  1680.     vp = (struct visited *)alloc((unsigned)sizeof(struct visited));
  1681. #else
  1682.     vp = (struct visited *)alloc((unsigned)(sizeof(struct visited) +
  1683.  STRLEN(expand_buf)));
  1684. #endif
  1685.     if (vp != NULL)
  1686.     {
  1687. #ifdef UNIX
  1688. vp->v_st = st;
  1689. #else
  1690. STRCPY(vp->v_fname, expand_buf);
  1691. #endif
  1692. vp->v_next = first_visited;
  1693. first_visited = vp;
  1694.     }
  1695.     break;
  1696. }
  1697. #ifndef UNIX
  1698. vim_free(expand_buf);
  1699. #endif
  1700.     }
  1701.     return OK;
  1702. }
  1703. /*
  1704.  * Parse one line from the tags file. Find start/end of tag name, start/end of
  1705.  * file name and start of search pattern.
  1706.  *
  1707.  * If is_etag is TRUE, tagp->fname and tagp->fname_end are not set.
  1708.  *
  1709.  * Return FAIL if there is a format error in this line, OK otherwise.
  1710.  */
  1711.     static int
  1712. parse_tag_line(lbuf,
  1713. #ifdef EMACS_TAGS
  1714.     is_etag,
  1715. #endif
  1716.       tagp)
  1717.     char_u *lbuf; /* line to be parsed */
  1718. #ifdef EMACS_TAGS
  1719.     int is_etag;
  1720. #endif
  1721.     struct tag_pointers *tagp;
  1722. {
  1723.     char_u *p;
  1724. #ifdef EMACS_TAGS
  1725.     char_u *p_7f;
  1726.     if (is_etag)
  1727.     {
  1728. /*
  1729.  * There are two formats for an emacs tag line:
  1730.  * 1:  struct EnvBase ^?EnvBase^A139,4627
  1731.  * 2: #define ARPB_WILD_WORLD ^?153,5194
  1732.  */
  1733. p_7f = vim_strchr(lbuf, 0x7f);
  1734. if (p_7f == NULL)
  1735.     return FAIL;
  1736. /* Find ^A.  If not found the line number is after the 0x7f */
  1737. p = vim_strchr(p_7f, Ctrl('A'));
  1738. if (p == NULL)
  1739.     p = p_7f + 1;
  1740. else
  1741.     ++p;
  1742. if (!isdigit(*p))     /* check for start of line number */
  1743.     return FAIL;
  1744. tagp->command = p;
  1745. if (p[-1] == Ctrl('A'))     /* first format: explicit tagname given */
  1746. {
  1747.     tagp->tagname = p_7f + 1;
  1748.     tagp->tagname_end = p - 1;
  1749. }
  1750. else     /* second format: isolate tagname */
  1751. {
  1752.     /* find end of tagname */
  1753.     for (p = p_7f - 1; !vim_iswordc(*p); --p)
  1754. if (p == lbuf)
  1755.     return FAIL;
  1756.     tagp->tagname_end = p + 1;
  1757.     while (p >= lbuf && vim_iswordc(*p))
  1758. --p;
  1759.     tagp->tagname = p + 1;
  1760. }
  1761.     }
  1762.     else /* not an Emacs tag */
  1763.     {
  1764. #endif
  1765. /* Isolate the tagname, from lbuf up to the first white */
  1766. tagp->tagname = lbuf;
  1767. #ifdef TAG_ANY_WHITE
  1768. p = skiptowhite(lbuf);
  1769. #else
  1770. p = vim_strchr(lbuf, TAB);
  1771. if (p == NULL)
  1772.     return FAIL;
  1773. #endif
  1774. tagp->tagname_end = p;
  1775. /* Isolate file name, from first to second white space */
  1776. #ifdef TAG_ANY_WHITE
  1777. p = skipwhite(p);
  1778. #else
  1779. if (*p != NUL)
  1780.     ++p;
  1781. #endif
  1782. tagp->fname = p;
  1783. #ifdef TAG_ANY_WHITE
  1784. p = skiptowhite(p);
  1785. #else
  1786. p = vim_strchr(p, TAB);
  1787. if (p == NULL)
  1788.     return FAIL;
  1789. #endif
  1790. tagp->fname_end = p;
  1791. /* find start of search command, after second white space */
  1792. #ifdef TAG_ANY_WHITE
  1793. p = skipwhite(p);
  1794. #else
  1795. if (*p != NUL)
  1796.     ++p;
  1797. #endif
  1798. if (*p == NUL)
  1799.     return FAIL;
  1800. tagp->command = p;
  1801. #ifdef EMACS_TAGS
  1802.     }
  1803. #endif
  1804.     return OK;
  1805. }
  1806. /*
  1807.  * Check if tagname is a static tag
  1808.  *
  1809.  * Static tags produced by the older ctags program have the format:
  1810.  * 'file:tag  file  /pattern'.
  1811.  * This is only recognized when both occurences of 'file' are the same, to
  1812.  * avoid recognizing "string::string" or ":exit".
  1813.  *
  1814.  * Static tags produced by the new ctags program have the format:
  1815.  * 'tag  file  /pattern/;"<Tab>file:'     "
  1816.  *
  1817.  * Return TRUE if it is a static tag and adjust *tagname to the real tag.
  1818.  * Return FALSE if it is not a static tag.
  1819.  */
  1820.     static int
  1821. test_for_static(tagp)
  1822.     struct tag_pointers *tagp;
  1823. {
  1824.     char_u *p;
  1825. #ifdef OLD_STATIC_TAGS
  1826.     int len;
  1827.     /*
  1828.      * Check for old style static tag: "file:tag file .."
  1829.      */
  1830.     len = tagp->fname_end - tagp->fname;
  1831.     p = tagp->tagname + len;
  1832.     if (       p < tagp->tagname_end
  1833.     && *p == ':'
  1834.     && fnamencmp(tagp->tagname, tagp->fname, len) == 0)
  1835.     {
  1836. tagp->tagname = p + 1;
  1837. return TRUE;
  1838.     }
  1839. #endif
  1840.     /*
  1841.      * Check for new style static tag ":...<Tab>file:[<Tab>...]"
  1842.      */
  1843.     p = tagp->command;
  1844.     while ((p = vim_strchr(p, 't')) != NULL)
  1845.     {
  1846. ++p;
  1847. if (STRNCMP(p, "file:", 5) == 0)
  1848.     return TRUE;
  1849.     }
  1850.     return FALSE;
  1851. }
  1852. /*
  1853.  * Parse a line from a matching tag.  Does not change the line itself.
  1854.  *
  1855.  * The line that we get looks like this:
  1856.  * Emacs tag: <mtt><tag_fname><NUL><ebuf><NUL><lbuf>
  1857.  * other tag: <mtt><tag_fname><NUL><NUL><lbuf>
  1858.  * without Emacs tags: <mtt><tag_fname><NUL><lbuf>
  1859.  *
  1860.  * Return OK or FAIL.
  1861.  */
  1862.     static int
  1863. parse_match(lbuf, tagp)
  1864.     char_u *lbuf;     /* input: matching line */
  1865.     struct tag_pointers *tagp;     /* output: pointers into the line */
  1866. {
  1867.     int retval;
  1868.     char_u *p;
  1869.     char_u *pc, *pt;
  1870.     tagp->tag_fname = lbuf + 1;
  1871.     lbuf += STRLEN(tagp->tag_fname) + 2;
  1872. #ifdef EMACS_TAGS
  1873.     if (*lbuf)
  1874.     {
  1875. tagp->is_etag = TRUE;
  1876. tagp->fname = lbuf;
  1877. lbuf += STRLEN(lbuf);
  1878. tagp->fname_end = lbuf++;
  1879.     }
  1880.     else
  1881.     {
  1882. tagp->is_etag = FALSE;
  1883. ++lbuf;
  1884.     }
  1885. #endif
  1886.     /* Find search pattern and the file name for non-etags. */
  1887.     retval = parse_tag_line(lbuf,
  1888. #ifdef EMACS_TAGS
  1889. tagp->is_etag,
  1890. #endif
  1891. tagp);
  1892.     tagp->tagkind = NULL;
  1893.     tagp->command_end = NULL;
  1894.     if (retval == OK)
  1895.     {
  1896. /* Try to find a kind field: "kind:<kind>" or just "<kind>"*/
  1897. p = tagp->command;
  1898. if (find_extra(&p) == OK)
  1899. {
  1900.     tagp->command_end = p;
  1901.     p += 3; /* skip ";"t" */
  1902.     while (isalpha(*p))
  1903.     {
  1904. if (STRNCMP(p, "kind:", 5) == 0)
  1905. {
  1906.     tagp->tagkind = p + 5;
  1907.     break;
  1908. }
  1909. pc = vim_strchr(p, ':');
  1910. pt = vim_strchr(p, 't');
  1911. if (pc == NULL || (pt != NULL && pc > pt))
  1912. {
  1913.     tagp->tagkind = p;
  1914.     break;
  1915. }
  1916. if (pt == NULL)
  1917.     break;
  1918. p = pt + 1;
  1919.     }
  1920. }
  1921. if (tagp->tagkind != NULL)
  1922. {
  1923.     for (p = tagp->tagkind;
  1924.     *p && *p != 't' && *p != 'r' && *p != 'n'; ++p)
  1925. ;
  1926.     tagp->tagkind_end = p;
  1927. }
  1928.     }
  1929.     return retval;
  1930. }
  1931. /*
  1932.  * Jump to a tag that has been found in one of the tag files
  1933.  *
  1934.  * returns OK for success, NOTAGFILE when file not found, FAIL otherwise.
  1935.  */
  1936.     static int
  1937. jumpto_tag(lbuf, forceit)
  1938.     char_u *lbuf; /* line from the tags file for this tag */
  1939.     int forceit; /* :ta with ! */
  1940. {
  1941.     int save_secure;
  1942.     int save_magic;
  1943.     int save_p_ws, save_p_scs, save_p_ic;
  1944.     int csave = 0;
  1945.     char_u *str;
  1946.     char_u *pbuf; /* search pattern buffer */
  1947.     char_u *pbuf_end;
  1948.     char_u *expanded_fname = NULL;
  1949.     char_u *tofree_fname = NULL;
  1950.     char_u *fname;
  1951.     struct tag_pointers tagp;
  1952.     int retval = FAIL;
  1953.     int getfile_result;
  1954.     int search_options;
  1955.     pbuf = alloc(LSIZE);
  1956.     /* parse the match line into the tagp structure */
  1957.     if (pbuf == NULL || parse_match(lbuf, &tagp) == FAIL)
  1958.     {
  1959. tagp.fname_end = NULL;
  1960. goto erret;
  1961.     }
  1962.     /* truncate the file name, so it can be used as a string */
  1963.     csave = *tagp.fname_end;
  1964.     *tagp.fname_end = NUL;
  1965.     fname = tagp.fname;
  1966.     /* copy the command to pbuf[], remove trailing CR/NL */
  1967.     str = tagp.command;
  1968.     for (pbuf_end = pbuf; *str && *str != 'n' && *str != 'r'; )
  1969.     {
  1970. #ifdef EMACS_TAGS
  1971. if (tagp.is_etag && *str == ',')/* stop at ',' after line number */
  1972.     break;
  1973. #endif
  1974. *pbuf_end++ = *str++;
  1975.     }
  1976.     *pbuf_end = NUL;
  1977. #ifdef EMACS_TAGS
  1978.     if (!tagp.is_etag)
  1979. #endif
  1980.     {
  1981. /*
  1982.  * Remove the "<Tab>fieldname:value" stuff; we don't need it here.
  1983.  */
  1984. str = pbuf;
  1985. if (find_extra(&str) == OK)
  1986. {
  1987.     pbuf_end = str;
  1988.     *pbuf_end = NUL;
  1989. }
  1990.     }
  1991.     /*
  1992.      * expand file name (for environment variables)
  1993.      */
  1994.     expanded_fname = ExpandOne((char_u *)fname, NULL, WILD_LIST_NOTFOUND,
  1995.     WILD_EXPAND_FREE);
  1996.     if (expanded_fname != NULL)
  1997. fname = expanded_fname;
  1998.     /*
  1999.      * if 'tagrelative' option set, may change file name
  2000.      */
  2001.     fname = expand_rel_name(fname, tagp.tag_fname);
  2002.     if (fname == NULL)
  2003. goto erret;
  2004.     tofree_fname = fname; /* free() it later */
  2005.     /*
  2006.      * check if file for tag exists before abandoning current file
  2007.      */
  2008.     if (mch_getperm(fname) < 0)
  2009.     {
  2010. retval = NOTAGFILE;
  2011. vim_free(nofile_fname);
  2012. nofile_fname = vim_strsave(fname);
  2013. if (nofile_fname == NULL)
  2014.     nofile_fname = (char_u *)"";
  2015. goto erret;
  2016.     }
  2017.     ++RedrawingDisabled;
  2018. #ifdef USE_GUI
  2019.     need_mouse_correct = TRUE;
  2020. #endif
  2021.     /* if it was a CTRL-W CTRL-] command split window now */
  2022.     if (postponed_split)
  2023. win_split(postponed_split > 0 ? postponed_split : 0, FALSE, FALSE);
  2024.     /* A :ta from a help file will keep the b_help flag set. */
  2025.     keep_help_flag = curbuf->b_help;
  2026.     getfile_result = getfile(0, fname, NULL, TRUE, (linenr_t)0, forceit);
  2027.     keep_help_flag = FALSE;
  2028.     if (getfile_result <= 0) /* got to the right file */
  2029.     {
  2030. curwin->w_set_curswant = TRUE;
  2031. postponed_split = 0;
  2032. save_secure = secure;
  2033. secure = 1;
  2034. save_magic = p_magic;
  2035. p_magic = FALSE; /* always execute with 'nomagic' */
  2036. tag_modified = FALSE;
  2037. /*
  2038.  * If 'cpoptions' contains 't', store the search pattern for the "n"
  2039.  * command.  If 'cpoptions' does not contain 't', the search pattern
  2040.  * is not stored.
  2041.  */
  2042. if (vim_strchr(p_cpo, CPO_TAGPAT) != NULL)
  2043.     search_options = 0;
  2044. else
  2045.     search_options = SEARCH_KEEP;
  2046. /*
  2047.  * If the command is a search, try here.
  2048.  *
  2049.  * Reset 'smartcase' for the search, since the search pattern was not
  2050.  * typed by the user.
  2051.  * Only use do_search() when there is a full search command, without
  2052.  * anything following.
  2053.  */
  2054. str = pbuf;
  2055. if (pbuf[0] == '/' || pbuf[0] == '?')
  2056.     str = skip_regexp(pbuf + 1, pbuf[0], FALSE) + 1;
  2057. if (str > pbuf_end - 1) /* search command with nothing following */
  2058. {
  2059.     save_p_ws = p_ws;
  2060.     save_p_ic = p_ic;
  2061.     save_p_scs = p_scs;
  2062.     p_ws = TRUE; /* Switch wrap-scan on temporarily */
  2063.     p_ic = FALSE; /* don't ignore case now */
  2064.     p_scs = FALSE;
  2065.     /* put pattern in search history */
  2066.     add_to_history(HIST_SEARCH, pbuf + 1);
  2067.     curwin->w_cursor.lnum = 0; /* start search before first line */
  2068.     if (do_search(NULL, pbuf[0], pbuf + 1, (long)1, search_options))
  2069. retval = OK;
  2070.     else
  2071.     {
  2072. int found = 1;
  2073. int cc;
  2074. /*
  2075.  * try again, ignore case now
  2076.  */
  2077. p_ic = TRUE;
  2078. if (!do_search(NULL, pbuf[0], pbuf + 1, (long)1,
  2079.       search_options))
  2080. {
  2081.     /*
  2082.      * Failed to find pattern, take a guess: "^func  ("
  2083.      */
  2084.     found = 2;
  2085.     (void)test_for_static(&tagp);
  2086.     cc = *tagp.tagname_end;
  2087.     *tagp.tagname_end = NUL;
  2088.     sprintf((char *)pbuf, "^%s\s\*(", tagp.tagname);
  2089.     if (!do_search(NULL, '/', pbuf, (long)1, search_options))
  2090.     {
  2091. /* Guess again: "^char * <func  (" */
  2092. sprintf((char *)pbuf, "^\[#a-zA-Z_]\.\*\<%s\s\*(",
  2093. tagp.tagname);
  2094. if (!do_search(NULL, '/', pbuf, (long)1,
  2095.       search_options))
  2096.     found = 0;
  2097.     }
  2098.     *tagp.tagname_end = cc;
  2099. }
  2100. if (found == 0)
  2101.     EMSG("Can't find tag pattern");
  2102. else
  2103. {
  2104.     /*
  2105.      * Only give a message when really guessed, not when 'ic'
  2106.      * is set and match found while ignoring case.
  2107.      */
  2108.     if (found == 2 || !save_p_ic)
  2109.     {
  2110. MSG("Couldn't find tag, just guessing!");
  2111. if (!msg_scrolled)
  2112. {
  2113.     out_flush();
  2114.     ui_delay(1000L, TRUE);
  2115. }
  2116.     }
  2117.     retval = OK;
  2118. }
  2119.     }
  2120.     p_ws = save_p_ws;
  2121.     p_ic = save_p_ic;
  2122.     p_scs = save_p_scs;
  2123.     /* A search command may have positioned the cursor beyond the end
  2124.      * of the line.  May need to correct that here. */
  2125.     adjust_cursor();
  2126. }
  2127. else
  2128. {
  2129.     curwin->w_cursor.lnum = 1; /* start command in line 1 */
  2130.     do_cmdline(pbuf, NULL, NULL, DOCMD_NOWAIT|DOCMD_VERBOSE);
  2131.     retval = OK;
  2132. }
  2133. /*
  2134.  * When the command has set the b_changed flag, give a warning to the
  2135.  * user about this.
  2136.  */
  2137. if (tag_modified)
  2138. {
  2139.     secure = 2;
  2140.     EMSG("WARNING: tag command changed a buffer!!!");
  2141. }
  2142. if (secure == 2)     /* done something that is not allowed */
  2143.     wait_return(TRUE);
  2144. secure = save_secure;
  2145. p_magic = save_magic;
  2146. /* Return OK if jumped to another file (at least we found the file!). */
  2147. if (getfile_result == -1)
  2148.     retval = OK;
  2149. /*
  2150.  * For a help buffer: Put the cursor line at the top of the window,
  2151.  * the help subject will be below it.
  2152.  */
  2153. if (curbuf->b_help)
  2154. {
  2155.     set_topline(curwin, curwin->w_cursor.lnum);
  2156.     update_topline(); /* correct for 'so' */
  2157.     update_screen(NOT_VALID);
  2158. }
  2159. --RedrawingDisabled;
  2160.     }
  2161.     else
  2162.     {
  2163. --RedrawingDisabled;
  2164. if (postponed_split) /* close the window */
  2165. {
  2166.     close_window(curwin, FALSE);
  2167.     postponed_split = 0;
  2168. }
  2169.     }
  2170. erret:
  2171.     if (tagp.fname_end != NULL)
  2172. *tagp.fname_end = csave;
  2173.     vim_free(pbuf);
  2174.     vim_free(tofree_fname);
  2175.     vim_free(expanded_fname);
  2176.     return retval;
  2177. }
  2178. /*
  2179.  * If 'tagrelative' option set, change fname (name of file containing tag)
  2180.  * according to tag_fname (name of tag file containing fname).
  2181.  * Returns a pointer to allocated memory (or NULL when out of memory).
  2182.  */
  2183.     static char_u *
  2184. expand_rel_name(fname, tag_fname)
  2185.     char_u *fname;
  2186.     char_u *tag_fname;
  2187. {
  2188.     char_u *p;
  2189.     char_u *retval;
  2190.     if ((p_tr || curbuf->b_help) && !mch_isFullName(fname) &&
  2191.        (p = gettail(tag_fname)) != tag_fname)
  2192.     {
  2193. retval = alloc(MAXPATHL);
  2194. if (retval == NULL)
  2195.     return NULL;
  2196. STRCPY(retval, tag_fname);
  2197. STRNCPY(retval + (p - tag_fname), fname, MAXPATHL - (p - tag_fname));
  2198. /*
  2199.  * Translate names like "src/a/../b/file.c" into "src/b/file.c".
  2200.  */
  2201. simplify_filename(retval);
  2202.     }
  2203.     else
  2204. retval = vim_strsave(fname);
  2205.     return retval;
  2206. }
  2207. /*
  2208.  * Moves the tail part of the path (including the terminating NUL) pointed to
  2209.  * by "tail" to the new location pointed to by "here". This should accomodate
  2210.  * an overlapping move.
  2211.  */
  2212. #define movetail(here, tail)  mch_memmove(here, tail, STRLEN(tail) + (size_t)1)
  2213. /*
  2214.  * Converts a file name into a canonical form. It simplifies a file name into
  2215.  * its simplest form by stripping out unneeded components, if any.  The
  2216.  * resulting file name is simplified in place and will either be the same
  2217.  * length as that supplied, or shorter.
  2218.  */
  2219.     void
  2220. simplify_filename(filename)
  2221.     char_u *filename;
  2222. {
  2223. #ifndef AMIGA     /* Amiga doesn't have "..", it uses "/" */
  2224.     int     components = 0;
  2225.     char_u  *p, *tail, *start;
  2226. #ifdef UNIX
  2227.     char_u  *orig = vim_strsave(filename);
  2228.     if (orig == NULL)
  2229. return;
  2230. #endif
  2231.     p = filename;
  2232. #ifdef BACKSLASH_IN_FILENAME
  2233.     if (p[1] == ':')     /* skip "x:" */
  2234. p += 2;
  2235. #endif
  2236.     while (vim_ispathsep(*p))
  2237. ++p;
  2238.     start = p;     /* remember start after "c:/" or "/" or "//" */
  2239.     do
  2240.     {
  2241. /* At this point "p" is pointing to the char following a "/". */
  2242. if (vim_ispathsep(*p))
  2243.     movetail(p, p + 1); /* remove duplicate "/" */
  2244. else if (p[0] == '.' && vim_ispathsep(p[1]))
  2245.     movetail(p, p + 2); /* strip "./" */
  2246. else if (p[0] == '.' && p[1] == '.' && vim_ispathsep(p[2]))
  2247. {
  2248.     if (components > 0) /* strip one preceding component */
  2249.     {
  2250. tail = p + 3; /* skip to after "../" or "..///" */
  2251. while (vim_ispathsep(*tail))
  2252.     ++tail;
  2253. --p;
  2254. /* skip back to after previous '/' */
  2255. while (p > start && !vim_ispathsep(p[-1]))
  2256.     --p;
  2257. /* skip back to after first '/' in a row */
  2258. while (p - 1 > start && vim_ispathsep(p[-2]))
  2259.     --p;
  2260. movetail(p, tail); /* strip previous component */
  2261. --components;
  2262.     }
  2263.     else /* leading "../" */
  2264. p += 3; /* skip to char after "/" */
  2265. }
  2266. else
  2267. {
  2268.     ++components; /* simple path component */
  2269.     p = getnextcomp(p);
  2270. }
  2271.     } while (p != NULL && *p != NUL);
  2272. #ifdef UNIX
  2273.     /* Check that the new file name is really the same file.  This will not be
  2274.      * the case when using symbolic links: "dir/link/../name" != "dir/name". */
  2275.     {
  2276. struct stat orig_st, new_st;
  2277. if (    stat((char *)orig, &orig_st) < 0
  2278. || stat((char *)filename, &new_st) < 0
  2279. || orig_st.st_ino != new_st.st_ino
  2280. || orig_st.st_dev != new_st.st_dev)
  2281.     STRCPY(filename, orig);
  2282. vim_free(orig);
  2283.     }
  2284. #endif
  2285. #endif /* !AMIGA */
  2286. }
  2287. /*
  2288.  * Check if we have a tag for the current file.
  2289.  * This is a bit slow, because of the full path compare in fullpathcmp().
  2290.  * Return TRUE if tag for file "fname" if tag file "tag_fname" is for current
  2291.  * file.
  2292.  */
  2293.     static int
  2294. #ifdef EMACS_TAGS
  2295. test_for_current(is_etag, fname, fname_end, tag_fname)
  2296.     int     is_etag;
  2297. #else
  2298. test_for_current(fname, fname_end, tag_fname)
  2299. #endif
  2300.     char_u  *fname;
  2301.     char_u  *fname_end;
  2302.     char_u  *tag_fname;
  2303. {
  2304.     int     c;
  2305.     int     retval = FALSE;
  2306.     char_u  *relname;
  2307.     if (curbuf->b_ffname != NULL) /* if the current buffer has a name */
  2308.     {
  2309. #ifdef EMACS_TAGS
  2310. if (is_etag)
  2311.     c = 0;     /* to shut up GCC */
  2312. else
  2313. #endif
  2314. {
  2315.     c = *fname_end;
  2316.     *fname_end = NUL;
  2317. }
  2318. relname = expand_rel_name(fname, tag_fname);
  2319. if (relname != NULL)
  2320. {
  2321.     retval = (fullpathcmp(relname, curbuf->b_ffname, TRUE) & FPC_SAME);
  2322.     vim_free(relname);
  2323. }
  2324. #ifdef EMACS_TAGS
  2325. if (!is_etag)
  2326. #endif
  2327.     *fname_end = c;
  2328.     }
  2329.     return retval;
  2330. }
  2331. /*
  2332.  * Find the end of the tagaddress.
  2333.  * Return OK if ";"t" is following, FAIL otherwise.
  2334.  */
  2335.     static int
  2336. find_extra(pp)
  2337.     char_u **pp;
  2338. {
  2339.     char_u *str = *pp;
  2340.     /* Repeat for addresses separated with ';' */
  2341.     for (;;)
  2342.     {
  2343. if (isdigit(*str))
  2344.     str = skipdigits(str);
  2345. else if (*str == '/' || *str == '?')
  2346. {
  2347.     str = skip_regexp(str + 1, *str, FALSE);
  2348.     if (*str != **pp)
  2349. str = NULL;
  2350.     else
  2351. ++str;
  2352. }
  2353. else
  2354.     str = NULL;
  2355. if (str == NULL || *str != ';'
  2356.       || !(isdigit(str[1]) || str[1] == '/' || str[1] == '?'))
  2357.     break;
  2358. ++str; /* skip ';' */
  2359.     }
  2360.     if (str != NULL && STRNCMP(str, ";"t", 3) == 0)
  2361.     {
  2362. *pp = str;
  2363. return OK;
  2364.     }
  2365.     return FAIL;
  2366. }