entry.c
资源名称:vim53src.zip [点击查看]
上传用户:gddssl
上传日期:2007-01-06
资源大小:1003k
文件大小:20k
源码类别:
编辑器/阅读器
开发平台:
DOS
- /*****************************************************************************
- * $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 != ' ' ; ++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 != ' ' ; 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 != ' ' && !(*p == 'n' && discardNewline))
- ++p; /* skip past character terminating character */
- *p = ' ';
- }
- }
- 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, "%s177%s:%s 01%lu,%ldn", line,
- pMember->parent, tag->name, tag->lineNumber,
- tag->location);
- else if (scope == SCOPE_STATIC)
- length = fprintf(TagFile.etags.fp, "%s177%s:%s 01%lu,%ldn", 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, "%s177%s 01%lu,%ldn", line,
- tag->name, tag->lineNumber, tag->location);
- else
- length = fprintf(TagFile.etags.fp, "%s177%lu,%ldn", 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)
- {
- length += fprintf(TagFile.fp, "%s%s:%s", separator,
- getTypeString(pMember->type),pMember->parent);
- if ((File.language == LANG_CPP || File.language == LANG_JAVA) &&
- pMember->visibility != VIS_UNDEFINED)
- {
- length += fprintf(TagFile.fp, "%s%s:", separator,
- getVisibilityString(pMember->visibility));
- }
- }
- break;
- }
- }
- return length;
- }
- static int writeLineNumberEntry( tag )
- const tagInfo *const tag;
- {
- return fprintf(TagFile.fp, "%lu", tag->lineNumber);
- }
- static int writePatternEntry( tag, type )
- const tagInfo *const tag;
- const tagType type;
- {
- char *const line = getSourceLine(&TagFile.line, tag->location);
- const int searchChar = Option.backward ? '?' : '/';
- boolean newlineTerminated;
- int length = 0;
- if (type == TAG_DEFINE_OBJ || type == TAG_DEFINE_FUNC)
- truncateTagLine(line, tag->name, FALSE);
- newlineTerminated = (boolean)(line[strlen(line) - 1] == 'n');
- length += fprintf(TagFile.fp, "%c^", searchChar);
- length += writeSourceLine(TagFile.fp, line);
- length += fprintf(TagFile.fp, "%s%c", newlineTerminated ? "$":"",
- searchChar);
- return length;
- }
- static int writeCtagsEntry( tag, pMember, scope, type, useLineNumber )
- const tagInfo *const tag;
- const memberInfo *const pMember;
- const tagScope scope;
- const tagType type;
- const boolean useLineNumber;
- {
- int length = fprintf(TagFile.fp, "%st%st", tag->name, File.name);
- if (useLineNumber || type == TAG_SOURCE_FILE)
- length += writeLineNumberEntry(tag);
- else
- length += writePatternEntry(tag, type);
- if (includeExtensionFlags())
- length += addExtensionFlags(pMember, scope, type);
- length += fprintf(TagFile.fp, "n");
- return length;
- }
- static void writeTagEntry( tag, pMember, scope, type, useLineNumber )
- const tagInfo *const tag;
- const memberInfo *const pMember;
- const tagScope scope;
- const tagType type;
- const boolean useLineNumber;
- {
- size_t length;
- if (Option.etags)
- length = writeEtagsEntry(tag, pMember, scope, type);
- else
- length = writeCtagsEntry(tag, pMember, scope, type, useLineNumber);
- ++TagFile.numTags.added;
- rememberMaxLengths(strlen(tag->name), length);
- }
- static boolean includeTag( scope, type )
- const tagScope scope;
- const tagType type;
- {
- boolean include;
- if (scope == SCOPE_STATIC && ! Option.include.statics)
- include = FALSE;
- else switch (type)
- {
- case TAG_CLASS: include = Option.include.classNames; break;
- case TAG_DEFINE_OBJ:
- case TAG_DEFINE_FUNC: include = Option.include.defines; break;
- case TAG_ENUM: include = Option.include.enumNames; break;
- case TAG_ENUMERATOR: include = Option.include.enumerators; break;
- case TAG_FUNCDECL: include = Option.include.prototypes; break;
- case TAG_FUNCTION: include = Option.include.functions; break;
- case TAG_INTERFACE: include = Option.include.interfaceNames;break;
- case TAG_MEMBER: include = Option.include.members; break;
- case TAG_NAMESPACE: include = Option.include.namespaceNames;break;
- case TAG_SOURCE_FILE: include = Option.include.sourceFiles; break;
- case TAG_STRUCT: include = Option.include.structNames; break;
- case TAG_TYPEDEF: include = Option.include.typedefs; break;
- case TAG_UNION: include = Option.include.unionNames; break;
- case TAG_VARIABLE: include = Option.include.variables; break;
- case TAG_EXTERN_VAR: include = Option.include.externVars; break;
- default: include = FALSE; break;
- }
- return include;
- }
- static void writeExtraMemberTagEntry( tag, pMember, scope, type,
- useLineNumber, format )
- const tagInfo *const tag;
- const memberInfo *const pMember;
- const tagScope scope;
- const tagType type;
- const boolean useLineNumber;
- const char *const format;
- {
- switch (type)
- {
- case TAG_FUNCDECL:
- case TAG_FUNCTION:
- case TAG_MEMBER:
- {
- tagInfo prefixedTag;
- prefixedTag = *tag;
- sprintf(prefixedTag.name, format, pMember->parent, tag->name);
- writeTagEntry(&prefixedTag, pMember, scope, type, useLineNumber);
- }
- default: break;
- }
- }
- static void makeExtraMemberTagEntry( tag, pMember, scope, type, useLineNumber )
- const tagInfo *const tag;
- const memberInfo *const pMember;
- const tagScope scope;
- const tagType type;
- const boolean useLineNumber;
- {
- if (File.language == LANG_CPP &&
- (pMember->type == MEMBER_CLASS || pMember->type == MEMBER_STRUCT))
- {
- writeExtraMemberTagEntry(tag, pMember, scope, type, useLineNumber, "%s::%s");
- }
- else if (File.language == LANG_JAVA && pMember->type == MEMBER_CLASS)
- {
- writeExtraMemberTagEntry(tag, pMember, scope, type, useLineNumber, "%s.%s");
- }
- }
- /* This function generates a tag for the object in name, whose tag line is
- * located at a given seek offset.
- */
- static void makeTagEntry( tag, pMember, scope, type, useLineNumber )
- const tagInfo *const tag;
- const memberInfo *const pMember;
- const tagScope scope;
- const tagType type;
- const boolean useLineNumber;
- {
- if (includeTag(scope, type) && tag->name[0] != ' ')
- {
- if (Option.xref)
- writeXrefEntry(tag, type);
- else
- {
- writeTagEntry(tag, pMember, scope, type, useLineNumber);
- if (Option.include.classPrefix && pMember->parent[0] != '0')
- makeExtraMemberTagEntry(tag, pMember, scope, type, useLineNumber);
- }
- DebugStatement( debugEntry(scope, type, tag->name, pMember); )
- }
- }
- extern void makeTag( tag, pMember, scope, type )
- const tagInfo *const tag;
- const memberInfo *const pMember;
- const tagScope scope;
- const tagType type;
- {
- makeTagEntry(tag, pMember, scope, type,
- (boolean)(Option.locate == EX_LINENUM));
- }
- extern void makeDefineTag( tag, scope, parameterized )
- const tagInfo *const tag;
- const tagScope scope;
- const boolean parameterized;
- {
- const tagType type = (parameterized ? TAG_DEFINE_FUNC : TAG_DEFINE_OBJ);
- makeTagEntry(tag, &NoClass, scope, type,
- (boolean)(Option.locate != EX_PATTERN));
- }
- /*----------------------------------------------------------------------------
- *- Pseudo tag support
- ----------------------------------------------------------------------------*/
- static void writePseudoTag( tagName, fileName, pattern )
- const char *const tagName;
- const char *const fileName;
- const char *const pattern;
- {
- const size_t length = fprintf(TagFile.fp, "%s%st%st/%s/n",
- PSEUDO_TAG_PREFIX, tagName, fileName, pattern);
- ++TagFile.numTags.added;
- rememberMaxLengths(strlen(tagName), length);
- }
- extern void addPseudoTags()
- {
- if (! Option.xref && ! Option.etags)
- {
- char format[11];
- const char *formatComment = "unknown format";
- sprintf(format, "%u", Option.tagFileFormat);
- if (Option.tagFileFormat == 1)
- formatComment = "original ctags format";
- else if (Option.tagFileFormat == 2)
- formatComment =
- "extended format; --format=1 will not append ;" to lines";
- writePseudoTag("TAG_FILE_FORMAT", format, formatComment);
- writePseudoTag("TAG_FILE_SORTED", Option.sorted ? "1":"0",
- "0=unsorted, 1=sorted");
- writePseudoTag("TAG_PROGRAM_AUTHOR", AUTHOR_NAME, AUTHOR_EMAIL);
- writePseudoTag("TAG_PROGRAM_NAME", PROGRAM_NAME, "");
- writePseudoTag("TAG_PROGRAM_URL", PROGRAM_URL, "official site");
- writePseudoTag("TAG_PROGRAM_VERSION", PROGRAM_VERSION,
- "with C++ and Java support");
- }
- }
- static void updateSortedFlag( line, fp, startOfLine )
- const char *const line;
- FILE *const fp;
- const long startOfLine;
- {
- const char *const tab = strchr(line, 't');
- if (tab != NULL)
- {
- const long boolOffset = tab - line + 1; /* where it should be */
- if (line[boolOffset] == '0' || line[boolOffset] == '1')
- {
- const long nextLine = ftell(fp);
- fseek(fp, startOfLine + boolOffset, SEEK_SET);
- fputc(Option.sorted ? '1' : '0', fp);
- fseek(fp, nextLine, SEEK_SET);
- }
- }
- }
- /* Look through all line beginning with "!_TAG_FILE", and update those which
- * require it.
- */
- extern unsigned long updatePseudoTags()
- {
- enum { maxClassLength = 20 };
- char class[maxClassLength + 1];
- FILE *const fp = TagFile.fp;
- long startOfLine = 0;
- unsigned long linesRead = 0;
- size_t classLength;
- const char *line;
- sprintf(class, "%sTAG_FILE", PSEUDO_TAG_PREFIX);
- classLength = strlen(class);
- DebugStatement( assert(classLength < maxClassLength); )
- rewind(fp);
- line = readLine(&TagFile.line, fp);
- while (line != NULL && line[0] == class[0])
- {
- ++linesRead;
- if (strncmp(line, class, classLength) == 0)
- {
- char tab, classType[16];
- if (sscanf(line + classLength, "%15s%c", classType, &tab) == 2 &&
- tab == 't')
- {
- if (strcmp(classType, "_SORTED") == 0)
- updateSortedFlag(line, fp, startOfLine);
- }
- startOfLine = ftell(fp);
- }
- line = readLine(&TagFile.line, fp);
- }
- while (line != NULL) /* skip to end of file */
- {
- ++linesRead;
- line = readLine(&TagFile.line, fp);
- }
- return linesRead;
- }
- /* vi:set tabstop=8 shiftwidth=4: */