This is entry.c in view mode; [Download] [Up]
/***************************************************************************** * $Id: entry.c,v 1.11 1997/04/06 02:13:52 darren Exp $ * * Copyright (c) 1996-1997, Darren Hiebert * * Contains functions for creating tag entries. *****************************************************************************/ /*============================================================================ = Include files ============================================================================*/ #ifdef HAVE_CONFIG_H # include <config.h> #endif #include "ctags.h" /*============================================================================ = Data definitions ============================================================================*/ /* Note that the strings in this array must correspond to the types in the * tagType enumeration. */ static const char *TagTypeNames[] = { "tag", "def", "enum", "proto", "func", "type", "var" }; /*============================================================================ = 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 tagScope scope)); static int writeLineNumberEntry __ARGS((const tagInfo *const tag, const tagScope scope)); static int writePatternEntry __ARGS((const tagInfo *const tag, const tagScope scope, const tagType type)); static void writeTagEntry __ARGS((const tagInfo *const tag, const tagScope scope, const tagType type, const boolean useLineNumber)); static boolean includeTag __ARGS((const tagScope scope, const tagType type)); static void makeTagEntry __ARGS((const tagInfo *const tag, const tagScope scope, const tagType type, const boolean useLineNumber)); /*============================================================================ = Function definitions ============================================================================*/ /* 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; char 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; char 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; { char line[MaxTagLine]; size_t length; getFileLine(tag->location, line, MaxTagLine); length = fprintf(TagFile.fp, "%-20s %-6s %4ld %-14s ", tag->name, tagTypeName(type), tag->lineNumber, File.name); line[MaxTagLine - 2 - length] = '\0'; /* truncate line */ length += writeCompactSourceLine(TagFile.fp, line); putc(NEWLINE, TagFile.fp); ++length; ++TagFile.numTags; 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, scope ) const tagInfo *const tag; const tagScope scope; { char line[MaxTagLine]; int length; getFileLine(tag->location, line, MaxTagLine); truncateTagLine(line, tag->name, TRUE); if (Option.include.prefix && scope == SCOPE_STATIC) length = fprintf(TagFile.etags.fp, "%s\177%s:%s\001%ld,%ld\n", line, File.name, tag->name, tag->lineNumber, tag->location); else length = fprintf(TagFile.etags.fp, "%s\177%ld,%ld\n", line, tag->lineNumber, tag->location); TagFile.etags.byteCount += length; return length; } static int writeLineNumberEntry( tag, scope ) const tagInfo *const tag; const tagScope scope; { int length; if (Option.include.prefix && scope == SCOPE_STATIC) length = fprintf(TagFile.fp, "%s:%s\t%s\t%ld\n", File.name, tag->name, File.name, tag->lineNumber); else length = fprintf(TagFile.fp, "%s\t%s\t%ld\n", tag->name, File.name, tag->lineNumber); return length; } static int writePatternEntry( tag, scope, type ) const tagInfo *const tag; const tagScope scope; const tagType type; { const int searchChar = Option.backward ? '?' : '/'; char line[MaxTagLine]; boolean newlineTerminated; int length; getFileLine(tag->location, line, MaxTagLine); if (type == TAG_DEFINE) truncateTagLine(line, tag->name, FALSE); newlineTerminated = (line[strlen(line) - 1] == '\n'); if (Option.include.prefix && scope == SCOPE_STATIC) length = fprintf(TagFile.fp, "%s:%s\t%s\t", File.name, tag->name, File.name); else length = fprintf(TagFile.fp, "%s\t%s\t", tag->name, File.name); length += fprintf(TagFile.fp, "%c^", searchChar); length += writeSourceLine(TagFile.fp, line); length += fprintf(TagFile.fp, "%.*s%c\n", MaxTagLine - 3 - length, newlineTerminated ? "$":"", searchChar); return length; } static void writeTagEntry( tag, scope, type, useLineNumber ) const tagInfo *const tag; const tagScope scope; const tagType type; const boolean useLineNumber; { size_t length; if (Option.etags) length = writeEtagsEntry(tag, scope); else if (useLineNumber) length = writeLineNumberEntry(tag, scope); else length = writePatternEntry(tag, scope, type); ++TagFile.numTags; rememberMaxLengths(strlen(tag->name), length); } static boolean includeTag( scope, type ) const tagScope scope; const tagType type; { boolean include; if (scope == SCOPE_EXTERN || /* should never happen */ (scope == SCOPE_STATIC && ! Option.include.statics)) { include = FALSE; } else { switch (type) { case TAG_BLOCKTAG: include = Option.include.blockTags; break; case TAG_DEFINE: include = Option.include.defines; break; case TAG_ENUM: include = Option.include.enumValues; break; case TAG_FUNCTION: include = Option.include.functions; break; case TAG_FUNCDECL: include = Option.include.prototypes; break; case TAG_TYPEDEF: include = Option.include.typedefs; break; case TAG_VARIABLE: include = Option.include.variables; break; default: include = FALSE; break; } } return include; } /* This function generates a tag for the object in name, whose tag line is * located at a given seek offset. */ static void makeTagEntry( tag, scope, type, useLineNumber ) const tagInfo *const tag; const tagScope scope; const tagType type; const boolean useLineNumber; { if (includeTag(scope, type)) { if (Option.xref) writeXrefEntry(tag, type); else writeTagEntry(tag, scope, type, useLineNumber); #ifdef DEBUG debugEntry(scope, type, tag->name); #endif } } extern void makeTag( tag, scope, type ) const tagInfo *const tag; const tagScope scope; const tagType type; { makeTagEntry(tag, scope, type, (Option.locate == EX_LINENUM)); } extern void makeDefineTag( tag, scope ) const tagInfo *const tag; const tagScope scope; { makeTagEntry(tag, scope, TAG_DEFINE, (Option.locate != EX_PATTERN)); } extern const char *tagTypeName( type ) const tagType type; { const char *name; if (type < TAG_NUMTYPES) name = TagTypeNames[type]; else name = "?"; return name; } /* vi:set tabstop=8 shiftwidth=4: */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.