[geany/geany] 8e804b: entry: Add the remaining code from uctags

Jiří Techet git-noreply at xxxxx
Mon Dec 17 21:05:45 UTC 2018


Branch:      refs/heads/master
Author:      Jiří Techet <techet at gmail.com>
Committer:   Jiří Techet <techet at gmail.com>
Date:        Sun, 09 Oct 2016 17:58:24 UTC
Commit:      8e804b3145db03b674e634fab876979d04df424e
             https://github.com/geany/geany/commit/8e804b3145db03b674e634fab876979d04df424e

Log Message:
-----------
entry: Add the remaining code from uctags

Also enable compilation of forgotten kind.c


Modified Paths:
--------------
    ctags/Makefile.am
    ctags/main/entry.c
    ctags/main/entry.h
    ctags/main/parse.c

Modified: ctags/Makefile.am
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -77,6 +77,7 @@ libctags_la_SOURCES = \
 	main/htable.h \
 	main/keyword.c \
 	main/keyword.h \
+	main/kind.c \
 	main/kind.h \
 	main/lcpp.c \
 	main/lcpp.h \


Modified: ctags/main/entry.c
782 lines changed, 777 insertions(+), 5 deletions(-)
===================================================================
@@ -295,7 +295,70 @@ static long unsigned int updatePseudoTags (MIO *const mio)
  *  Tag file management
  */
 
+static bool isValidTagAddress (const char *const excmd)
+{
+	bool isValid = false;
+
+	if (strchr ("/?", excmd [0]) != NULL)
+		isValid = true;
+	else
+	{
+		char *address = xMalloc (strlen (excmd) + 1, char);
+		if (sscanf (excmd, "%[^;\n]", address) == 1  &&
+			strspn (address,"0123456789") == strlen (address))
+				isValid = true;
+		eFree (address);
+	}
+	return isValid;
+}
+
+static bool isCtagsLine (const char *const line)
+{
+	enum fieldList { TAG, TAB1, SRC_FILE, TAB2, EXCMD, NUM_FIELDS };
+	bool ok = false;  /* we assume not unless confirmed */
+	const size_t fieldLength = strlen (line) + 1;
+	char *const fields = xMalloc (NUM_FIELDS * fieldLength, char);
 
+	if (fields == NULL)
+		error (FATAL, "Cannot analyze tag file");
+	else
+	{
+#define field(x)		(fields + ((size_t) (x) * fieldLength))
+
+		const int numFields = sscanf (
+			line, "%[^\t]%[\t]%[^\t]%[\t]%[^\r\n]",
+			field (TAG), field (TAB1), field (SRC_FILE),
+			field (TAB2), field (EXCMD));
+
+		/*  There must be exactly five fields: two tab fields containing
+		 *  exactly one tab each, the tag must not begin with "#", and the
+		 *  file name should not end with ";", and the excmd must be
+		 *  acceptable.
+		 *
+		 *  These conditions will reject tag-looking lines like:
+		 *      int a;        <C-comment>
+		 *      #define LABEL <C-comment>
+		 */
+		if (numFields == NUM_FIELDS   &&
+			strlen (field (TAB1)) == 1  &&
+			strlen (field (TAB2)) == 1  &&
+			field (TAG) [0] != '#'      &&
+			field (SRC_FILE) [strlen (field (SRC_FILE)) - 1] != ';'  &&
+			isValidTagAddress (field (EXCMD)))
+				ok = true;
+
+		eFree (fields);
+	}
+	return ok;
+}
+
+static bool isEtagsLine (const char *const line)
+{
+	bool result = false;
+	if (line [0] == '\f')
+		result = (bool) (line [1] == '\n'  ||  line [1] == '\r');
+	return result;
+}
 
 static bool isTagFile (const char *const filename)
 {
@@ -310,6 +373,8 @@ static bool isTagFile (const char *const filename)
 
 		if (line == NULL)
 			ok = true;
+		else
+			ok = (bool) (isCtagsLine (line) || isEtagsLine (line));
 		mio_free (mio);
 	}
 	return ok;
@@ -436,10 +501,576 @@ static int replacementTruncate (const char *const name, const long size)
 
 #endif
 
+#ifndef EXTERNAL_SORT
+static void internalSortTagFile (void)
+{
+	MIO *mio;
+
+	/*  Open/Prepare the tag file and place its lines into allocated buffers.
+	 */
+	if (TagsToStdout)
+	{
+		mio = TagFile.mio;
+		mio_seek (mio, 0, SEEK_SET);
+	}
+	else
+	{
+		mio = mio_new_file (tagFileName (), "r");
+		if (mio == NULL)
+			failedSort (mio, NULL);
+	}
+
+	internalSortTags (TagsToStdout,
+			  mio,
+			  TagFile.numTags.added + TagFile.numTags.prev);
+
+	if (! TagsToStdout)
+		mio_free (mio);
+}
+#endif
+
+static void sortTagFile (void)
+{
+	if (TagFile.numTags.added > 0L)
+	{
+		if (Option.sorted != SO_UNSORTED)
+		{
+			verbose ("sorting tag file\n");
+#ifdef EXTERNAL_SORT
+			externalSortTags (TagsToStdout, TagFile.mio);
+#else
+			internalSortTagFile ();
+#endif
+		}
+		else if (TagsToStdout)
+			catFile (TagFile.mio);
+	}
+}
+
+static void resizeTagFile (const long newSize)
+{
+	int result;
+
+#ifdef USE_REPLACEMENT_TRUNCATE
+	result = replacementTruncate (TagFile.name, newSize);
+#else
+# ifdef HAVE_TRUNCATE
+	result = truncate (TagFile.name, (off_t) newSize);
+# else
+	const int fd = open (TagFile.name, O_RDWR);
+
+	if (fd == -1)
+		result = -1;
+	else
+	{
+#  ifdef HAVE_FTRUNCATE
+		result = ftruncate (fd, (off_t) newSize);
+#  else
+#   ifdef HAVE_CHSIZE
+		result = chsize (fd, newSize);
+#   endif
+#  endif
+		close (fd);
+	}
+# endif
+#endif
+	if (result == -1)
+		fprintf (stderr, "Cannot shorten tag file: errno = %d\n", errno);
+}
+
+static void writeEtagsIncludes (MIO *const mio)
+{
+	if (Option.etagsInclude)
+	{
+		unsigned int i;
+		for (i = 0  ;  i < stringListCount (Option.etagsInclude)  ;  ++i)
+		{
+			vString *item = stringListItem (Option.etagsInclude, i);
+			mio_printf (mio, "\f\n%s,include\n", vStringValue (item));
+		}
+	}
+}
+
+extern void closeTagFile (const bool resize)
+{
+	long desiredSize, size;
+
+	if (Option.etags)
+		writeEtagsIncludes (TagFile.mio);
+	mio_flush (TagFile.mio);
+	abort_if_ferror (TagFile.mio);
+	desiredSize = mio_tell (TagFile.mio);
+	mio_seek (TagFile.mio, 0L, SEEK_END);
+	size = mio_tell (TagFile.mio);
+	if (! TagsToStdout)
+		/* The tag file should be closed before resizing. */
+		if (mio_free (TagFile.mio) != 0)
+			error (FATAL | PERROR, "cannot close tag file");
+
+	if (resize  &&  desiredSize < size)
+	{
+		DebugStatement (
+			debugPrintf (DEBUG_STATUS, "shrinking %s from %ld to %ld bytes\n",
+				TagFile.name, size, desiredSize); )
+		resizeTagFile (desiredSize);
+	}
+	sortTagFile ();
+	if (TagsToStdout)
+	{
+		if (mio_free (TagFile.mio) != 0)
+			error (FATAL | PERROR, "cannot close tag file");
+		remove (tagFileName ());  /* remove temporary file */
+	}
+	eFree (TagFile.name);
+	TagFile.name = NULL;
+}
+
 /*
  *  Tag entry management
  */
 
+/*  This function copies the current line out to a specified file. It has no
+ *  effect on the fileGetc () function.  During copying, any '\' characters
+ *  are doubled and a leading '^' or trailing '$' is also quoted. End of line
+ *  characters (line feed or carriage return) are dropped.
+ */
+static size_t appendInputLine (int putc_func (char , void *), const char *const line, void * data, bool *omitted)
+{
+	size_t length = 0;
+	const char *p;
+
+	/*  Write everything up to, but not including, a line end character.
+	 */
+	*omitted = false;
+	for (p = line  ;  *p != '\0'  ;  ++p)
+	{
+		const int next = *(p + 1);
+		const int c = *p;
+
+		if (c == CRETURN  ||  c == NEWLINE)
+			break;
+
+		if (Option.patternLengthLimit != 0 && length >= Option.patternLengthLimit)
+		{
+			*omitted = true;
+			break;
+		}
+		/*  If character is '\', or a terminal '$', then quote it.
+		 */
+		if (c == BACKSLASH  ||  c == (Option.backward ? '?' : '/')  ||
+			(c == '$'  &&  (next == NEWLINE  ||  next == CRETURN)))
+		{
+			putc_func (BACKSLASH, data);
+			++length;
+		}
+		putc_func (c, data);
+		++length;
+	}
+
+	return length;
+}
+
+static int vstring_putc (char c, void *data)
+{
+	vString *str = data;
+	vStringPut (str, c);
+	return 1;
+}
+
+static int vstring_puts (const char* s, void *data)
+{
+	vString *str = data;
+	int len = vStringLength (str);
+	vStringCatS (str, s);
+	return vStringLength (str) - len;
+}
+
+static bool isPosSet(MIOPos pos)
+{
+	char * p = (char *)&pos;
+	bool r = false;
+	unsigned int i;
+
+	for (i = 0; i < sizeof(pos); i++)
+		r |= p[i];
+	return r;
+}
+
+extern char *readLineFromBypassAnyway (vString *const vLine, const tagEntryInfo *const tag,
+				   long *const pSeekValue)
+{
+	char * line;
+
+	if (isPosSet (tag->filePosition) || (tag->pattern == NULL))
+		line = 	readLineFromBypass (vLine, tag->filePosition, pSeekValue);
+	else
+		line = NULL;
+/*
+		line = readLineFromBypassSlow (vLine, tag->lineNumber, tag->pattern, pSeekValue);
+*/
+	return line;
+}
+
+/*  Truncates the text line containing the tag at the character following the
+ *  tag, providing a character which designates the end of the tag.
+ */
+extern void truncateTagLine (
+		char *const line, const char *const token, const bool 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 char* getFullQualifiedScopeNameFromCorkQueue (const tagEntryInfo * inner_scope)
+{
+
+	const kindOption *kind = NULL;
+	const tagEntryInfo *scope = inner_scope;
+	stringList *queue = stringListNew ();
+	vString *v;
+	vString *n;
+	unsigned int c;
+	const char *sep;
+
+	while (scope)
+	{
+		if (!scope->placeholder)
+		{
+			if (kind)
+			{
+				sep = scopeSeparatorFor (kind, scope->kind->letter);
+				v = vStringNewInit (sep);
+				stringListAdd (queue, v);
+			}
+			/* TODO: scope field of SCOPE can be used for optimization. */
+			v = vStringNewInit (scope->name);
+			stringListAdd (queue, v);
+			kind = scope->kind;
+		}
+		scope =  getEntryInCorkQueue (scope->extensionFields.scopeIndex);
+	}
+
+	n = vStringNew ();
+	while ((c = stringListCount (queue)) > 0)
+	{
+		v = stringListLast (queue);
+		vStringCat (n, v);
+		vStringDelete (v);
+		stringListRemoveLast (queue);
+	}
+	stringListDelete (queue);
+
+	return vStringDeleteUnwrap (n);
+}
+
+extern void getTagScopeInformation (tagEntryInfo *const tag,
+				    const char **kind, const char **name)
+{
+	if (kind)
+		*kind = NULL;
+	if (name)
+		*name = NULL;
+
+	if (tag->extensionFields.scopeKind == NULL
+	    && tag->extensionFields.scopeName == NULL
+	    && tag->extensionFields.scopeIndex != CORK_NIL
+	    && TagFile.corkQueue.count > 0)
+	{
+		const tagEntryInfo * scope = NULL;
+		char *full_qualified_scope_name = NULL;
+
+		scope = getEntryInCorkQueue (tag->extensionFields.scopeIndex);
+		full_qualified_scope_name = getFullQualifiedScopeNameFromCorkQueue(scope);
+		Assert (full_qualified_scope_name);
+
+		/* Make the information reusable to generate full qualified entry, and xformat output*/
+		tag->extensionFields.scopeKind = scope->kind;
+		tag->extensionFields.scopeName = full_qualified_scope_name;
+	}
+
+	if (tag->extensionFields.scopeKind != NULL  &&
+	    tag->extensionFields.scopeName != NULL)
+	{
+		if (kind)
+			*kind = tag->extensionFields.scopeKind->name;
+		if (name)
+			*name = tag->extensionFields.scopeName;
+	}
+}
+
+
+extern int   makePatternStringCommon (const tagEntryInfo *const tag,
+				      int putc_func (char , void *),
+				      int puts_func (const char* , void *),
+				      void *output)
+{
+	int length = 0;
+
+	char *line;
+	int searchChar;
+	const char *terminator;
+	bool  omitted;
+	size_t line_len;
+
+	bool making_cache = false;
+	int (* puts_o_func)(const char* , void *);
+	void * o_output;
+
+	static vString *cached_pattern;
+	static MIOPos   cached_location;
+	if (TagFile.patternCacheValid
+	    && (! tag->truncateLine)
+	    && (memcmp (&tag->filePosition, &cached_location, sizeof(MIOPos)) == 0))
+		return puts_func (vStringValue (cached_pattern), output);
+
+	line = readLineFromBypass (TagFile.vLine, tag->filePosition, NULL);
+	if (line == NULL)
+		error (FATAL, "could not read tag line from %s at line %lu", getInputFileName (),tag->lineNumber);
+	if (tag->truncateLine)
+		truncateTagLine (line, tag->name, false);
+
+	line_len = strlen (line);
+	searchChar = Option.backward ? '?' : '/';
+	terminator = (bool) (line [line_len - 1] == '\n') ? "$": "";
+
+	if (!tag->truncateLine)
+	{
+		making_cache = true;
+		cached_pattern = vStringNewOrClear (cached_pattern);
+
+		puts_o_func = puts_func;
+		o_output    = output;
+		putc_func   = vstring_putc;
+		puts_func   = vstring_puts;
+		output      = cached_pattern;
+	}
+
+	length += putc_func(searchChar, output);
+/*	if ((tag->boundaryInfo & BOUNDARY_START) == 0)
+		length += putc_func('^', output);*/
+	length += appendInputLine (putc_func, line, output, &omitted);
+	length += puts_func (omitted? "": terminator, output);
+	length += putc_func (searchChar, output);
+
+	if (making_cache)
+	{
+		puts_o_func (vStringValue (cached_pattern), o_output);
+		cached_location = tag->filePosition;
+		TagFile.patternCacheValid = true;
+	}
+
+	return length;
+}
+
+extern char* makePatternString (const tagEntryInfo *const tag)
+{
+	vString* pattern = vStringNew ();
+	makePatternStringCommon (tag, vstring_putc, vstring_puts, pattern);
+	return vStringDeleteUnwrap (pattern);
+}
+
+extern void attachParserField (tagEntryInfo *const tag, fieldType ftype, const char * value)
+{
+	Assert (tag->usedParserFields < PRE_ALLOCATED_PARSER_FIELDS);
+
+	tag->parserFields [tag->usedParserFields].ftype = ftype;
+	tag->parserFields [tag->usedParserFields].value = value;
+	tag->usedParserFields++;
+}
+
+extern void attachParserFieldToCorkEntry (int index,
+					 fieldType type,
+					 const char *value)
+{
+	tagEntryInfo * tag;
+	const char * v;
+
+	if (index == CORK_NIL)
+		return;
+
+	tag = getEntryInCorkQueue(index);
+	Assert (tag != NULL);
+
+	v = eStrdup (value);
+	attachParserField (tag, type, v);
+}
+
+static void copyParserFields (const tagEntryInfo *const tag, tagEntryInfo* slot)
+{
+	unsigned int i;
+	const char* value;
+
+	for (i = 0; i < tag->usedParserFields; i++)
+	{
+		value = tag->parserFields [i].value;
+		if (value)
+			value = eStrdup (value);
+
+		attachParserField (slot,
+				   tag->parserFields [i].ftype,
+				   value);
+	}
+}
+
+static void recordTagEntryInQueue (const tagEntryInfo *const tag, tagEntryInfo* slot)
+{
+	*slot = *tag;
+
+	if (slot->pattern)
+		slot->pattern = eStrdup (slot->pattern);
+	else if (!slot->lineNumberEntry)
+		slot->pattern = makePatternString (slot);
+
+	slot->inputFileName = eStrdup (slot->inputFileName);
+	slot->name = eStrdup (slot->name);
+	if (slot->extensionFields.access)
+		slot->extensionFields.access = eStrdup (slot->extensionFields.access);
+	if (slot->extensionFields.fileScope)
+		slot->extensionFields.fileScope = eStrdup (slot->extensionFields.fileScope);
+	if (slot->extensionFields.implementation)
+		slot->extensionFields.implementation = eStrdup (slot->extensionFields.implementation);
+	if (slot->extensionFields.inheritance)
+		slot->extensionFields.inheritance = eStrdup (slot->extensionFields.inheritance);
+	if (slot->extensionFields.scopeName)
+		slot->extensionFields.scopeName = eStrdup (slot->extensionFields.scopeName);
+	if (slot->extensionFields.signature)
+		slot->extensionFields.signature = eStrdup (slot->extensionFields.signature);
+	if (slot->extensionFields.varType)
+		slot->extensionFields.varType = eStrdup (slot->extensionFields.varType);
+#ifdef HAVE_LIBXML
+	if (slot->extensionFields.xpath)
+		slot->extensionFields.xpath = eStrdup (slot->extensionFields.xpath);
+#endif
+
+	if (slot->sourceLanguage)
+		slot->sourceLanguage = eStrdup (slot->sourceLanguage);
+	if (slot->sourceFileName)
+		slot->sourceFileName = eStrdup (slot->sourceFileName);
+
+	slot->usedParserFields = 0;
+	copyParserFields (tag, slot);
+}
+
+extern void clearParserFields (tagEntryInfo *const tag)
+{
+	unsigned int i;
+	const char* value;
+
+	for (i = 0; i < tag->usedParserFields; i++)
+	{
+		value = tag->parserFields[i].value;
+		if (value)
+			eFree ((char *)value);
+		tag->parserFields[i].value = NULL;
+		tag->parserFields[i].ftype = FIELD_UNKNOWN;
+	}
+}
+
+static void clearTagEntryInQueue (tagEntryInfo* slot)
+{
+	if (slot->pattern)
+		eFree ((char *)slot->pattern);
+	eFree ((char *)slot->inputFileName);
+	eFree ((char *)slot->name);
+
+	if (slot->extensionFields.access)
+		eFree ((char *)slot->extensionFields.access);
+	if (slot->extensionFields.fileScope)
+		eFree ((char *)slot->extensionFields.fileScope);
+	if (slot->extensionFields.implementation)
+		eFree ((char *)slot->extensionFields.implementation);
+	if (slot->extensionFields.inheritance)
+		eFree ((char *)slot->extensionFields.inheritance);
+	if (slot->extensionFields.scopeKind)
+		slot->extensionFields.scopeKind = NULL;
+	if (slot->extensionFields.scopeName)
+		eFree ((char *)slot->extensionFields.scopeName);
+	if (slot->extensionFields.signature)
+		eFree ((char *)slot->extensionFields.signature);
+	if (slot->extensionFields.varType)
+		eFree ((char *)slot->extensionFields.varType);
+#ifdef HAVE_LIBXML
+	if (slot->extensionFields.xpath)
+		eFree ((char *)slot->extensionFields.xpath);
+#endif
+
+	if (slot->sourceLanguage)
+		eFree ((char *)slot->sourceLanguage);
+	if (slot->sourceFileName)
+		eFree ((char *)slot->sourceFileName);
+
+	clearParserFields (slot);
+}
+
+static unsigned int queueTagEntry(const tagEntryInfo *const tag)
+{
+	unsigned int i;
+	void *tmp;
+	tagEntryInfo * slot;
+
+	if (! (TagFile.corkQueue.count < TagFile.corkQueue.length))
+	{
+		if (!TagFile.corkQueue.length)
+			TagFile.corkQueue.length = 1;
+
+		tmp = eRealloc (TagFile.corkQueue.queue,
+				sizeof (*TagFile.corkQueue.queue) * TagFile.corkQueue.length * 2);
+
+		TagFile.corkQueue.length *= 2;
+		TagFile.corkQueue.queue = tmp;
+	}
+
+	i = TagFile.corkQueue.count;
+	TagFile.corkQueue.count++;
+
+
+	slot = TagFile.corkQueue.queue + i;
+	recordTagEntryInQueue (tag, slot);
+
+	return i;
+}
+
+
+static void *writerData;
+static tagWriter *writer;
+
+extern void setTagWriter (tagWriter *t)
+{
+	writer = t;
+}
+
+extern bool outpuFormatUsedStdoutByDefault (void)
+{
+	return writer->useStdoutByDefault;
+}
+
+extern void setupWriter (void)
+{
+	if (writer->preWriteEntry)
+		writerData = writer->preWriteEntry (TagFile.mio);
+	else
+		writerData = NULL;
+}
+
+extern void teardownWriter (const char *filename)
+{
+	if (writer->postWriteEntry)
+		writer->postWriteEntry (TagFile.mio, filename, writerData);
+}
+
+static void buildFqTagCache (const tagEntryInfo *const tag)
+{
+	renderFieldEscaped (FIELD_SCOPE_KIND_LONG, tag, NO_PARSER_FIELD);
+	renderFieldEscaped (FIELD_SCOPE, tag, NO_PARSER_FIELD);
+}
+
 static void writeTagEntry (const tagEntryInfo *const tag)
 {
 	int length = 0;
@@ -471,6 +1102,89 @@ static void writeTagEntry (const tagEntryInfo *const tag)
 	/*abort_if_ferror (TagFile.mio);*/
 }
 
+extern bool writePseudoTag (const ptagDesc *desc,
+			       const char *const fileName,
+			       const char *const pattern,
+			       const char *const parserName)
+{
+	int length;
+
+	if (writer->writePtagEntry == NULL)
+		return false;
+
+	length = writer->writePtagEntry (TagFile.mio, desc, fileName,
+									 pattern, parserName, writerData);
+	abort_if_ferror (TagFile.mio);
+
+	++TagFile.numTags.added;
+	rememberMaxLengths (strlen (desc->name), (size_t) length);
+
+	return true;
+}
+
+extern void corkTagFile(void)
+{
+	TagFile.cork++;
+	if (TagFile.cork == 1)
+	{
+		  TagFile.corkQueue.length = 1;
+		  TagFile.corkQueue.count = 1;
+		  TagFile.corkQueue.queue = eMalloc (sizeof (*TagFile.corkQueue.queue));
+		  memset (TagFile.corkQueue.queue, 0, sizeof (*TagFile.corkQueue.queue));
+	}
+}
+
+extern void uncorkTagFile(void)
+{
+	unsigned int i;
+
+	TagFile.cork--;
+
+	if (TagFile.cork > 0)
+		return ;
+
+	for (i = 1; i < TagFile.corkQueue.count; i++)
+	{
+		tagEntryInfo *tag = TagFile.corkQueue.queue + i;
+		writeTagEntry (tag);
+/*		if (doesInputLanguageRequestAutomaticFQTag ()
+		    && isXtagEnabled (XTAG_QUALIFIED_TAGS)
+		    && tag->extensionFields.scopeKind
+		    && tag->extensionFields.scopeName
+		    && tag->extensionFields.scopeIndex)
+			makeQualifiedTagEntry (tag);*/
+	}
+	for (i = 1; i < TagFile.corkQueue.count; i++)
+		clearTagEntryInQueue (TagFile.corkQueue.queue + i);
+
+	memset (TagFile.corkQueue.queue, 0,
+		sizeof (*TagFile.corkQueue.queue) * TagFile.corkQueue.count);
+	TagFile.corkQueue.count = 0;
+	eFree (TagFile.corkQueue.queue);
+	TagFile.corkQueue.queue = NULL;
+	TagFile.corkQueue.length = 0;
+}
+
+extern tagEntryInfo *getEntryInCorkQueue   (unsigned int n)
+{
+	if ((CORK_NIL < n) && (n < TagFile.corkQueue.count))
+		return TagFile.corkQueue.queue + n;
+	else
+		return NULL;
+}
+
+extern tagEntryInfo *getEntryOfNestingLevel (const NestingLevel *nl)
+{
+	if (nl == NULL)
+		return NULL;
+/*	return getEntryInCorkQueue (nl->corkIndex); */
+}
+
+extern size_t        countEntryInCorkQueue (void)
+{
+	return TagFile.corkQueue.count;
+}
+
 extern int makeTagEntry (const tagEntryInfo *const tag)
 {
 	int r = CORK_NIL;
@@ -504,6 +1218,58 @@ extern int makeTagEntry (const tagEntryInfo *const tag)
 	return r;
 }
 
+extern int makeQualifiedTagEntry (const tagEntryInfo *const e)
+{
+	int r = CORK_NIL;
+	tagEntryInfo x;
+	char xk;
+	const char *sep;
+	static vString *fqn;
+
+	if (isXtagEnabled (XTAG_QUALIFIED_TAGS))
+	{
+		x = *e;
+		markTagExtraBit (&x, XTAG_QUALIFIED_TAGS);
+
+		fqn = vStringNewOrClear (fqn);
+
+		if (e->extensionFields.scopeName)
+		{
+			vStringCatS (fqn, e->extensionFields.scopeName);
+			xk = e->extensionFields.scopeKind->letter;
+			sep = scopeSeparatorFor (e->kind, xk);
+			vStringCatS (fqn, sep);
+		}
+		else
+		{
+			/* This is an top level item. prepend a root separator
+			   if the kind of the item has. */
+			sep = scopeSeparatorFor (e->kind, KIND_NULL);
+			if (sep == NULL)
+			{
+				/* No root separator. The name of the
+				   oritinal tag and that of full qualified tag
+				   are the same; recording the full qualified tag
+				   is meaningless. */
+				return r;
+			}
+			else
+				vStringCatS (fqn, sep);
+		}
+		vStringCatS (fqn, e->name);
+
+		x.name = vStringValue (fqn);
+		/* makeExtraTagEntry of c.c doesn't clear scope
+		   releated fields. */
+#if 0
+		x.extensionFields.scopeKind = NULL;
+		x.extensionFields.scopeName = NULL;
+#endif
+		r = makeTagEntry (&x);
+	}
+	return r;
+}
+
 extern void initTagEntry (tagEntryInfo *const e, const char *const name,
 			  const kindOption *kind)
 {
@@ -575,11 +1341,6 @@ extern void initTagEntryFull (tagEntryInfo *const e, const char *const name,
 		e->parserFields[i].ftype = FIELD_UNKNOWN;
 }
 
-extern void setTagWriter (tagWriter *t)
-{
-/*	writer = t; */
-}
-
 extern void    markTagExtraBit     (tagEntryInfo *const tag, xtagType extra)
 {
 	unsigned int index;
@@ -593,6 +1354,17 @@ extern void    markTagExtraBit     (tagEntryInfo *const tag, xtagType extra)
 	tag->extra [ index ] |= (1 << offset);
 }
 
+extern bool isTagExtraBitMarked (const tagEntryInfo *const tag, xtagType extra)
+{
+	unsigned int index = (extra / 8);
+	unsigned int offset = (extra % 8);
+
+	Assert (extra < XTAG_COUNT);
+	Assert (extra != XTAG_UNKNOWN);
+
+	return !! ((tag->extra [ index ]) & (1 << offset));
+}
+
 extern unsigned long numTagsAdded(void)
 {
 	return TagFile.numTags.added;


Modified: ctags/main/entry.h
33 lines changed, 31 insertions(+), 2 deletions(-)
===================================================================
@@ -30,8 +30,6 @@
 #define WHOLE_FILE  -1L
 #define includeExtensionFlags()         (Option.tagFileFormat > 1)
 
-#define CORK_NIL 0
-
 /*
 *   DATA DECLARATIONS
 */
@@ -113,6 +111,8 @@ extern void freeTagFileResources (void);
 extern const char *tagFileName (void);
 extern void openTagFile (void);
 extern void closeTagFile (const bool resize);
+extern void  setupWriter (void);
+extern void  teardownWriter (const char *inputFilename);
 extern int makeTagEntry (const tagEntryInfo *const tag);
 extern void initTagEntry (tagEntryInfo *const e, const char *const name,
 			  const kindOption *kind);
@@ -128,6 +128,7 @@ extern void initTagEntryFull (tagEntryInfo *const e, const char *const name,
 			      const char *sourceFileName,
 			      const char* sourceLanguage,
 			      long sourceLineNumberDifference);
+extern int makeQualifiedTagEntry (const tagEntryInfo *const e);
 
 extern unsigned long numTagsAdded(void);
 extern void setNumTagsAdded (unsigned long nadded);
@@ -140,6 +141,34 @@ extern void setTagFilePosition (MIOPos *p);
 extern const char* getTagFileDirectory (void);
 extern void getTagScopeInformation (tagEntryInfo *const tag,
 				    const char **kind, const char **name);
+
+/* Getting line associated with tag */
+extern char *readLineFromBypassAnyway (vString *const vLine, const tagEntryInfo *const tag,
+				   long *const pSeekValue);
+
+/* Generating pattern associated tag, caller must do eFree for the returned value. */
+extern char* makePatternString (const tagEntryInfo *const tag);
+
+
+/* language is optional: can be NULL. */
+extern bool writePseudoTag (const ptagDesc *pdesc,
+			       const char *const fileName,
+			       const char *const pattern,
+			       const char *const parserName);
+
+#define CORK_NIL 0
+void          corkTagFile(void);
+void          uncorkTagFile(void);
+tagEntryInfo *getEntryInCorkQueue   (unsigned int n);
+tagEntryInfo *getEntryOfNestingLevel (const NestingLevel *nl);
+size_t        countEntryInCorkQueue (void);
+
+extern void makeFileTag (const char *const fileName);
+
 extern void    markTagExtraBit     (tagEntryInfo *const tag, xtagType extra);
+extern bool isTagExtraBitMarked (const tagEntryInfo *const tag, xtagType extra);
+
+extern void attachParserField (tagEntryInfo *const tag, fieldType ftype, const char* value);
+extern void attachParserFieldToCorkEntry (int index, fieldType ftype, const char* value);
 
 #endif  /* CTAGS_MAIN_ENTRY_H */


Modified: ctags/main/parse.c
15 lines changed, 0 insertions(+), 15 deletions(-)
===================================================================
@@ -568,21 +568,6 @@ extern void printKindOptions (void)
 *   File parsing
 */
 
-static void makeFileTag (const char *const fileName)
-{
-	if (isXtagEnabled(XTAG_FILE_NAMES))
-	{
-		tagEntryInfo tag;
-		initTagEntry (&tag, baseFilename (fileName), getInputLanguageFileKind ());
-
-		tag.isFileEntry     = true;
-		tag.lineNumberEntry = true;
-		tag.lineNumber      = 1;
-
-		makeTagEntry (&tag);
-	}
-}
-
 static bool createTagsForFile (const char *const fileName,
 							   const langType language,
 							   const unsigned int passCount)



--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).


More information about the Commits mailing list