📄 entry.c
字号:
/*****************************************************************************
* $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 + -