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

📄 entry.c

📁 VIM文本编辑器
💻 C
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************************
*   $Id: entry.c,v 6.4 1998/07/22 02:32:58 darren Exp $
*
*   Copyright (c) 1996-1998, Darren Hiebert
*
*   This source code is released for free distribution under the terms of the
*   GNU General Public License.
*
*   This module contains functions for creating tag entries.
*****************************************************************************/

/*============================================================================
=   Include files
============================================================================*/
#include <stdio.h>
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef DEBUG
# include <assert.h>
#endif
#include "ctags.h"

/*============================================================================
 *=	Defines
============================================================================*/
#define includeExtensionFlags()		(Option.tagFileFormat > 1)

/*============================================================================
=   Data definitions
============================================================================*/

/*  Note that the strings and characters in these arrays must correspond to
 *  the types in the tagType enumeration.
 */
static const char *TagTypeNames[] = {
    "class", "define", "macro", "enum", "enumerator", "prototype", "function",
    "interface", "member", "namespace", "file", "struct", "typedef", "union",
    "variable", "externvar"
};

static const char TagTypeChars[] = "cddgepfimnFstuvx";

/*============================================================================
=   Function prototypes
============================================================================*/
static size_t writeSourceLine __ARGS((FILE *const fp, const char *const line));
static size_t writeCompactSourceLine __ARGS((FILE *const fp, const char *const line));
static void rememberMaxLengths __ARGS((const size_t nameLength, const size_t lineLength));
static void writeXrefEntry __ARGS((const tagInfo *const tag, const tagType type));
static void truncateTagLine __ARGS((char *const line, const char *const token, const boolean discardNewline));
static int writeEtagsEntry __ARGS((const tagInfo *const tag, const memberInfo *const pMember, const tagScope scope, const tagType type));
static int addExtensionFlags __ARGS((const memberInfo *const pMember, const tagScope scope, const tagType type));
static int writeLineNumberEntry __ARGS((const tagInfo *const tag));
static int writePatternEntry __ARGS((const tagInfo *const tag, const tagType type));
static int writeCtagsEntry __ARGS((const tagInfo *const tag, const memberInfo *const pMember, const tagScope scope, const tagType type, const boolean useLineNumber));
static void writeTagEntry __ARGS((const tagInfo *const tag, const memberInfo *const pMember, const tagScope scope, const tagType type, const boolean useLineNumber));
static boolean includeTag __ARGS((const tagScope scope, const tagType type));
static void writeExtraMemberTagEntry __ARGS((const tagInfo *const tag, const memberInfo *const pMember, const tagScope scope, const tagType type, const boolean useLineNumber, const char *const format));
static void makeExtraMemberTagEntry __ARGS((const tagInfo *const tag, const memberInfo *const pMember, const tagScope scope, const tagType type, const boolean useLineNumber));
static void makeTagEntry __ARGS((const tagInfo *const tag, const memberInfo *const pMember, const tagScope scope, const tagType type, const boolean useLineNumber));
static void writePseudoTag __ARGS((const char *const tagName, const char *const fileName, const char *const pattern));
static void updateSortedFlag __ARGS((const char *const line, FILE *const fp, const long startOfLine));

/*============================================================================
=   Function definitions
============================================================================*/

extern const char *tagTypeName( type )
    const tagType type;
{
    const char *name;

    if ((int)type < (int)TAG_NUMTYPES)
	name = TagTypeNames[(int)type];
    else
	name = "?";

    return name;
}

/*  This function copies the current line out some other fp.  It has no
 *  effect on the fileGetc() function.  During copying, any '\' characters
 *  are doubled and a leading '^' or trailing '$' is also quoted.  The '\n'
 *  character is not copied.  If the '\n' is preceded by a '\r', then the
 *  '\r' isn't copied.
 *
 *  This is meant to be used when generating a tag line.
 */
static size_t writeSourceLine( fp, line )
    FILE *const fp;
    const char *const line;
{
    size_t length = 0;
    const char *p;
    int c;

    /*	Write everything up to, but not including, the newline.
     */
    for (p = line, c = *p  ;  c != NEWLINE  &&  c != '\0'  ;  ++p, c = *p)
    {
	const int next = *(p + 1);

	/*  If character is '\', or a terminal '$', then quote it.
	 */
	if (c == BACKSLASH  ||  c == (Option.backward ? '?' : '/')  ||
	    (c == '$'  &&  next == NEWLINE))
	{
	    putc(BACKSLASH, fp);
	    ++length;
	}

	/*  Copy the character, unless it is a terminal '\r'.
	 */
	if (c != CRETURN  ||  next != NEWLINE)
	{
	    putc(c, fp);
	    ++length;
	}
    }
    return length;
}

/*  Writes "line", stripping leading and duplicate white space.
 */
static size_t writeCompactSourceLine( fp, line )
    FILE *const fp;
    const char *const line;
{
    boolean lineStarted = FALSE;
    size_t  length = 0;
    const char *p;
    int c;

    /*	Write everything up to, but not including, the newline.
     */
    for (p = line, c = *p  ;  c != NEWLINE  &&  c != '\0'  ;  c = *++p)
    {
	if (lineStarted  || ! isspace(c))	/* ignore leading spaces */
	{
	    lineStarted = TRUE;
	    if (isspace(c))
	    {
		int next;

		/*  Consume repeating white space.
		 */
		while (next = *(p+1) , isspace(next)  &&  next != NEWLINE)
		    ++p;
		c = ' ';	/* force space character for any white space */
	    }
	    if (c != CRETURN  ||  *(p + 1) != NEWLINE)
	    {
		putc(c, fp);
		++length;
	    }
	}
    }
    return length;
}

static void rememberMaxLengths( nameLength, lineLength )
    const size_t nameLength;
    const size_t lineLength;
{
    if (nameLength > TagFile.max.tag)
	TagFile.max.tag = nameLength;

    if (lineLength > TagFile.max.line)
	TagFile.max.line = lineLength;
}

static void writeXrefEntry( tag, type )
    const tagInfo *const tag;
    const tagType type;
{
    const char *const line = getSourceLine(&TagFile.line, tag->location);
    size_t length = fprintf(TagFile.fp, "%-20s %-10s %4lu  %-14s ",
			    tag->name, tagTypeName(type), tag->lineNumber,
			    File.name);

    length += writeCompactSourceLine(TagFile.fp, line);
    putc(NEWLINE, TagFile.fp);
    ++length;

    ++TagFile.numTags.added;
    rememberMaxLengths(strlen(tag->name), length);
}

/*  Truncates the text line containing the tag at the character following the
 *  tag, providing a character which designates the end of the tag.
 */
static void truncateTagLine( line, token, discardNewline )
    char *const line;
    const char *const token;
    const boolean discardNewline;
{
    char *p = strstr(line, token);

    if (p != NULL)
    {
	p += strlen(token);
	if (*p != '\0'  &&  !(*p == '\n'  &&  discardNewline))
	    ++p;		/* skip past character terminating character */
	*p = '\0';
    }
}

static int writeEtagsEntry( tag, pMember, scope, type )
    const tagInfo *const tag;
    const memberInfo *const pMember;
    const tagScope scope;
    const tagType type;
{
    char *const line = getSourceLine(&TagFile.line, tag->location);
    int length;

    truncateTagLine(line, tag->name, TRUE);
    if (pMember->type != MEMBER_NONE)
	length = fprintf(TagFile.etags.fp, "%s\177%s:%s\001%lu,%ld\n", line,
			 pMember->parent, tag->name, tag->lineNumber,
			 tag->location);
    else if (scope == SCOPE_STATIC)
	length = fprintf(TagFile.etags.fp, "%s\177%s:%s\001%lu,%ld\n", line,
			 File.name, tag->name, tag->lineNumber, tag->location);
    else if (type == TAG_CLASS   ||  type == TAG_DEFINE_FUNC  ||
	     type == TAG_ENUM    ||  type == TAG_STRUCT	      ||
	     type == TAG_TYPEDEF ||  type == TAG_UNION)
	length = fprintf(TagFile.etags.fp, "%s\177%s\001%lu,%ld\n", line,
			 tag->name, tag->lineNumber, tag->location);
    else
	length = fprintf(TagFile.etags.fp, "%s\177%lu,%ld\n", line,
			 tag->lineNumber, tag->location);
    TagFile.etags.byteCount += length;
    return length;
}

extern const char *getTypeString( mType )
    const memberType mType;
{
    const char *typeString;

    switch (mType)
    {
	case MEMBER_ENUM:	typeString = "enum";		break;
	case MEMBER_CLASS:	typeString = "class";		break;
	case MEMBER_INTERFACE:	typeString = "interface";	break;
	case MEMBER_NAMESPACE:	typeString = "namespace";	break;
	case MEMBER_STRUCT:	typeString = "struct";		break;
	case MEMBER_UNION:	typeString = "union";		break;
	default:		typeString = "";		break;
    }
    return typeString;
}

extern const char *getVisibilityString( visibility )
    const visibilityType visibility;
{
    const char *visibilityString;

    switch (visibility)
    {
	case VIS_PRIVATE:	visibilityString = "private";		break;
	case VIS_PROTECTED:	visibilityString = "protected";		break;
	case VIS_PUBLIC:	visibilityString = "public";		break;
	default:		visibilityString = "";			break;
    }
    return visibilityString;
}

static int addExtensionFlags( pMember, scope, type )
    const memberInfo *const pMember;
    const tagScope scope;
    const tagType type;
{
    const char *const prefix = ";\"\t";
    const char *const separator = "\t";
    int length = 0;
#ifdef LONG_FORM_TYPE
    const char *const format = "%skind:%c";
#else
    const char *const format = "%s%c";
#endif

    /*  Add an extension flag designating that the type of the tag.
     */
    length += fprintf(TagFile.fp, format, prefix, TagTypeChars[(int)type]);

    /*  If this is a static tag, add the appropriate extension flag.
     */
    if (scope == SCOPE_STATIC)
	length += fprintf(TagFile.fp, "%sfile:", separator);

    /*  For selected tag types, append an extension flag designating the
     *  parent object in which the tag is defined.
     */
    switch (type)
    {
	case TAG_DEFINE_FUNC:
	case TAG_DEFINE_OBJ:
	default:
	    /* always global scope */
	    break;

	case TAG_ENUMERATOR:
	case TAG_FUNCDECL:
	case TAG_FUNCTION:
	case TAG_MEMBER:
	case TAG_TYPEDEF:
	case TAG_VARIABLE:
	{
	    if (pMember->type != MEMBER_NONE)

⌨️ 快捷键说明

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