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