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