⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tag.c

📁 VIM文本编辑器
💻 C
📖 第 1 页 / 共 5 页
字号:
	     * Not jumping around in the file: Read the next line.
	     */
	    else
#endif
	    {
		/* skip empty and blank lines */
		do
		{
#ifdef USE_CSCOPE
		    if (use_cscope)
			eof = cs_fgets(lbuf, LSIZE);
		    else
#endif
			eof = vim_fgets(lbuf, LSIZE, fp);
		} while (!eof && vim_isblankline(lbuf));

		if (eof
#ifdef USE_CSCOPE
			&& !use_cscope
#endif
				       )
#ifdef EMACS_TAGS
		    if (incstack_idx)	/* this was an included file */
		    {
			--incstack_idx;
			fclose(fp);	/* end of this file ... */
			fp = incstack[incstack_idx].fp;
			STRCPY(tag_fname, incstack[incstack_idx].etag_fname);
			vim_free(incstack[incstack_idx].etag_fname);
			is_etag = 1;	/* (only etags can include) */
			continue;	/* ... continue with parent file */
		    }
		    else
#endif
			break;			    /* end of file */
	    }
line_read_in:

#ifdef EMACS_TAGS
	    /*
	     * Emacs tags line with CTRL-L: New file name on next line.
	     * The file name is followed by a ','.
	     */
	    if (*lbuf == Ctrl('L'))	/* remember etag file name in ebuf */
	    {
		is_etag = 1;		/* in case at the start */
		state = TS_LINEAR;
		if (!vim_fgets(ebuf, LSIZE, fp))
		{
		    for (p = ebuf; *p && *p != ','; p++)
			;
		    *p = NUL;

		    /*
		     * atoi(p+1) is the number of bytes before the next ^L
		     * unless it is an include statement.
		     */
		    if (STRNCMP(p + 1, "include", 7) == 0
					      && incstack_idx < INCSTACK_SIZE)
		    {
			if ((incstack[incstack_idx].etag_fname =
					      vim_strsave(tag_fname)) != NULL)
			{
			    incstack[incstack_idx].fp = fp;
			    if ((fp = fopen((char *)ebuf, "r")) == NULL)
			    {
				fp = incstack[incstack_idx].fp;
				vim_free(incstack[incstack_idx].etag_fname);
			    }
			    else
			    {
				STRCPY(tag_fname, ebuf);
				++incstack_idx;
			    }
			    is_etag = 0;	/* we can include anything */
			}
		    }
		}
		continue;
	    }
#endif

	    /*
	     * When still at the start of the file, check for Emacs tags file
	     * format, and for "not sorted" flag.
	     */
	    if (state == TS_START)
	    {
#ifdef BINARY_TAGS
		/*
		 * When there is no tag head, or ignoring case, need to do a
		 * linear search.
		 * When no "!_TAG_" is found, default to binary search.  If
		 * the tag file isn't sorted, the second loop will find it.
		 * When "!_TAG_FILE_SORTED" found: start binary search if
		 * flag set.
		 * For cscope, it's always linear.
		 */
#ifdef USE_CSCOPE
		if (linear || use_cscope)
#else
		if (linear)
#endif
		    state = TS_LINEAR;
		else if (STRNCMP(lbuf, "!_TAG_", 6) > 0)
		    state = TS_BINARY;
		else if (STRNCMP(lbuf, "!_TAG_FILE_SORTED\t", 18) == 0)
		{
		    /* Check sorted flag */
		    if (lbuf[18] == '1')
			state = TS_BINARY;
		    else
			state = TS_LINEAR;
		}
#else
		state = TS_LINEAR;
#endif

#ifdef BINARY_TAGS
		/*
		 * When starting a binary search, get the size of the file and
		 * compute the first offset.
		 */
		if (state == TS_BINARY)
		{
		    /* Get the tag file size (don't use fstat(), it's not
		     * portable). */
		    if ((filesize = lseek(fileno(fp),
						   (off_t)0L, SEEK_END)) <= 0)
			state = TS_LINEAR;
		    else
		    {
			lseek(fileno(fp), (off_t)0L, SEEK_SET);

			/* Calculate the first read offset in the file.  Start
			 * the search in the middle of the file.
			 */
			search_info.low_offset = 0;
			search_info.low_char = 0;
			search_info.high_offset = filesize;
			search_info.high_char = 0xff;
		    }
		    continue;
		}
#endif
	    }

	    /*
	     * Figure out where the different strings are in this line.
	     * For "normal" tags: Do a quick check if the tag matches.
	     * This speeds up tag searching a lot!
	     */
	    if (patheadlen
#ifdef EMACS_TAGS
			    && !is_etag
#endif
					)
	    {
		tagp.tagname = lbuf;
#ifdef TAG_ANY_WHITE
		tagp.tagname_end = skiptowhite(lbuf);
		if (*tagp.tagname_end == NUL)	    /* corrupted tag line */
#else
		tagp.tagname_end = vim_strchr(lbuf, TAB);
		if (tagp.tagname_end == NULL)	    /* corrupted tag line */
#endif
		{
		    EMSG2(e_tagformat, tag_fname);
		    stop_searching = TRUE;
		    break;
		}

#ifdef OLD_STATIC_TAGS
		/*
		 * Check for old style static tag: "file:tag file .."
		 */
		tagp.fname = NULL;
		for (p = lbuf; p < tagp.tagname_end; ++p)
		{
		    if (*p == ':')
		    {
			if (tagp.fname == NULL)
#ifdef TAG_ANY_WHITE
			    tagp.fname = skipwhite(tagp.tagname_end);
#else
			    tagp.fname = tagp.tagname_end + 1;
#endif
			if (	   fnamencmp(lbuf, tagp.fname, p - lbuf) == 0
#ifdef TAG_ANY_WHITE
				&& vim_iswhite(tagp.fname[p - lbuf])
#else
				&& tagp.fname[p - lbuf] == TAB
#endif
				    )
			{
			    /* found one */
			    tagp.tagname = p + 1;
			    break;
			}
		    }
		}
#endif

		/*
		 * Skip this line if the length of the tag is different and
		 * there is no regexp, or the tag is too short.
		 */
		cmplen = tagp.tagname_end - tagp.tagname;
		if (p_tl != 0 && cmplen > p_tl)	    /* adjust for 'taglength' */
		    cmplen = p_tl;
		if (has_re && patheadlen < cmplen)
		    cmplen = patheadlen;
		else if (state == TS_LINEAR && patheadlen != cmplen)
		    continue;

#ifdef BINARY_TAGS
		if (state == TS_BINARY)
		{
		    /*
		     * Simplistic check for unsorted tags file.
		     */
		    if ((int)tagp.tagname[0] < search_info.low_char
			    || (int)tagp.tagname[0] > search_info.high_char)
			sort_error = TRUE;

		    /*
		     * Compare the current tag with the searched tag.
		     */
		    tagcmp = STRNCMP(tagp.tagname, pathead, cmplen);

		    /*
		     * A match with a shorter tag means to search forward.
		     * A match with a longer tag means to search backward.
		     */
		    if (tagcmp == 0)
		    {
			if (cmplen < patheadlen)
			    tagcmp = -1;
			else if (cmplen > patheadlen)
			    tagcmp = 1;
		    }

		    if (tagcmp == 0)
		    {
			/* We've located the tag, now skip back and search
			 * forward until the first matching tag is found.
			 */
			state = TS_SKIP_BACK;
			search_info.match_offset = search_info.curr_offset;
			continue;
		    }
		    if (tagcmp < 0)
		    {
			search_info.curr_offset = ftell(fp);
			if (search_info.curr_offset < search_info.high_offset)
			{
			    search_info.low_offset = search_info.curr_offset;
			    search_info.low_char = tagp.tagname[0];
			    continue;
			}
		    }
		    if (tagcmp > 0
			&& search_info.curr_offset != search_info.high_offset)
		    {
			search_info.high_offset = search_info.curr_offset;
			search_info.high_char = tagp.tagname[0];
			continue;
		    }

		    /* No match yet and are at the end of the binary search. */
		    break;
		}
		else if (state == TS_SKIP_BACK)
		{
		    if (STRNICMP(tagp.tagname, pathead, cmplen) != 0)
			state = TS_STEP_FORWARD;
		    continue;
		}
		else if (state == TS_STEP_FORWARD)
		{
		    if (STRNICMP(tagp.tagname, pathead, cmplen))
		    {
			if (ftell(fp) > search_info.match_offset)
			    break;	/* past last match */
			else
			    continue;	/* before first match */
		    }
		}
		else
#endif
		    /* skip this match if it can't match */
		    if (STRNICMP(tagp.tagname, pathead, cmplen))
		    continue;

		/*
		 * Can be a matching tag, isolate the file name and command.
		 */
#ifdef OLD_STATIC_TAGS
		if (tagp.fname == NULL)
#endif
#ifdef TAG_ANY_WHITE
		    tagp.fname = skipwhite(tagp.tagname_end);
#else
		    tagp.fname = tagp.tagname_end + 1;
#endif
#ifdef TAG_ANY_WHITE
		tagp.fname_end = skiptowhite(tagp.fname);
		tagp.command = skipwhite(tagp.fname_end);
		if (*tagp.command == NUL)
#else
		tagp.fname_end = vim_strchr(tagp.fname, TAB);
		tagp.command = tagp.fname_end + 1;
		if (tagp.fname_end == NULL)
#endif
		    i = FAIL;
		else
		    i = OK;
	    }
	    else
		i = parse_tag_line(lbuf,
#ifdef EMACS_TAGS
				       is_etag,
#endif
					       &tagp);
	    if (i == FAIL)
	    {
		EMSG2(e_tagformat, tag_fname);
		stop_searching = TRUE;
		break;
	    }

#ifdef EMACS_TAGS
	    if (is_etag)
		tagp.fname = ebuf;
#endif
	    /*
	     * First try matching with the pattern literally (also when it is
	     * a regexp).
	     */
	    cmplen = tagp.tagname_end - tagp.tagname;
	    if (p_tl != 0 && cmplen > p_tl)	    /* adjust for 'taglength' */
		cmplen = p_tl;
	    /* if tag length does not match, don't try comparing */
	    if (patlen != cmplen)
		match = FALSE;
	    else
	    {
		if (reg_ic)
		{
		    match = (STRNICMP(tagp.tagname, pat, cmplen) == 0);
		    if (match)
			match_no_ic = (STRNCMP(tagp.tagname, pat, cmplen) == 0);
		}
		else
		    match = (STRNCMP(tagp.tagname, pat, cmplen) == 0);
	    }

	    /*
	     * Has a regexp: Also find tags matching regexp "prog".
	     */
	    match_re = FALSE;
	    if (!match && prog != NULL)
	    {
		int	cc;

		cc = *tagp.tagname_end;
		*tagp.tagname_end = NUL;
		match = vim_regexec(prog, tagp.tagname, TRUE);
		matchoff = (int)(prog->startp[0] - tagp.tagname);
		if (match && reg_ic)
		{
		    reg_ic = FALSE;
		    match_no_ic = vim_regexec(prog, tagp.tagname, TRUE);
		    reg_ic = TRUE;
		}
		*tagp.tagname_end = cc;
		match_re = TRUE;
	    }

	    /*
	     * If a match is found, add it to ga_match[].
	     */
	    if (match)
	    {
		/* Decide in which array to store this match. */
		is_current = test_for_current(
#ifdef EMACS_TAGS
			is_etag,
#endif
				 tagp.fname, tagp.fname_end, tag_fname);
#ifdef EMACS_TAGS
		is_static = FALSE;
		if (!is_etag)	/* emacs tags are never static */
#endif
		{
#ifdef OLD_STATIC_TAGS
		    if (tagp.tagname != lbuf)	/* detected static tag before */
			is_static = TRUE;
		    else
#endif
			is_static = test_for_static(&tagp);
		}

		/* decide in which of the six table to store this match */
		if (is_static)
		{
		    if (is_current)
			mtt = MT_ST_CUR;
		    else
			mtt = MT_ST_OTH;
		}
		else
		{
		    if (is_current)
			mtt = MT_GL_CUR;
		    else
			mtt = MT_GL_OTH;
		}
		if (reg_ic && !match_no_ic)
		    mtt += MT_IC_OFF;
		if (match_re)
		    mtt += MT_RE_OFF;

		if (ga_grow(&ga_match[mtt], 1) == OK)
		{
		    if (help_only)
		    {
			/*
			 * Append the help-heuristic number after the
			 * tagname, for sorting it later.
			 */
			*tagp.tagname_end = NUL;
			len = tagp.tagname_end - tagp.tagname;
			p = vim_strnsave(tagp.tagname, len + 10);
			if (p != NULL)
			    sprintf((char *)p + len + 1, "%06d",
				    help_heuristic(tagp.tagname,
				    match_re ? matchoff : 0, !match_no_ic));
			*tagp.tagname_end = TAB;
			++len;	/* compare one more char */
		    }
		    else if (name_only)
		    {
			p = NULL;
			len = 0;
			if (get_it_again)
			{
			    char_u *temp_end = tagp.command;

			    if ((*temp_end) == '/')
				while ( *temp_end && (*temp_end != '\r')
					&& (*temp_end != '\n')
					&& (*temp_end != '$'))
				    temp_end++;

			    if ((tagp.command + 2) < temp_end)
			    {
				len = temp_end - tagp.command - 2;
				p = vim_strnsave(tagp.command + 2, len);
			    }
			    get_it_again = FALSE;
			}
			else
			{
			    len = tagp.tagname_end - tagp.tagname;
			    p = vim_strnsave(tagp.tagname, len);
			    /* if wanted, re-read line to get long form too*/
			    if (State & INSERT)
				get_it_again = p_sft;
			}
			++len;	/* compare one more char */
		    }
		    else
		    {
			/* Save the tag in a buffer.
			 * Emacs tag: <mtt><tag_fname><NUL><ebuf><NUL><lbuf>
			 * other tag: <mtt><tag_fname><NUL><NUL><lbuf>
			 * without Emacs tags: <mtt><tag_fname><NUL><lbuf>
			 */
			len = STRLEN(tag_fname) + STRLEN(lbuf) + 3;
#ifdef EMACS_TAGS
			if (is_etag)
			    len += STRLEN(ebuf) + 1;
			else
			    ++len;
#endif
			p = alloc(len);
			if (p != NULL)
			{
			    p[0] = mtt;
			    STRCPY(p + 1, tag_fname);
			    s = p + 1 + STRLEN(tag_fname) + 1;
#ifdef EMACS_TAGS
			    if (is_etag)
			    {
				STRCPY(s, ebuf);
				s += STRLEN(ebuf) + 1;
			    }
			    else
				*s++ = NUL;
#endif
			    STRCPY(s, lbuf);
			}
		    }

		    if (p != NULL)
		    {
			/*
			 * Don't add identical matches.
			 */
			for (i = ga_match[mtt].ga_len; --i >= 0; )

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -