[geany/geany] a1cf47: Sync ctags with upstream so that most parsers can be copied from uctags (#2018)

Jiří Techet git-noreply at xxxxx
Sat Apr 6 02:14:30 UTC 2019


Branch:      refs/heads/master
Author:      Jiří Techet <techet at gmail.com>
Committer:   elextr <elextr at gmail.com>
Date:        Sat, 06 Apr 2019 02:14:30 UTC
Commit:      a1cf475fcf2c81420bfa90307585ec645cfb4dc1
             https://github.com/geany/geany/commit/a1cf475fcf2c81420bfa90307585ec645cfb4dc1

Log Message:
-----------
Sync ctags with upstream so that most parsers can be copied from uctags (#2018)

* Use latest version of htable

* Use latest version of mio

* Use latest version of objpool

* Use latest version of ptrarray

* Use latest version of vstring

This also requires adding trashbox.c/h which is now used by vstring and
inline macros from inline.h.

* Rename fieldSpec to fieldDefinition

See b56bd065123d69087acd6f202499d71a86a7ea7a upstream.

* Rename kindOption to kindDefinition

See e112e8ab6e0933b5bd7922e0dfb969b1f28c60fa upstream

* Rename kinds field in parserDefinition to kindTable

See 09ae690face8b5cde940e2d7cf40f8860381067b upstream.

* Rename structure fields about field in parserDefinition

See a739fa5fb790bc349a66b2bee0bf42cf289994e8 upstream.

* Use kindIndex instead of kindDefinition

This patch replaces kindDefinition related entries from sTagEntryInfo
with kindIndex so kinds are referenced indirectly using the index. For
more info please refer to commits:

16a2541c0698bd8ee03c1be8172ef3191f6e695a
f92e6bf2aeb21fd6b04756487f98d0eefa16d9ce

Some other changes had to be made to make the sources compile (without
bringing all the diffs from upstream). At some places, which aren't used
by Geany, only stub implementations have been created.

In particular, the regex parser has been disabled (for now?) because its
current implementation doesn't allow accessing kindDefinitions using
index and allowing this would require big changes in its implementation.
The affected parsers are Cobol, ActionScript and HTML. For HTML we can
use the token-based parser from upstream, and we should consider
whether Cobol and ActionScript are worth the effort to maintain a separate
regex implementation using GRegex (IMO these languages are dead enough
not to justify the extra effort).

The patch also disables tests for languages using regex parsers.

* Rename roleDesc to roleDefinition

See 1345725842c196cc0523ff60231192bcd588961b upstream. Since we don't care
about roles in Geany, we don't have to do the additional stuff the upstream
patch does.

* Add XTAG_ANONYMOUS used by jscript

See 0e4c5d4a0461bc8d9616fe3b97d75b91d014246e upstream.

* Include stdint.h in entry.h

* Don't use hash value as an Anonymous field identifier

Instead of something like "Anonymous0ab283cd9402" use sequential integer
values like "Anonymous1".

* Call anonReset in main part

See 3c91b1ea509df238feb86c9cbd552b621e462653 upstream.

* Use upstream javascript parser

* Use upstream css parser

* Create correctly sized MIO for 0 size

See https://github.com/universal-ctags/ctags/pull/1951

* Always enable promise API and subparsers for Geany

* Support subparsers in Geany and add HTML parser demonstrating this feature

This feature requires several changes:

1. Propagating language of the tag from ctags to Geany so we know whether
the tag comes from a master parser or a subparser.

2. We need to address the problem that tag types from a subparsers can
clash with tag types from master parsers or other subparsers used by the
master parser. For instance, HTML and both its css and javascript
subparsers use tm_tag_class_t but HTML uses it for <h2> headings, and
css and javascript for classes. Representing all of them using
tm_tag_class_t would lead to complete mess where all of these types would
for instance be listed in the same branch of the tree in the sidebar.

To avoid this problem, this patch adds another mapping for subparsers where
each tag type can be mapped to another tag type (which isn't used neither
by master parser or other subparsers). To avoid unwanted clashes with other
parsers, only tags explicitly mentioned in such mappings are added to tag
manager; other subparser tags are discarded.

For HTML this patch introduces mapping only for tm_tag_function_t (which
in this case maps to the same type) to mimick the previous HTML parser
behavior but other javascript and css tag types can be added this way
in the future too.

3. Since in most of the code Geany and tag manager assume that tags from
one file use the same language, subparser's tags are modified to have the
same language like the master parser.

4. HTML parser itself was copied from upstream without any modifications.
Tests were fixed as the parser now correctly ignores comments.

* Rename truncateLine field of tagEntryInfo

See 0e70b22791877322598f03ecbe3eb26a6b661001 upstream. Needed for Fortran
parser.

* Add dummy mbcs.h and trace.h

Included by javascript parser.

* Introduce an accessor to `locate' field of `Option'

See fb5ef68859f71ff2949f1d9a7cab7515f523532f upstream. Needed for Fortran.

* Add numarray.c/h

Needed by various parsers.

* Add getLanguageForFilename() and getLanguageForCommand()

See

416c5e6b8807feaec318d7f8addbb4107370c187
334e072f9d6d9954ebd3eb89bbceb252c20ae9dd

upstream. Needed for Sh parser.

* txt2tags: Fix scope separator definition and re-enable tests

* Rename rest.c to rst.c to match upstream filename

* Use upstream asciidoc and rst parsers

* Add asciidoc and rst unit tests

* Rename conf.c to iniconf.c to match upstream filename

* Add tests of conf, diff, md parsers from universal ctags

* Add more ctags unit tests

This patch adds unit tests for: nsis, docbook, haskell, haxe, abaqus, vala,
abc.

The only missing unit tests are for GLSL and Ferite parsers which
however share the implementation with the C parser and should be
reasonably well covered by other C-like language tests.

The tests were put together from various tutorials and help of the
languages in order to cover the tags these parsers generate. No guarantee
they'd compile with real parsers.

* Rename latex.c to tex.c to match upstream filename

* Rename entry points of parsers to match upstream names

* Initialize trashbox

* Add newline to the end of file


Modified Paths:
--------------
    ctags/Makefile.am
    ctags/main/ctags-api.c
    ctags/main/ctags-api.h
    ctags/main/dependency.c
    ctags/main/entry.c
    ctags/main/entry.h
    ctags/main/field.c
    ctags/main/field.h
    ctags/main/htable.c
    ctags/main/htable.h
    ctags/main/inline.h
    ctags/main/kind.c
    ctags/main/kind.h
    ctags/main/lcpp.c
    ctags/main/lcpp.h
    ctags/main/lregex.c
    ctags/main/lxcmd.c
    ctags/main/lxpath.c
    ctags/main/mbcs.h
    ctags/main/mio.c
    ctags/main/mio.h
    ctags/main/numarray.c
    ctags/main/numarray.h
    ctags/main/objpool.c
    ctags/main/objpool.h
    ctags/main/options.c
    ctags/main/options.h
    ctags/main/parse.c
    ctags/main/parse.h
    ctags/main/parsers.h
    ctags/main/promise.c
    ctags/main/ptrarray.c
    ctags/main/ptrarray.h
    ctags/main/read.c
    ctags/main/read.h
    ctags/main/trace.h
    ctags/main/trashbox.c
    ctags/main/trashbox.h
    ctags/main/types.h
    ctags/main/vstring.c
    ctags/main/vstring.h
    ctags/main/xtag.c
    ctags/main/xtag.h
    ctags/parsers/abaqus.c
    ctags/parsers/abc.c
    ctags/parsers/asciidoc.c
    ctags/parsers/asm.c
    ctags/parsers/basic.c
    ctags/parsers/c.c
    ctags/parsers/css.c
    ctags/parsers/diff.c
    ctags/parsers/docbook.c
    ctags/parsers/erlang.c
    ctags/parsers/fortran.c
    ctags/parsers/go.c
    ctags/parsers/haskell.c
    ctags/parsers/haxe.c
    ctags/parsers/html.c
    ctags/parsers/iniconf.c
    ctags/parsers/jscript.c
    ctags/parsers/json.c
    ctags/parsers/lua.c
    ctags/parsers/make.c
    ctags/parsers/markdown.c
    ctags/parsers/matlab.c
    ctags/parsers/nsis.c
    ctags/parsers/objc.c
    ctags/parsers/pascal.c
    ctags/parsers/perl.c
    ctags/parsers/php.c
    ctags/parsers/powershell.c
    ctags/parsers/python.c
    ctags/parsers/r.c
    ctags/parsers/rest.c
    ctags/parsers/rst.c
    ctags/parsers/ruby.c
    ctags/parsers/rust.c
    ctags/parsers/sh.c
    ctags/parsers/sql.c
    ctags/parsers/tcl.c
    ctags/parsers/tex.c
    ctags/parsers/txt2tags.c
    ctags/parsers/verilog.c
    ctags/parsers/vhdl.c
    src/tagmanager/tm_parser.c
    src/tagmanager/tm_parser.h
    src/tagmanager/tm_source_file.c
    tests/ctags/Makefile.am
    tests/ctags/complex-return.js.tags
    tests/ctags/geany.nsi
    tests/ctags/geany.nsi.tags
    tests/ctags/js-class-related-unterminated.js.tags
    tests/ctags/js-let.js.tags
    tests/ctags/js-string-continuation.js.tags
    tests/ctags/jsFunc_tutorial.js.tags
    tests/ctags/simple.abc
    tests/ctags/simple.abc.tags
    tests/ctags/simple.asciidoc
    tests/ctags/simple.asciidoc.tags
    tests/ctags/simple.conf
    tests/ctags/simple.conf.tags
    tests/ctags/simple.diff
    tests/ctags/simple.diff.tags
    tests/ctags/simple.docbook
    tests/ctags/simple.docbook.tags
    tests/ctags/simple.hs
    tests/ctags/simple.hs.tags
    tests/ctags/simple.html.tags
    tests/ctags/simple.hx
    tests/ctags/simple.hx.tags
    tests/ctags/simple.inp
    tests/ctags/simple.inp.tags
    tests/ctags/simple.js.tags
    tests/ctags/simple.md
    tests/ctags/simple.md.tags
    tests/ctags/simple.rst
    tests/ctags/simple.rst.tags
    tests/ctags/simple.vala
    tests/ctags/simple.vala.tags

Modified: ctags/Makefile.am
13 lines changed, 10 insertions(+), 3 deletions(-)
===================================================================
@@ -17,7 +17,7 @@ parsers = \
 	parsers/basic.c \
 	parsers/c.c \
 	parsers/cobol.c \
-	parsers/conf.c \
+	parsers/iniconf.c \
 	parsers/css.c \
 	parsers/diff.c \
 	parsers/docbook.c \
@@ -29,7 +29,6 @@ parsers = \
 	parsers/html.c \
 	parsers/jscript.c \
 	parsers/json.c \
-	parsers/latex.c \
 	parsers/lua.c \
 	parsers/make.c \
 	parsers/markdown.c \
@@ -42,12 +41,13 @@ parsers = \
 	parsers/powershell.c \
 	parsers/python.c \
 	parsers/r.c \
-	parsers/rest.c \
+	parsers/rst.c \
 	parsers/ruby.c \
 	parsers/rust.c \
 	parsers/sh.c \
 	parsers/sql.c \
 	parsers/tcl.c \
+	parsers/tex.c \
 	parsers/txt2tags.c \
 	parsers/verilog.c \
 	parsers/vhdl.c
@@ -77,6 +77,7 @@ libctags_la_SOURCES = \
 	main/general.h \
 	main/htable.c \
 	main/htable.h \
+	main/inline.h \
 	main/keyword.c \
 	main/keyword.h \
 	main/kind.c \
@@ -88,10 +89,13 @@ libctags_la_SOURCES = \
 	main/lxpath.c \
 	main/main.c \
 	main/main.h \
+	main/mbcs.h \
 	main/mio.c \
 	main/mio.h \
 	main/nestlevel.c \
 	main/nestlevel.h \
+	main/numarray.c \
+	main/numarray.h \
 	main/objpool.c \
 	main/objpool.h \
 	main/options.c \
@@ -121,6 +125,9 @@ libctags_la_SOURCES = \
 	main/sort.h \
 	main/strlist.c \
 	main/strlist.h \
+	main/trace.h \
+	main/trashbox.c \
+	main/trashbox.h \
 	main/types.h \
 	main/vstring.c \
 	main/vstring.h \


Modified: ctags/main/ctags-api.c
13 lines changed, 8 insertions(+), 5 deletions(-)
===================================================================
@@ -18,6 +18,7 @@
 #include "output.h"
 #include "parse.h"
 #include "options.h"
+#include "trashbox.h"
 
 #include <stdio.h>
 #include <string.h>
@@ -51,6 +52,8 @@ extern void ctagsInit(void)
 	initializeParsing ();
 	initOptions ();
 
+	initDefaultTrashBox ();
+
 	/* make sure all parsers are initialized */
 	initializeParser (LANG_AUTO);
 }
@@ -92,7 +95,7 @@ extern const char *ctagsGetLangKinds(int lang)
 	static char kinds[257];
 
 	for (i = 0; i < def->kindCount; i++)
-		kinds[i] = def->kinds[i].letter;
+		kinds[i] = def->kindTable[i].letter;
 	kinds[i] = '\0';
 
 	return kinds;
@@ -106,8 +109,8 @@ extern const char *ctagsGetKindName(char kind, int lang)
 
 	for (i = 0; i < def->kindCount; i++)
 	{
-		if (def->kinds[i].letter == kind)
-			return def->kinds[i].name;
+		if (def->kindTable[i].letter == kind)
+			return def->kindTable[i].name;
 	}
 	return "unknown";
 }
@@ -120,8 +123,8 @@ extern char ctagsGetKindFromName(const char *name, int lang)
 
 	for (i = 0; i < def->kindCount; i++)
 	{
-		if (strcmp(def->kinds[i].name, name) == 0)
-			return def->kinds[i].letter;
+		if (strcmp(def->kindTable[i].name, name) == 0)
+			return def->kindTable[i].letter;
 	}
 	return '-';
 }


Modified: ctags/main/ctags-api.h
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -27,6 +27,7 @@ typedef struct {
 	char kindLetter;
 	bool isFileScope;
 	unsigned long lineNumber;
+	int lang;
 } ctagsTag;
 
 /* Callback invoked for every tag found by the parser. The return value is


Modified: ctags/main/dependency.c
12 lines changed, 6 insertions(+), 6 deletions(-)
===================================================================
@@ -18,9 +18,9 @@
 #include <string.h>
 
 
-static void linkKinds (kindOption *masterKind, kindOption *slaveKind)
+static void linkKinds (kindDefinition *masterKind, kindDefinition *slaveKind)
 {
-	kindOption *tail;
+	kindDefinition *tail;
 
 	slaveKind->master = masterKind;
 
@@ -39,16 +39,16 @@ static void linkKindDependency (parserDefinition *const masterParser,
 				parserDefinition *const slaveParser)
 {
 	unsigned int k_slave, k_master;
-	kindOption *kind_slave, *kind_master;
+	kindDefinition *kind_slave, *kind_master;
 
 	for (k_slave = 0; k_slave < slaveParser->kindCount; k_slave++)
 	{
-		if (slaveParser->kinds [k_slave].syncWith == LANG_AUTO)
+		if (slaveParser->kindTable [k_slave].syncWith == LANG_AUTO)
 		{
-			kind_slave = slaveParser->kinds + k_slave;
+			kind_slave = slaveParser->kindTable + k_slave;
 			for (k_master = 0; k_master < masterParser->kindCount; k_master++)
 			{
-				kind_master = masterParser->kinds + k_master;
+				kind_master = masterParser->kindTable + k_master;
 				if ((kind_slave->letter == kind_master->letter)
 				    && (strcmp (kind_slave->name, kind_master->name) == 0))
 				{


Modified: ctags/main/entry.c
86 lines changed, 48 insertions(+), 38 deletions(-)
===================================================================
@@ -188,15 +188,15 @@ extern void makeFileTag (const char *const fileName)
 	if (xtag != XTAG_UNKNOWN)
 	{
 		tagEntryInfo tag;
-		kindOption  *kind;
+		kindDefinition  *kind;
 
 		kind = getInputLanguageFileKind();
 		Assert (kind);
 		kind->enabled = isXtagEnabled(XTAG_FILE_NAMES);
 
 		/* TODO: you can return here if enabled == false. */
 
-		initTagEntry (&tag, baseFilename (fileName), kind);
+		initTagEntry (&tag, baseFilename (fileName), KIND_FILE_INDEX);
 
 		tag.isFileEntry     = true;
 		tag.lineNumberEntry = true;
@@ -736,7 +736,8 @@ extern void truncateTagLine (
 static char* getFullQualifiedScopeNameFromCorkQueue (const tagEntryInfo * inner_scope)
 {
 
-	const kindOption *kind = NULL;
+	int kindIndex = KIND_GHOST_INDEX;
+	langType lang;
 	const tagEntryInfo *scope = inner_scope;
 	stringList *queue = stringListNew ();
 	vString *v;
@@ -748,16 +749,17 @@ static char* getFullQualifiedScopeNameFromCorkQueue (const tagEntryInfo * inner_
 	{
 		if (!scope->placeholder)
 		{
-			if (kind)
+			if (kindIndex != KIND_GHOST_INDEX)
 			{
-				sep = scopeSeparatorFor (kind, scope->kind->letter);
+				sep = scopeSeparatorFor (lang, kindIndex, scope->kindIndex);
 				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;
+			kindIndex = scope->kindIndex;
+			lang = scope->langType;
 		}
 		scope =  getEntryInCorkQueue (scope->extensionFields.scopeIndex);
 	}
@@ -783,7 +785,7 @@ extern void getTagScopeInformation (tagEntryInfo *const tag,
 	if (name)
 		*name = NULL;
 
-	if (tag->extensionFields.scopeKind == NULL
+	if (tag->extensionFields.scopeKindIndex == KIND_GHOST_INDEX
 	    && tag->extensionFields.scopeName == NULL
 	    && tag->extensionFields.scopeIndex != CORK_NIL
 	    && TagFile.corkQueue.count > 0)
@@ -796,15 +798,23 @@ extern void getTagScopeInformation (tagEntryInfo *const tag,
 		Assert (full_qualified_scope_name);
 
 		/* Make the information reusable to generate full qualified entry, and xformat output*/
-		tag->extensionFields.scopeKind = scope->kind;
+		tag->extensionFields.scopeLangType = scope->langType;
+		tag->extensionFields.scopeKindIndex = scope->kindIndex;
 		tag->extensionFields.scopeName = full_qualified_scope_name;
 	}
 
-	if (tag->extensionFields.scopeKind != NULL  &&
+	if (tag->extensionFields.scopeKindIndex != KIND_GHOST_INDEX  &&
 	    tag->extensionFields.scopeName != NULL)
 	{
 		if (kind)
-			*kind = tag->extensionFields.scopeKind->name;
+		{
+			langType lang = (tag->extensionFields.scopeLangType == LANG_AUTO)
+				? tag->langType
+				: tag->extensionFields.scopeLangType;
+			kindDefinition *kdef = getLanguageKind (lang,
+													tag->extensionFields.scopeKindIndex);
+			*kind = kdef->name;
+		}
 		if (name)
 			*name = tag->extensionFields.scopeName;
 	}
@@ -831,21 +841,21 @@ extern int   makePatternStringCommon (const tagEntryInfo *const tag,
 	static vString *cached_pattern;
 	static MIOPos   cached_location;
 	if (TagFile.patternCacheValid
-	    && (! tag->truncateLine)
+	    && (! tag->truncateLineAfterTag)
 	    && (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)
+	if (tag->truncateLineAfterTag)
 		truncateTagLine (line, tag->name, false);
 
 	line_len = strlen (line);
 	searchChar = Option.backward ? '?' : '/';
 	terminator = (bool) (line [line_len - 1] == '\n') ? "$": "";
 
-	if (!tag->truncateLine)
+	if (!tag->truncateLineAfterTag)
 	{
 		making_cache = true;
 		cached_pattern = vStringNewOrClear (cached_pattern);
@@ -960,8 +970,6 @@ static void recordTagEntryInQueue (const tagEntryInfo *const tag, tagEntryInfo*
 		slot->extensionFields.xpath = eStrdup (slot->extensionFields.xpath);
 #endif
 
-	if (slot->sourceLanguage)
-		slot->sourceLanguage = eStrdup (slot->sourceLanguage);
 	if (slot->sourceFileName)
 		slot->sourceFileName = eStrdup (slot->sourceFileName);
 
@@ -999,8 +1007,6 @@ static void clearTagEntryInQueue (tagEntryInfo* slot)
 		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)
@@ -1018,8 +1024,6 @@ static void clearTagEntryInQueue (tagEntryInfo* slot)
 		eFree ((char *)slot->extensionFields.xpath);
 #endif
 
-	if (slot->sourceLanguage)
-		eFree ((char *)slot->sourceLanguage);
 	if (slot->sourceFileName)
 		eFree ((char *)slot->sourceFileName);
 
@@ -1098,9 +1102,10 @@ static void initCtagsTag(ctagsTag *tag, const tagEntryInfo *info)
 	tag->varType = info->extensionFields.varType;
 	tag->access = info->extensionFields.access;
 	tag->implementation = info->extensionFields.implementation;
-	tag->kindLetter = info->kind->letter;
+	tag->kindLetter = getLanguageKind(info->langType, info->kindIndex)->letter;
 	tag->isFileScope = info->isFileScope;
 	tag->lineNumber = info->lineNumber;
+	tag->lang = info->langType;
 }
 #endif
 
@@ -1194,7 +1199,7 @@ extern void uncorkTagFile(void)
 		writeTagEntry (tag);
 		if (doesInputLanguageRequestAutomaticFQTag ()
 		    && isXtagEnabled (XTAG_QUALIFIED_TAGS)
-		    && tag->extensionFields.scopeKind
+		    && (tag->extensionFields.scopeKindIndex != KIND_GHOST_INDEX)
 		    && tag->extensionFields.scopeName
 		    && tag->extensionFields.scopeIndex)
 			makeQualifiedTagEntry (tag);
@@ -1281,15 +1286,15 @@ extern int makeQualifiedTagEntry (const tagEntryInfo *const e)
 		if (e->extensionFields.scopeName)
 		{
 			vStringCatS (fqn, e->extensionFields.scopeName);
-			xk = e->extensionFields.scopeKind->letter;
-			sep = scopeSeparatorFor (e->kind, xk);
+			xk = e->extensionFields.scopeKindIndex;
+			sep = scopeSeparatorFor (e->langType, e->kindIndex, 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);
+			sep = scopeSeparatorFor (e->langType, e->kindIndex, KIND_GHOST_INDEX);
 			if (sep == NULL)
 			{
 				/* No root separator. The name of the
@@ -1316,67 +1321,72 @@ extern int makeQualifiedTagEntry (const tagEntryInfo *const e)
 }
 
 extern void initTagEntry (tagEntryInfo *const e, const char *const name,
-			  const kindOption *kind)
+			  int kindIndex)
 {
 	initTagEntryFull(e, name,
 			 getInputLineNumber (),
-			 getInputLanguageName (),
+			 getInputLanguage (),
 			 getInputFilePosition (),
 			 getInputFileTagPath (),
-			 kind,
+			 kindIndex,
 			 ROLE_INDEX_DEFINITION,
 			 getSourceFileTagPath(),
-			 getSourceLanguageName(),
+			 getSourceLanguage(),
 			 getSourceLineNumber() - getInputLineNumber ());
 }
 
 extern void initRefTagEntry (tagEntryInfo *const e, const char *const name,
-			     const kindOption *kind, int roleIndex)
+			     int kindIndex, int roleIndex)
 {
 	initTagEntryFull(e, name,
 			 getInputLineNumber (),
-			 getInputLanguageName (),
+			 getInputLanguage (),
 			 getInputFilePosition (),
 			 getInputFileTagPath (),
-			 kind,
+			 kindIndex,
 			 roleIndex,
 			 getSourceFileTagPath(),
-			 getSourceLanguageName(),
+			 getSourceLanguage(),
 			 getSourceLineNumber() - getInputLineNumber ());
 }
 
 extern void initTagEntryFull (tagEntryInfo *const e, const char *const name,
 			      unsigned long lineNumber,
-			      const char* language,
+			      langType langType_,
 			      MIOPos      filePosition,
 			      const char *inputFileName,
-			      const kindOption *kind,
+			      int kindIndex,
 			      int roleIndex,
 			      const char *sourceFileName,
-			      const char* sourceLanguage,
+			      langType sourceLangType,
 			      long sourceLineNumberDifference)
 {
 	int i;
+
 	Assert (getInputFileName() != NULL);
 
 	memset (e, 0, sizeof (tagEntryInfo));
 	e->lineNumberEntry = (bool) (Option.locate == EX_LINENUM);
 	e->lineNumber      = lineNumber;
 	e->boundaryInfo    = getNestedInputBoundaryInfo (lineNumber);
-	e->language        = language;
+	e->langType        = langType_;
 	e->filePosition    = filePosition;
 	e->inputFileName   = inputFileName;
 	e->name            = name;
+	e->extensionFields.scopeLangType = LANG_AUTO;
+	e->extensionFields.scopeKindIndex = KIND_GHOST_INDEX;
 	e->extensionFields.scopeIndex     = CORK_NIL;
-	e->kind = kind;
+
+	Assert (kindIndex < 0 || kindIndex < (int)countLanguageKinds(langType_));
+	e->kindIndex = kindIndex;
 
 	Assert (roleIndex >= ROLE_INDEX_DEFINITION);
 	Assert (kind == NULL || roleIndex < kind->nRoles);
 	e->extensionFields.roleIndex = roleIndex;
 	if (roleIndex > ROLE_INDEX_DEFINITION)
 		markTagExtraBit (e, XTAG_REFERENCE_TAGS);
 
-	e->sourceLanguage = sourceLanguage;
+	e->sourceLangType = sourceLangType;
 	e->sourceFileName = sourceFileName;
 	e->sourceLineNumberDifference = sourceLineNumberDifference;
 


Modified: ctags/main/entry.h
25 lines changed, 15 insertions(+), 10 deletions(-)
===================================================================
@@ -15,6 +15,7 @@
 #include "general.h"  /* must always come first */
 #include "types.h"
 
+#include <stdint.h>
 #include <stdio.h>
 
 #include "field.h"
@@ -45,7 +46,7 @@ struct sTagEntryInfo {
 	unsigned int lineNumberEntry:1;  /* pattern or line number entry */
 	unsigned int isFileScope    :1;  /* is tag visible only within input file? */
 	unsigned int isFileEntry    :1;  /* is this just an entry for a file name? */
-	unsigned int truncateLine   :1;  /* truncate tag line at end of tag name? */
+	unsigned int truncateLineAfterTag :1;  /* truncate tag line at end of tag name? */
 	unsigned int placeholder    :1;	 /* This is just a part of scope context.
 					    Put this entry to cork queue but
 					    don't print it to tags file. */
@@ -55,10 +56,10 @@ struct sTagEntryInfo {
 				       * (may be NULL if not present) *//*  */
 	unsigned int boundaryInfo;    /* info about nested input stream */
 	MIOPos      filePosition;     /* file position of line containing tag */
-	const char* language;         /* language of input file */
+	langType langType;         /* language of input file */
 	const char *inputFileName;   /* name of input file */
 	const char *name;             /* name of the tag */
-	const kindOption *kind;	      /* kind descriptor */
+	int kindIndex;	      /* kind descriptor */
 	unsigned char extra[ ((XTAG_COUNT) / 8) + 1 ];
 
 	struct {
@@ -67,7 +68,11 @@ struct sTagEntryInfo {
 		const char* implementation;
 		const char* inheritance;
 
-		const kindOption* scopeKind;
+		/* Which scopeKindIndex belong to. If the value is LANG_AUTO,
+		   the value for langType field of this structure is used as default value.
+		   LANG_AUTO is set automatically in initTagEntryInfo. */
+		langType    scopeLangType;
+		int         scopeKindIndex;
 		const char* scopeName;
 		int         scopeIndex;   /* cork queue entry for upper scope tag.
 					     This field is meaningful if the value
@@ -99,7 +104,7 @@ struct sTagEntryInfo {
 
 	/* Following source* fields are used only when #line is found
 	   in input and --line-directive is given in ctags command line. */
-	const char* sourceLanguage;
+	langType sourceLangType;
 	const char *sourceFileName;
 	unsigned long sourceLineNumberDifference;
 };
@@ -121,18 +126,18 @@ 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);
+			  int kindIndex);
 extern void initRefTagEntry (tagEntryInfo *const e, const char *const name,
-			     const kindOption *kind, int roleIndex);
+			     int kindIndex, int roleIndex);
 extern void initTagEntryFull (tagEntryInfo *const e, const char *const name,
 			      unsigned long lineNumber,
-			      const char* language,
+			      langType langType_,
 			      MIOPos      filePosition,
 			      const char *inputFileName,
-			      const kindOption *kind,
+			      int kindIndex,
 			      int roleIndex,
 			      const char *sourceFileName,
-			      const char* sourceLanguage,
+			      langType sourceLangType,
 			      long sourceLineNumberDifference);
 extern int makeQualifiedTagEntry (const tagEntryInfo *const e);
 


Modified: ctags/main/field.c
63 lines changed, 30 insertions(+), 33 deletions(-)
===================================================================
@@ -27,7 +27,7 @@
 
 
 struct sFieldDesc {
-	fieldSpec *spec;
+	fieldDefinition *spec;
 	unsigned int fixed:   1;   /* fields which cannot be disabled. */
 	vString     *buffer;
 	const char* nameWithPrefix;
@@ -84,7 +84,7 @@ static bool     isEndFieldAvailable       (const tagEntryInfo *const tag);
 
 #define WITH_DEFUALT_VALUE(str) ((str)?(str):"-")
 
-static fieldSpec fieldSpecsFixed [] = {
+static fieldDefinition fieldDefinitionsFixed [] = {
         /* FIXED FIELDS */
 	DEFINE_FIELD_SPEC ('N', "name",     true,
 			  "tag name (fixed field)",
@@ -97,7 +97,7 @@ static fieldSpec fieldSpecsFixed [] = {
 			   renderFieldPattern),
 };
 
-static fieldSpec fieldSpecsExuberant [] = {
+static fieldDefinition fieldDefinitionsExuberant [] = {
 	DEFINE_FIELD_SPEC ('C', "compact",        false,
 			   "compact input line (fixed field, only used in -x option)",
 			   renderFieldCompactInputLine),
@@ -143,7 +143,7 @@ static fieldSpec fieldSpecsExuberant [] = {
 			   renderFieldKindName),
 };
 
-static fieldSpec fieldSpecsUniversal [] = {
+static fieldDefinition fieldDefinitionsUniversal [] = {
 	DEFINE_FIELD_SPEC_FULL ('r', "role",    false,
 			   "Role",
 			   renderFieldRole, isRoleFieldAvailable),
@@ -182,43 +182,43 @@ extern void initFieldDescs (void)
 	Assert (fieldDescs == NULL);
 
 	fieldDescAllocated
-	  = ARRAY_SIZE (fieldSpecsFixed)
-	  + ARRAY_SIZE (fieldSpecsExuberant)
-	  + ARRAY_SIZE (fieldSpecsUniversal);
+	  = ARRAY_SIZE (fieldDefinitionsFixed)
+	  + ARRAY_SIZE (fieldDefinitionsExuberant)
+	  + ARRAY_SIZE (fieldDefinitionsUniversal);
 	fieldDescs = xMalloc (fieldDescAllocated, fieldDesc);
 
 	fieldDescUsed = 0;
 
-	for (i = 0; i < ARRAY_SIZE (fieldSpecsFixed); i++)
+	for (i = 0; i < ARRAY_SIZE (fieldDefinitionsFixed); i++)
 	{
 		fdesc = fieldDescs + i + fieldDescUsed;
-		fdesc->spec   = fieldSpecsFixed + i;
+		fdesc->spec   = fieldDefinitionsFixed + i;
 		fdesc->fixed  = 1;
 		fdesc->buffer = NULL;
 		fdesc->nameWithPrefix = fdesc->spec->name;
 		fdesc->language = LANG_IGNORE;
 		fdesc->sibling  = FIELD_UNKNOWN;
 	}
-	fieldDescUsed += ARRAY_SIZE (fieldSpecsFixed);
+	fieldDescUsed += ARRAY_SIZE (fieldDefinitionsFixed);
 
-	for (i = 0; i < ARRAY_SIZE (fieldSpecsExuberant); i++)
+	for (i = 0; i < ARRAY_SIZE (fieldDefinitionsExuberant); i++)
 	{
 		fdesc = fieldDescs + i + fieldDescUsed;
-		fdesc->spec = fieldSpecsExuberant +i;
+		fdesc->spec = fieldDefinitionsExuberant +i;
 		fdesc->fixed = 0;
 		fdesc->buffer = NULL;
 		fdesc->nameWithPrefix = fdesc->spec->name;
 		fdesc->language = LANG_IGNORE;
 		fdesc->sibling  = FIELD_UNKNOWN;
 	}
-	fieldDescUsed += ARRAY_SIZE (fieldSpecsExuberant);
+	fieldDescUsed += ARRAY_SIZE (fieldDefinitionsExuberant);
 
-	for (i = 0; i < ARRAY_SIZE (fieldSpecsUniversal); i++)
+	for (i = 0; i < ARRAY_SIZE (fieldDefinitionsUniversal); i++)
 	{
 		char *nameWithPrefix;
 
 		fdesc = fieldDescs + i + fieldDescUsed;
-		fdesc->spec = fieldSpecsUniversal + i;
+		fdesc->spec = fieldDefinitionsUniversal + i;
 		fdesc->fixed = 0;
 		fdesc->buffer = NULL;
 
@@ -235,7 +235,7 @@ extern void initFieldDescs (void)
 		fdesc->language = LANG_IGNORE;
 		fdesc->sibling  = FIELD_UNKNOWN;
 	}
-	fieldDescUsed += ARRAY_SIZE (fieldSpecsUniversal);
+	fieldDescUsed += ARRAY_SIZE (fieldDefinitionsUniversal);
 
 	Assert ( fieldDescAllocated == fieldDescUsed );
 }
@@ -401,9 +401,10 @@ static const char *renderEscapedName (const char* s,
 		int c = *s;
 		if ((c > 0x00 && c <= 0x1F) || c == 0x7F)
 		{
+			char letter = getLanguageKind(tag->langType, tag->kindIndex)->letter;
 			verbose ("Unexpected character (0 < *c && *c < 0x20) included in a tagEntryInfo: %s\n", base);
 			verbose ("File: %s, Line: %lu, Lang: %s, Kind: %c\n",
-				 tag->inputFileName, tag->lineNumber, tag->language, tag->kind->letter);
+				 tag->inputFileName, tag->lineNumber, getLanguageName(tag->langType), letter);
 			verbose ("Escape the character\n");
 			break;
 		}
@@ -518,7 +519,8 @@ static const char* renderCompactInputLine (vString *b,  const char *const line)
 
 static const char *renderFieldKindName (const tagEntryInfo *const tag, const char *value CTAGS_ATTR_UNUSED, vString* b)
 {
-	return renderAsIs (b, tag->kind->name);
+	kindDefinition *kdef = getLanguageKind(tag->langType, tag->kindIndex);
+	return renderAsIs (b, kdef->name);
 }
 
 static const char *renderFieldCompactInputLine (const tagEntryInfo *const tag,
@@ -564,15 +566,12 @@ static const char *renderFieldRole (const tagEntryInfo *const tag,
 				    vString* b)
 {
 	int rindex = tag->extensionFields.roleIndex;
-	const roleDesc * role;
 
 	if (rindex == ROLE_INDEX_DEFINITION)
 		vStringClear (b);
 	else
 	{
-		Assert (rindex < tag->kind->nRoles);
-		role  = & (tag->kind->roles [rindex]);
-		return renderRole (role, b);
+		return "TODO";
 	}
 
 	return vStringValue (b);
@@ -582,10 +581,12 @@ static const char *renderFieldLanguage (const tagEntryInfo *const tag,
 					const char *value CTAGS_ATTR_UNUSED,
 					vString* b)
 {
-	const char *l = tag->language;
+	const char *l;
 
-	if (Option.lineDirectives && tag->sourceLanguage)
-		l = tag->sourceLanguage;
+	if (Option.lineDirectives && (tag->sourceLangType != LANG_IGNORE))
+		l = getLanguageName(tag->sourceLangType);
+	else
+		l = getLanguageName(tag->langType);
 
 	return renderAsIs (b, WITH_DEFUALT_VALUE(l));
 }
@@ -601,11 +602,7 @@ static const char *renderFieldKindLetter (const tagEntryInfo *const tag,
 					  const char *value CTAGS_ATTR_UNUSED,
 					  vString* b)
 {
-	static char c[2] = { [1] = '\0' };
-
-	c [0] = tag->kind->letter;
-
-	return renderAsIs (b, c);
+	return "TODO";
 }
 
 static const char *renderFieldImplementation (const tagEntryInfo *const tag,
@@ -712,7 +709,7 @@ static const char *renderFieldEnd (const tagEntryInfo *const tag,
 
 static bool     isLanguageFieldAvailable (const tagEntryInfo *const tag)
 {
-	return (tag->language != NULL)? true: false;
+	return (tag->langType == LANG_IGNORE)? false: true;
 }
 
 static bool     isTyperefFieldAvailable  (const tagEntryInfo *const tag)
@@ -789,7 +786,7 @@ static bool isFieldFixed (fieldType type)
 
 extern bool enableField (fieldType type, bool state, bool warnIfFixedField)
 {
-	fieldSpec *spec = getFieldDesc(type)->spec;
+	fieldDefinition *spec = getFieldDesc(type)->spec;
 	bool old = spec->enabled? true: false;
 	if (isFieldFixed (type))
 	{
@@ -877,7 +874,7 @@ static const char* defaultRenderer (const tagEntryInfo *const tag,
 	return value;
 }
 
-extern int defineField (fieldSpec *spec, langType language)
+extern int defineField (fieldDefinition *spec, langType language)
 {
 	fieldDesc *fdesc;
 	char *nameWithPrefix;


Modified: ctags/main/field.h
6 lines changed, 3 insertions(+), 3 deletions(-)
===================================================================
@@ -58,7 +58,7 @@ typedef const char* (* renderEscaped) (const tagEntryInfo *const tag,
 typedef bool (* isValueAvailable) (const struct sTagEntryInfo *const tag);
 
 #define FIELD_LETTER_NO_USE '\0'
-typedef struct sFieldSpec {
+typedef struct sFieldDefinition {
 	/* lettern, and ftype are initialized in the main part,
 	   not in a parser. */
 #define NUL_FIELD_LETTER '\0'
@@ -70,7 +70,7 @@ typedef struct sFieldSpec {
 	isValueAvailable isValueAvailable;
 
 	unsigned int ftype;	/* Given from the main part */
-} fieldSpec;
+} fieldDefinition;
 
 
 extern fieldType getFieldTypeForOption (char letter);
@@ -105,7 +105,7 @@ extern int countFields (void);
 
 /* language should be typed to langType.
    Use int here to avoid circular dependency */
-extern int defineField (fieldSpec *spec, langType language);
+extern int defineField (fieldDefinition *spec, langType language);
 extern fieldType nextSiblingField (fieldType type);
 
 #endif	/* CTAGS_MAIN_FIELD_H */


Modified: ctags/main/htable.c
71 lines changed, 55 insertions(+), 16 deletions(-)
===================================================================
@@ -85,7 +85,7 @@ static void  entry_reclaim (hentry* entry,
 		entry = entry_destroy (entry, keyfreefn, valfreefn);
 }
 
-static void *entry_find (hentry* entry, void* key, hashTableEqualFunc equalfn)
+static void *entry_find (hentry* entry, const void* const key, hashTableEqualFunc equalfn)
 {
 	while (entry)
 	{
@@ -141,6 +141,17 @@ extern hashTable *hashTableNew    (unsigned int size,
 }
 
 extern void       hashTableDelete (hashTable *htable)
+{
+	if (!htable)
+		return;
+
+	hashTableClear (htable);
+
+	eFree (htable->table);
+	eFree (htable);
+}
+
+extern void       hashTableClear (hashTable *htable)
 {
 	unsigned int i;
 	if (!htable)
@@ -154,8 +165,6 @@ extern void       hashTableDelete (hashTable *htable)
 		entry_reclaim (entry, htable->keyfreefn, htable->valfreefn);
 		htable->table[i] = NULL;
 	}
-	eFree (htable->table);
-	eFree (htable);
 }
 
 extern void       hashTablePutItem    (hashTable *htable, void *key, void *value)
@@ -166,7 +175,7 @@ extern void       hashTablePutItem    (hashTable *htable, void *key, void *value
 	htable->table[i] = entry_new(key, value, htable->table[i]);
 }
 
-extern void*      hashTableGetItem   (hashTable *htable, void *key)
+extern void*      hashTableGetItem   (hashTable *htable, const void * key)
 {
 	unsigned int i;
 
@@ -183,7 +192,7 @@ extern bool     hashTableDeleteItem (hashTable *htable, void *key)
 			    htable->equalfn, htable->keyfreefn, htable->valfreefn);
 }
 
-extern bool    hashTableHasItem    (hashTable *htable, void *key)
+extern bool    hashTableHasItem    (hashTable *htable, const void *key)
 {
 	return hashTableGetItem (htable, key)? true: false;
 }
@@ -208,27 +217,28 @@ extern int        hashTableCountItem   (hashTable *htable)
 	hashTableForeachItem (htable, count, &c);
 	return c;
 }
-unsigned int hashPtrhash (void * x)
+
+unsigned int hashPtrhash (const void * const x)
 {
 	union {
-		void *ptr;
+		const void * ptr;
 		unsigned int ui;
 	} v;
-
 	v.ui = 0;
 	v.ptr = x;
+
 	return v.ui;
 }
 
-bool hashPtreq (void *a, void *b)
+bool hashPtreq (const void *const a, const void *const b)
 {
 	return (a == b)? true: false;
 }
 
 
 /* http://www.cse.yorku.ca/~oz/hash.html */
 static unsigned long
-djb2(unsigned char *str)
+djb2(const unsigned char *str)
 {
 	unsigned long hash = 5381;
 	int c;
@@ -239,18 +249,35 @@ djb2(unsigned char *str)
 	return hash;
 }
 
-unsigned int hashCstrhash (void * x)
+static unsigned long
+casedjb2(const unsigned char *str)
 {
-	char *s = x;
-	return (unsigned int)djb2((unsigned char *)s);
+	unsigned long hash = 5381;
+	int c;
+
+	while ((c = *str++))
+	{
+		if (('a' <= c) && (c <= 'z'))
+			c += ('A' - 'a');
+		hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
+	}
+
+	return hash;
 }
 
-bool hashCstreq (void *a, void *b)
+
+unsigned int hashCstrhash (const void *const x)
+{
+	const char *const s = x;
+	return (unsigned int)djb2((const unsigned char *)s);
+}
+
+bool hashCstreq (const void * const a, const void *const b)
 {
 	return !!(strcmp (a, b) == 0);
 }
 
-unsigned int hashInthash (void *x)
+unsigned int hashInthash (const void *const x)
 {
        union tmp {
                unsigned int u;
@@ -262,10 +289,22 @@ unsigned int hashInthash (void *x)
        return x0.u;
 }
 
-bool hashInteq (void *a, void *b)
+bool hashInteq (const void *const a, const void *const b)
 {
        int ai = *(int *)a;
        int bi = *(int *)b;
 
        return !!(ai == bi);
 }
+
+
+unsigned int hashCstrcasehash (const void *const x)
+{
+	const char *const s = x;
+	return (unsigned int)casedjb2((const unsigned char *)s);
+}
+
+bool hashCstrcaseeq (const void *const a, const void *const b)
+{
+	return !!(strcasecmp (a, b) == 0);
+}


Modified: ctags/main/htable.h
24 lines changed, 14 insertions(+), 10 deletions(-)
===================================================================
@@ -14,29 +14,33 @@
 #include "general.h"
 
 typedef struct sHashTable hashTable;
-typedef unsigned int (* hashTableHashFunc)  (void * key);
-typedef bool      (* hashTableEqualFunc) (void* a, void* b);
+typedef unsigned int (* hashTableHashFunc)  (const void * const key);
+typedef bool      (* hashTableEqualFunc) (const void* a, const void* b);
 typedef void         (* hashTableFreeFunc)  (void * ptr);
 typedef void         (* hashTableForeachFunc) (void *key, void *value, void* user_data);
 
-unsigned int hashPtrhash (void * x);
-bool hashPtreq (void *a, void *b);
+unsigned int hashPtrhash (const void * x);
+bool hashPtreq (const void * a, const void * constb);
 
-unsigned int hashCstrhash (void * x);
-bool hashCstreq (void *a, void *b);
+unsigned int hashCstrhash (const void * x);
+bool hashCstreq (const void * a, const void * b);
 
-unsigned int hashInthash (void *x);
-bool hashInteq (void *a, void *b);
+unsigned int hashCstrcasehash (const void * x);
+bool hashCstrcaseeq (const void * a, const void * b);
+
+unsigned int hashInthash (const void * x);
+bool hashInteq (const void * a, const void * b);
 
 extern hashTable* hashTableNew         (unsigned int size,
 					hashTableHashFunc hashfn,
 					hashTableEqualFunc equalfn,
 					hashTableFreeFunc keyfreefn,
 					hashTableFreeFunc valfreefn);
 extern void       hashTableDelete      (hashTable *htable);
+extern void       hashTableClear       (hashTable *htable);
 extern void       hashTablePutItem     (hashTable *htable, void *key, void *value);
-extern void*      hashTableGetItem     (hashTable *htable, void *key);
-extern bool    hashTableHasItem     (hashTable *htable, void *key);
+extern void*      hashTableGetItem     (hashTable *htable, const void * key);
+extern bool    hashTableHasItem     (hashTable * htable, const void * key);
 extern bool    hashTableDeleteItem  (hashTable *htable, void *key);
 extern void       hashTableForeachItem (hashTable *htable, hashTableForeachFunc proc, void *user_data);
 extern int        hashTableCountItem   (hashTable *htable);


Modified: ctags/main/inline.h
26 lines changed, 26 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,26 @@
+/*
+ *
+ *  Copyright (c) 2016, 2017 Matthew Brush
+ *
+ *
+ *   This source code is released for free distribution under the terms of the
+ *   GNU General Public License version 2 or (at your option) any later version.
+ *
+ */
+
+#ifndef CTAGS_MAIN_INLINE_H
+#define CTAGS_MAIN_INLINE_H
+
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+# define CTAGS_INLINE static inline
+#elif defined(_MSC_VER)
+# define CTAGS_INLINE static __inline
+#elif defined(__GNUC__) || defined(__clang__)
+# define CTAGS_INLINE static __inline__
+// #elif ... other compilers/tests here ...
+// # define CTAGS_INLINE ...
+#else
+# define CTAGS_INLINE static
+#endif
+
+#endif /* CTAGS_MAIN_INLINE_H */


Modified: ctags/main/kind.c
27 lines changed, 13 insertions(+), 14 deletions(-)
===================================================================
@@ -17,13 +17,13 @@
 #include "kind.h"
 #include "parse.h"
 
-extern void printRole (const roleDesc* const role)
+extern void printRole (const roleDefinition* const role)
 {
 	if (role)
 		printf ("%s\t%s\t%s\n", role->name, role->description, role->enabled? "on": "off");
 }
 
-extern const char *renderRole (const roleDesc* const role, vString* b)
+extern const char *renderRole (const roleDefinition* const role, vString* b)
 {
 	vStringCatS (b, role->name);
 	return vStringValue (b);
@@ -78,7 +78,7 @@ extern void printKindListHeader (bool indent, bool tabSeparated)
 #undef KIND_HEADER_COMMON_FMT
 }
 
-extern void printKind (const kindOption* const kind, bool allKindFields, bool indent,
+extern void printKind (const kindDefinition* const kind, bool allKindFields, bool indent,
 		       bool tabSeparated)
 {
 #define KIND_FMT MAKE_KIND_FMT("", c, d)
@@ -109,19 +109,18 @@ extern void printKind (const kindOption* const kind, bool allKindFields, bool in
 #undef KIND_FMT
 }
 
-const char *scopeSeparatorFor (const kindOption *kind, char parentLetter)
+const char *scopeSeparatorFor (langType lang, int kindIndex, int parentKindIndex)
 {
-	scopeSeparator *table;
-	Assert (kind);
-	table = kind->separators;
+	kindDefinition *kind = getLanguageKind (lang, kindIndex);
+	scopeSeparator *table = kind->separators;
 
 	/* If no table is given, use the default generic separator ".".
 	   The exception is if a root separator is looked up. In this case,
 	   return NULL to notify there is no root separator to the caller. */
 
 	if (table == NULL)
 	{
-		if (parentLetter == KIND_NULL)
+		if (parentKindIndex == KIND_GHOST_INDEX)
 			return NULL;
 		else
 			return ".";
@@ -131,21 +130,21 @@ const char *scopeSeparatorFor (const kindOption *kind, char parentLetter)
 	{
 		/* KIND_WILDCARD cannot be used as a key for finding
 		   a root separator.*/
-		if ( (table->parentLetter == KIND_WILDCARD
-		       && parentLetter != KIND_NULL)
-		    || table->parentLetter == parentLetter)
+		if ( (table->parentKindIndex == KIND_WILDCARD_INDEX
+		       && parentKindIndex != KIND_GHOST_INDEX)
+		    || table->parentKindIndex == parentKindIndex)
 			return table->separator;
 		table++;
 	}
-	if (parentLetter == KIND_NULL)
+	if (parentKindIndex == KIND_GHOST_INDEX)
 		return NULL;
 	else
 		return ".";
 }
 
-extern void enableKind (kindOption *kind, bool enable)
+extern void enableKind (kindDefinition *kind, bool enable)
 {
-	kindOption *slave;
+	kindDefinition *slave;
 
 	if (kind->master)
 		enableKind (kind->master, enable);


Modified: ctags/main/kind.h
27 lines changed, 15 insertions(+), 12 deletions(-)
===================================================================
@@ -13,14 +13,14 @@
 #include "routines.h"		/* for STRINGIFY */
 #include "vstring.h"
 
-typedef struct sRoleDesc {
+typedef struct sRoleDefinition {
 	bool enabled;
 	const char* name;		  /* role name */
 	const char* description;	  /* displayed in --help output */
-} roleDesc;
+} roleDefinition;
 
-extern void printRole (const roleDesc* const role); /* for --help */
-extern const char *renderRole (const roleDesc* const role, vString* b);
+extern void printRole (const roleDefinition* const role); /* for --help */
+extern const char *renderRole (const roleDefinition* const role, vString* b);
 
 /*
  * Predefined kinds
@@ -32,9 +32,11 @@ extern const char *renderRole (const roleDesc* const role, vString* b);
 
 #define KIND_NULL    '\0'
 
+#define KIND_GHOST_INDEX -1
 #define KIND_GHOST   ' '
 #define KIND_GHOST_LONG "ghost"
 
+#define KIND_FILE_INDEX -2
 #define KIND_FILE_DEFAULT 'F'
 #define KIND_FILE_DEFAULT_LONG "file"
 
@@ -43,21 +45,22 @@ extern const char *renderRole (const roleDesc* const role, vString* b);
 #define KIND_GENERIC_REFERENCE '@'
 #define KIND_GENERIC_REFERENCE_DEFAULT_LONG "reference"
 
+#define KIND_WILDCARD_INDEX -3
 #define KIND_WILDCARD '*'
 
 typedef struct sScopeSeparator {
-	char  parentLetter;
+	int parentKindIndex;
 	const char *separator;
 } scopeSeparator;
 
-struct sKindOption {
+struct sKindDefinition {
 	bool enabled;          /* are tags for kind enabled? */
 	char  letter;               /* kind letter */
 	const char* name;		  /* kind name */
 	const char* description;	  /* displayed in --help output */
 	bool referenceOnly;
 	int nRoles;		/* The number of role elements. */
-	roleDesc *roles;
+	roleDefinition *roles;
 	scopeSeparator *separators;
 	unsigned int separatorCount;
 
@@ -71,20 +74,20 @@ struct sKindOption {
 	   If the value other than `LANG_AUTO' is specified,
 	   the main part does nothing. */
 	langType syncWith;
-	kindOption *slave;
-	kindOption *master;
+	kindDefinition *slave;
+	kindDefinition *master;
 };
 
 #define ATTACH_ROLES(RS) .nRoles = ARRAY_SIZE(RS), .roles = RS
 #define ATTACH_SEPARATORS(S) .separators = S, .separatorCount = ARRAY_SIZE(S)
 
 /* The value of `tabSeparated' is meaningfull only when `allKindFields' is true. */
-extern void printKind (const kindOption* const kind, bool allKindFields, bool indent,
+extern void printKind (const kindDefinition* const kind, bool allKindFields, bool indent,
 		       bool tabSeparated);
 extern void printKindListHeader (bool indent, bool tabSeparated);
-extern const char *scopeSeparatorFor (const kindOption *kind, char parentLetter);
+extern const char *scopeSeparatorFor (langType lang, int kindIndex, int parentKindIndex);
 
-extern void enableKind (kindOption *kind, bool enable);
+extern void enableKind (kindDefinition *kind, bool enable);
 
 #define PR_KIND_STR(X) PR_KIND_WIDTH_##X
 #define PR_KIND_FMT(X,T) "%-" STRINGIFY(PR_KIND_STR(X)) STRINGIFY(T)


Modified: ctags/main/lcpp.c
16 lines changed, 8 insertions(+), 8 deletions(-)
===================================================================
@@ -66,7 +66,7 @@ typedef struct sCppState {
 	bool resolveRequired;     /* must resolve if/else/elif/endif branch */
 	bool hasAtLiteralStrings; /* supports @"c:\" strings */
 	bool hasCxxRawLiteralStrings; /* supports R"xxx(...)xxx" strings */
-	const kindOption  *defineMacroKind;
+	int  defineMacroKindIndex;
 	struct sDirective {
 		enum eState state;       /* current directive being processed */
 		bool	accept;          /* is a directive syntactically permitted? */
@@ -92,7 +92,7 @@ static cppState Cpp = {
 	false,       /* resolveRequired */
 	false,       /* hasAtLiteralStrings */
 	false,       /* hasCxxRawLiteralStrings */
-	NULL,        /* defineMacroKind */
+	-1,          /* defineMacroKindIndex */
 	{
 		DRCTV_NONE,  /* state */
 		false,       /* accept */
@@ -118,7 +118,7 @@ extern unsigned int cppGetDirectiveNestLevel (void)
 
 extern void cppInit (const bool state, const bool hasAtLiteralStrings,
                      const bool hasCxxRawLiteralStrings,
-                     const kindOption *defineMacroKind)
+                     int defineMacroKindIndex)
 {
 	BraceFormat = state;
 
@@ -127,7 +127,7 @@ extern void cppInit (const bool state, const bool hasAtLiteralStrings,
 	Cpp.resolveRequired = false;
 	Cpp.hasAtLiteralStrings = hasAtLiteralStrings;
 	Cpp.hasCxxRawLiteralStrings = hasCxxRawLiteralStrings;
-	Cpp.defineMacroKind = defineMacroKind;
+	Cpp.defineMacroKindIndex = defineMacroKindIndex;
 
 	Cpp.directive.state     = DRCTV_NONE;
 	Cpp.directive.accept    = true;
@@ -326,22 +326,22 @@ static int makeDefineTag (const char *const name, bool parameterized, bool undef
 {
 	const bool isFileScope = (bool) (! isInputHeaderFile ());
 
-	if (!Cpp.defineMacroKind)
+	if (Cpp.defineMacroKindIndex == -1)
 		return CORK_NIL;
 	if (isFileScope && !isXtagEnabled(XTAG_FILE_SCOPE))
 		return CORK_NIL;
 
 	if ( /* condition for definition tag */
-		((!undef) && Cpp.defineMacroKind->enabled)
+		((!undef) && isLanguageKindEnabled (getInputLanguage(), Cpp.defineMacroKindIndex))
 		|| /* condition for reference tag */
 		(undef && isXtagEnabled(XTAG_REFERENCE_TAGS)))
 	{
 		tagEntryInfo e;
 
-		initTagEntry (&e, name, Cpp.defineMacroKind);
+		initTagEntry (&e, name, Cpp.defineMacroKindIndex);
 		e.lineNumberEntry = (bool) (Option.locate == EX_LINENUM);
 		e.isFileScope  = isFileScope;
-		e.truncateLine = true;
+		e.truncateLineAfterTag = true;
 		if (parameterized)
 			e.extensionFields.signature = cppGetSignature ();
 		makeTagEntry (&e);


Modified: ctags/main/lcpp.h
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -64,7 +64,7 @@ extern unsigned int cppGetDirectiveNestLevel (void);
 extern void cppInit (const bool state,
 		     const bool hasAtLiteralStrings,
 		     const bool hasCxxRawLiteralStrings,
-		     const kindOption *defineMacroKind);
+		     int defineMacroKindIndex);
 extern void cppTerminate (void);
 extern void cppBeginStatement (void);
 extern void cppEndStatement (void);


Modified: ctags/main/lregex.c
34 lines changed, 20 insertions(+), 14 deletions(-)
===================================================================
@@ -75,7 +75,7 @@ typedef struct {
 	union {
 		struct {
 			char *name_pattern;
-			kindOption *kind;
+			kindDefinition *kind;
 		} tag;
 		struct {
 			regexCallback function;
@@ -139,9 +139,14 @@ static void clearPatternSet (const langType language)
 */
 
 static int makeRegexTag (
-		const vString* const name, const kindOption* const kind, int scopeIndex, int placeholder)
+		const vString* const name, const kindDefinition* const kind, int scopeIndex, int placeholder)
 {
 	Assert (kind != NULL);
+	/* TODO: Disable regex tag generation for now. We would need to pass kindIndex
+	 * to initTagEntry() but currently we don't have kinds indexable because
+	 * they are stored in hash table. Consider whether we want to support
+	 * regex parsers at all in Geany. */
+#if 0
 	if (kind->enabled)
 	{
 		tagEntryInfo e;
@@ -152,6 +157,7 @@ static int makeRegexTag (
 		return makeTagEntry (&e);
 	}
 	else
+#endif
 		return CORK_NIL;
 }
 
@@ -299,9 +305,9 @@ static flagDefinition scopePtrnFlagDef[] = {
 	  NULL, "don't put this tag to tags file."},
 };
 
-static kindOption *kindNew ()
+static kindDefinition *kindNew ()
 {
-	kindOption *kind = xCalloc (1, kindOption);
+	kindDefinition *kind = xCalloc (1, kindDefinition);
 	kind->letter        = '\0';
 	kind->name = NULL;
 	kind->description = NULL;
@@ -314,7 +320,7 @@ static kindOption *kindNew ()
 
 static void kindFree (void *data)
 {
-	kindOption *kind = data;
+	kindDefinition *kind = data;
 	kind->letter = '\0';
 	if (kind->name)
 	{
@@ -335,7 +341,7 @@ static regexPattern* addCompiledTagCommon (const langType language,
 {
 	patternSet* set;
 	regexPattern *ptrn;
-	kindOption *kind = NULL;
+	kindDefinition *kind = NULL;
 
 	if (language > SetUpper)
 	{
@@ -865,14 +871,14 @@ extern bool processRegexOption (const char *const option,
 }
 
 struct kindCbHelperData {
-	bool (*func) (kindOption *, void *);
+	bool (*func) (kindDefinition *, void *);
 	void *func_data;
 	bool result;
 };
 
 static void kindCbHelper (void *key, void *value, void* user_data)
 {
-	kindOption *kind = value;
+	kindDefinition *kind = value;
 	struct kindCbHelperData *helper_data = user_data;
 
 	if (helper_data->result)
@@ -882,7 +888,7 @@ static void kindCbHelper (void *key, void *value, void* user_data)
 }
 
 extern void foreachRegexKinds (const langType language,
-			       bool (*func) (kindOption *, void *),
+			       bool (*func) (kindDefinition *, void *),
 			       void *data)
 {
 	initializeParser (language);
@@ -900,7 +906,7 @@ extern void foreachRegexKinds (const langType language,
 }
 
 
-static bool kind_reset_cb (kindOption *kind, void *data)
+static bool kind_reset_cb (kindDefinition *kind, void *data)
 {
 	kind->enabled = *(bool *)data;
 	return false;		/* continue */
@@ -919,7 +925,7 @@ struct kind_and_mode_and_result
 	bool result;
 };
 
-static bool enable_kind_cb (kindOption *kind, void *data)
+static bool enable_kind_cb (kindDefinition *kind, void *data)
 {
 	struct kind_and_mode_and_result *kmr = data;
 	if ((kmr->kind != KIND_NULL
@@ -967,7 +973,7 @@ struct kind_and_result
 	bool result;
 };
 
-static bool is_kind_enabled_cb (kindOption *kind, void *data)
+static bool is_kind_enabled_cb (kindDefinition *kind, void *data)
 {
 	bool r = false;
 	struct kind_and_result *kr = data;
@@ -981,7 +987,7 @@ static bool is_kind_enabled_cb (kindOption *kind, void *data)
 	return r;
 }
 
-static bool does_kind_exist_cb (kindOption *kind, void *data)
+static bool does_kind_exist_cb (kindDefinition *kind, void *data)
 {
 	bool r = false;
 	struct kind_and_result *kr = data;
@@ -1026,7 +1032,7 @@ struct printRegexKindCBData{
 	bool tabSeparated;
 };
 
-static bool printRegexKind (kindOption *kind, void *user_data)
+static bool printRegexKind (kindDefinition *kind, void *user_data)
 {
 	struct printRegexKindCBData *data = user_data;
 	if (kind->letter != KIND_GHOST)


Modified: ctags/main/lxcmd.c
36 lines changed, 18 insertions(+), 18 deletions(-)
===================================================================
@@ -116,7 +116,7 @@ typedef struct {
 	} address;
 
 
-	const kindOption* kind;
+	const kindDefinition* kind;
 
 		/* is tag of file-limited scope? */
 	short fileScope;
@@ -134,7 +134,7 @@ typedef struct {
 
 typedef struct {
 	vString *path;
-	kindOption *kinds;
+	kindDefinition *kinds;
 	unsigned int n_kinds;
 	bool available;
 	unsigned int id;	/* not used yet */
@@ -166,7 +166,7 @@ static void clearPathSet (const langType language)
 			p->available = false;
 			for (k = 0; k < p->n_kinds; k++)
 			{
-				kindOption* kind = &(p->kinds[k]);
+				kindDefinition* kind = &(p->kinds[k]);
 
 				eFree ((void *)kind->name);
 				kind->name = NULL;
@@ -191,7 +191,7 @@ static bool loadPathKind (xcmdPath *const path, char* line, char *args[])
 	const char* backup = line;
 	char* off;
 	vString *desc;
-	kindOption *kind;
+	kindDefinition *kind;
 
 	if (line[0] == '\0')
 		return false;
@@ -201,7 +201,7 @@ static bool loadPathKind (xcmdPath *const path, char* line, char *args[])
 		return false;
 	}
 
-	path->kinds = xRealloc (path->kinds, path->n_kinds + 1, kindOption);
+	path->kinds = xRealloc (path->kinds, path->n_kinds + 1, kindDefinition);
 	kind = &path->kinds [path->n_kinds];
 	memset (kind, 0, sizeof (*kind));
 	kind->enabled = true;
@@ -405,7 +405,7 @@ static bool loadPathKinds  (xcmdPath *const path, const langType language)
 
 
 extern void foreachXcmdKinds (const langType language,
-			      bool (*func) (kindOption *, void *),
+			      bool (*func) (kindDefinition *, void *),
 			      void *data)
 {
 #ifdef HAVE_COPROC
@@ -428,7 +428,7 @@ extern void foreachXcmdKinds (const langType language,
 #endif
 }
 
-static bool kind_reset_cb (kindOption *kind, void *data)
+static bool kind_reset_cb (kindDefinition *kind, void *data)
 {
 	kind->enabled = *(bool *)data;
 	return false;		/* continue */
@@ -447,7 +447,7 @@ struct kind_and_mode_and_result
 	bool result;
 };
 
-static bool enable_kind_cb (kindOption *kind, void *data)
+static bool enable_kind_cb (kindDefinition *kind, void *data)
 {
 	struct kind_and_mode_and_result *kmr = data;
 	if ((kmr->kind != KIND_NULL
@@ -500,7 +500,7 @@ struct kind_and_result
 	bool result;
 };
 
-static bool is_kind_enabled_cb (kindOption *kind, void *data)
+static bool is_kind_enabled_cb (kindDefinition *kind, void *data)
 {
 	bool r = false;
 	struct kind_and_result *kr = data;
@@ -514,7 +514,7 @@ static bool is_kind_enabled_cb (kindOption *kind, void *data)
 	return r;
 }
 
-static bool does_kind_exist_cb (kindOption *kind, void *data)
+static bool does_kind_exist_cb (kindDefinition *kind, void *data)
 {
 	bool r = false;
 	struct kind_and_result *kr = data;
@@ -560,7 +560,7 @@ struct printXcmdKindCBData {
 };
 
 #ifdef HAVE_COPROC
-static bool printXcmdKind (kindOption *kind, void *user_data)
+static bool printXcmdKind (kindDefinition *kind, void *user_data)
 {
 	struct printXcmdKindCBData *data = user_data;
 
@@ -732,10 +732,10 @@ extern bool processXcmdOption (const char *const option, const char *const param
 }
 
 #ifdef HAVE_COPROC
-static const kindOption* lookupKindFromLetter (const xcmdPath* const path, char kind_letter)
+static const kindDefinition* lookupKindFromLetter (const xcmdPath* const path, char kind_letter)
 {
 	unsigned int k;
-	kindOption *kind;
+	kindDefinition *kind;
 
 	for (k = 0; k < path->n_kinds; k++)
 	{
@@ -747,10 +747,10 @@ static const kindOption* lookupKindFromLetter (const xcmdPath* const path, char
 
 }
 
-static const kindOption* lookupKindFromName (const xcmdPath* const path, const char* const kind_name)
+static const kindDefinition* lookupKindFromName (const xcmdPath* const path, const char* const kind_name)
 {
 	unsigned int k;
-	kindOption *kind;
+	kindDefinition *kind;
 
 	for (k = 0; k < path->n_kinds; k++)
 	{
@@ -799,7 +799,7 @@ static const char* entryGetAnyUnpulledField (tagEntry *const entry, const char *
 static bool isKindEnabled (xcmdPath* path, const char* value)
 {
 	unsigned int k;
-	kindOption *kind;
+	kindDefinition *kind;
 
 	Assert (path->kinds);
 	Assert (value);
@@ -857,7 +857,7 @@ static bool parseExtensionFields (tagEntry *const entry, char *const string, xcm
 						entry->kind = lookupKindFromLetter (path, field[0]);
 						if (entry->kind == NULL)
 						{
-							kindOption *fileKind = getInputLanguageFileKind ();
+							kindDefinition *fileKind = getInputLanguageFileKind ();
 							if (fileKind && fileKind->letter == field[0])
 								/* ctags will make a tag for file. */
 								goto reject;
@@ -889,7 +889,7 @@ static bool parseExtensionFields (tagEntry *const entry, char *const string, xcm
 							entry->kind = lookupKindFromName (path, value);
 							if (entry->kind == NULL)
 							{
-								kindOption *fileKind = getInputLanguageFileKind ();
+								kindDefinition *fileKind = getInputLanguageFileKind ();
 								if (fileKind && (strcmp(fileKind->name, value) == 0))
 									/* ctags will make a tag for file. */
 									goto reject;


Modified: ctags/main/lxpath.c
15 lines changed, 6 insertions(+), 9 deletions(-)
===================================================================
@@ -23,25 +23,22 @@
 
 static void simpleXpathMakeTag (xmlNode *node,
 				const tagXpathMakeTagSpec *spec,
-				const kindOption* const kinds,
+				const kindDefinition* const kinds,
 				void *userData)
 {
 	tagEntryInfo tag;
 	xmlChar* str;
-	const kindOption *kind;
 	char *path;
 
 	str = xmlNodeGetContent(node);
 	if (str == NULL)
 		return;
 
-	kind = kinds + spec->kind;
-
 	if (spec->role == ROLE_INDEX_DEFINITION)
-		initTagEntry (&tag, (char *)str, kind);
+		initTagEntry (&tag, (char *)str, spec->kind);
 	else if (isXtagEnabled(XTAG_REFERENCE_TAGS))
 		initRefTagEntry (&tag, (char *)str,
-				 kind,
+				 spec->kind,
 				 spec->role);
 	else
 		goto out;
@@ -77,7 +74,7 @@ extern void addTagXpath (const langType language CTAGS_ATTR_UNUSED, tagXpathTabl
 
 static void findXMLTagsCore (xmlXPathContext *ctx, xmlNode *root,
 			     const tagXpathTableTable *xpathTableTable,
-			     const kindOption* const kinds,void *userData)
+			     const kindDefinition* const kinds,void *userData)
 {
 	unsigned int i;
 	int j;
@@ -156,7 +153,7 @@ static xmlDocPtr makeXMLDoc (void)
 
 extern void findXMLTags (xmlXPathContext *ctx, xmlNode *root,
 			 const tagXpathTableTable *xpathTableTable,
-			 const kindOption* const kinds,void *userData)
+			 const kindDefinition* const kinds,void *userData)
 {
 	bool usedAsEntryPoint = false;
 	xmlDocPtr doc = NULL;
@@ -210,7 +207,7 @@ extern void addTagXpath (const langType language, tagXpathTable *xpathTable)
 
 extern void findXMLTags (xmlXPathContext *ctx, xmlNode *root,
 			 const tagXpathTableTable *xpathTableTable,
-			 const kindOption* const kinds, void *userData)
+			 const kindDefinition* const kinds, void *userData)
 {
 }
 


Modified: ctags/main/mbcs.h
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1 @@
+/* Dummy header - only included by some parsers */


Modified: ctags/main/mio.c
32 lines changed, 16 insertions(+), 16 deletions(-)
===================================================================
@@ -48,7 +48,7 @@
 #define xCalloc(n,Type)    (Type *)eCalloc((size_t)(n), sizeof (Type))
 #define xRealloc(p,n,Type) (Type *)eRealloc((p), (n) * sizeof (Type))
 
-extern void *eMalloc (const size_t size)
+static void *eMalloc (const size_t size)
 {
 	void *buffer = malloc (size);
 
@@ -61,7 +61,7 @@ extern void *eMalloc (const size_t size)
 	return buffer;
 }
 
-extern void *eCalloc (const size_t count, const size_t size)
+static void *eCalloc (const size_t count, const size_t size)
 {
 	void *buffer = calloc (count, size);
 
@@ -74,7 +74,7 @@ extern void *eCalloc (const size_t count, const size_t size)
 	return buffer;
 }
 
-extern void *eRealloc (void *const ptr, const size_t size)
+static void *eRealloc (void *const ptr, const size_t size)
 {
 	void *buffer;
 	if (ptr == NULL)
@@ -91,13 +91,13 @@ extern void *eRealloc (void *const ptr, const size_t size)
 	return buffer;
 }
 
-extern void eFree (void *const ptr)
+static void eFree (void *const ptr)
 {
 	free (ptr);
 }
 
-#  define Assert(c)
-#  define AssertNotReached()
+#  define Assert(c) do {} while(0)
+#  define AssertNotReached() do {} while(0)
 #endif
 
 /* minimal reallocation chunk size */
@@ -361,20 +361,20 @@ MIO *mio_new_memory (unsigned char *data,
  * @size: the length of the data copied from @base to new mio
  *
  * Creates a new #MIO object by copying data from existing #MIO (@base).
- * The range for copying are given with @start and @size.
+ * The range for copying is given with @start and @size.
  * Copying data at the range from @start to the end of @base is
- * done if 0 is given as @size.
+ * done if -1 is given as @size.
  *
- * If @size(!= 0) is larger than the length from @start to the end of
- * @base, %NULL is return.
+ * If @size is larger than the length from @start to the end of
+ * @base, %NULL is returned.
  *
  * The function doesn't move the file position of @base.
  *
  * Free-function: mio_free()
  *
  */
 
-MIO *mio_new_mio (MIO *base, long start, size_t size)
+MIO *mio_new_mio (MIO *base, long start, long size)
 {
 	unsigned char *data;
 	long original_pos;
@@ -383,15 +383,15 @@ MIO *mio_new_mio (MIO *base, long start, size_t size)
 
 	original_pos = mio_tell (base);
 
-	if (size == 0)
+	if (size == -1)
 	{
 		long end;
 
 		if (mio_seek (base, 0, SEEK_END) != 0)
 			return NULL;
 		end = mio_tell (base);
+		Assert (end >= start);
 		size = end - start;
-		Assert (size >= 0);
 	}
 
 	if (mio_seek (base, start, SEEK_SET) != 0)
@@ -732,7 +732,7 @@ size_t mio_write (MIO *mio,
  * Writes a character to a #MIO stream. This function behaves the same as
  * fputc().
  *
- * Returns: The written wharacter, or %EOF on error.
+ * Returns: The written character, or %EOF on error.
  */
 int mio_putc (MIO *mio, int c)
 {
@@ -796,7 +796,7 @@ int mio_puts (MIO *mio, const char *s)
 /**
  * mio_vprintf:
  * @mio: A #MIO object
- * @format: A printf fomrat string
+ * @format: A printf format string
  * @ap: The variadic argument list for the format
  *
  * Writes a formatted string into a #MIO stream. This function behaves the same
@@ -1100,7 +1100,7 @@ int mio_error (MIO *mio)
  *          SEEK_CUR from the current position and SEEK_SET from the end of the
  *          stream.
  *
- * Sets the curosr position on a #MIO stream. This functions behaves the same as
+ * Sets the cursor position on a #MIO stream. This functions behaves the same as
  * fseek(). See also mio_tell() and mio_setpos().
  *
  * Returns: 0 on success, -1 otherwise, in which case errno should be set to


Modified: ctags/main/mio.h
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -123,7 +123,7 @@ MIO *mio_new_memory (unsigned char *data,
 					 MIOReallocFunc realloc_func,
 					 MIODestroyNotify free_func);
 
-MIO *mio_new_mio    (MIO *base, long start, size_t size);
+MIO *mio_new_mio    (MIO *base, long start, long size);
 MIO *mio_ref        (MIO *mio);
 
 int mio_free (MIO *mio);


Modified: ctags/main/numarray.c
175 lines changed, 175 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,175 @@
+/*
+*   Copyright (c) 1999-2002, Darren Hiebert
+*
+*   This source code is released for free distribution under the terms of the
+*   GNU General Public License version 2 or (at your option) any later version.
+*
+*   This module contains functions managing resizable pointer arrays.
+*/
+
+/*
+*   INCLUDE FILES
+*/
+#include "general.h"  /* must always come first */
+
+#include "debug.h"
+#include "numarray.h"
+#include "routines.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#define impNumArray(prefix,Prefix,type)									\
+																		\
+	struct s##Prefix##Array {											\
+		unsigned int max;												\
+		unsigned int count;												\
+		type *array;													\
+	};																	\
+																		\
+	extern prefix##Array *prefix##ArrayNew (void)						\
+	{																	\
+		prefix##Array* const result = xMalloc (1, prefix##Array);		\
+		result->max = 8;												\
+		result->count = 0;												\
+		result->array = xMalloc (result->max, type);					\
+		return result;													\
+	}																	\
+																		\
+	extern void prefix##ArrayAdd (prefix##Array *const current, type num) \
+	{																	\
+		Assert (current != NULL);										\
+		if (current->count == current->max)								\
+		{																\
+			current->max *= 2;											\
+			current->array = xRealloc (current->array, current->max, type);	\
+		}																\
+		current->array [current->count++] = num;						\
+	}																	\
+																		\
+	extern void prefix##ArrayRemoveLast (prefix##Array *const current)	\
+	{																	\
+		Assert (current != NULL);										\
+		Assert (current->count > 0);									\
+		--current->count;												\
+	}																	\
+																		\
+	extern void prefix##ArrayCombine (prefix##Array *const current, prefix##Array *const from) \
+	{																	\
+		unsigned int i;													\
+		Assert (current != NULL);										\
+		Assert (from != NULL);											\
+		for (i = 0  ;  i < from->count  ;  ++i)							\
+			prefix##ArrayAdd (current, from->array [i]);				\
+		from->count = 0;												\
+		prefix##ArrayDelete (from);										\
+	}																	\
+																		\
+	extern unsigned int prefix##ArrayCount (const prefix##Array *const current)	\
+	{																	\
+		Assert (current != NULL);										\
+		return current->count;											\
+	}																	\
+																		\
+	extern type prefix##ArrayItem (const prefix##Array *const current, const unsigned int indx)	\
+	{																	\
+		Assert (current != NULL);										\
+		return current->array [indx];									\
+	}																	\
+																		\
+	extern type prefix##ArrayLast (const prefix##Array *const current)	\
+	{																	\
+		Assert (current != NULL);										\
+		Assert (current->count > 0);									\
+		return current->array [current->count - 1];						\
+	}																	\
+																		\
+	extern void prefix##ArrayClear (prefix##Array *const current)		\
+	{																	\
+		Assert (current != NULL);										\
+		current->count = 0;												\
+	}																	\
+																		\
+	extern void prefix##ArrayDelete (prefix##Array *const current)		\
+	{																	\
+		if (current != NULL)											\
+		{																\
+			prefix##ArrayClear (current);								\
+			eFree (current->array);										\
+			eFree (current);											\
+		}																\
+	}																	\
+																		\
+	extern bool prefix##ArrayHasTest (const prefix##Array *const current, \
+									  bool (*test)(const type num, void *userData),	\
+									  void *userData)					\
+	{																	\
+		bool result = false;											\
+		unsigned int i;													\
+		Assert (current != NULL);										\
+		for (i = 0  ;  ! result  &&  i < current->count  ;  ++i)		\
+			result = (*test)(current->array [i], userData);				\
+		return result;													\
+	}																	\
+																		\
+	static bool prefix##Eq (const type num, void *userData)				\
+	{																	\
+		type *num0 = userData;											\
+		return (num == *num0);											\
+	}																	\
+																		\
+	extern bool prefix##ArrayHas (const prefix##Array *const current, type num)	\
+	{																	\
+		return prefix##ArrayHasTest (current, prefix##Eq, &num);		\
+	}																	\
+																		\
+	extern void prefix##ArrayReverse (const prefix##Array *const current) \
+	{																	\
+		unsigned int i, j;												\
+		type tmp;														\
+																		\
+		Assert (current != NULL);										\
+		for (i = 0, j = current->count - 1 ; i <  (current->count / 2); ++i, --j) \
+		{																\
+			tmp = current->array[i];									\
+			current->array[i] = current->array[j];						\
+			current->array[j] = tmp;									\
+		}																\
+	}																	\
+																		\
+	extern void prefix##ArrayDeleteItem (prefix##Array* const current, unsigned int indx) \
+	{																	\
+		memmove (current->array + indx, current->array + indx + 1,		\
+				 (current->count - indx) * sizeof (*current->array));	\
+		--current->count;												\
+	}																	\
+	static int prefix##GreaterThan(const void *a, const void *b)		\
+    {																	\
+		type an = *(type *)a;											\
+		type bn = *(type *)b;											\
+		if (an > bn)													\
+			return 1;													\
+		else if (an == bn)												\
+			return 0;													\
+		else															\
+			return -1;													\
+	}																	\
+	static int prefix##LessThan(const void *a, const void *b)			\
+	{																	\
+		return prefix##GreaterThan (b, a);								\
+	}																	\
+	extern void prefix##ArraySort (prefix##Array *const current, bool descendingOrder) \
+	{																	\
+		if (descendingOrder)											\
+			qsort (current->array, current->count, sizeof (type), prefix##GreaterThan); \
+		else															\
+			qsort (current->array, current->count, sizeof (type), prefix##LessThan); \
+	}
+
+/* We expect the linker we use is enough clever to delete dead code. */
+impNumArray(char, Char, char);
+impNumArray(uchar, Uchar, unsigned char);
+impNumArray(int, Int, int);
+impNumArray(uint, Uint, unsigned int);
+impNumArray(long, Long, long);
+impNumArray(ulong, Ulong, unsigned long);


Modified: ctags/main/numarray.h
48 lines changed, 48 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,48 @@
+/*
+*   Copyright (c) 1999-2002, Darren Hiebert
+*
+*   This source code is released for free distribution under the terms of the
+*   GNU General Public License version 2 or (at your option) any later version.
+*
+*   Defines external interface to resizable pointer arrays.
+*/
+#ifndef CTAGS_MAIN_NUMARRAY_H
+#define CTAGS_MAIN_NUMARRAY_H
+
+/*
+*   INCLUDE FILES
+*/
+#include "general.h"  /* must always come first */
+
+
+#define declNumArray(prefix,Prefix,type)								\
+																		\
+	struct s##Prefix##Array;											\
+	typedef struct s##Prefix##Array prefix##Array;						\
+																		\
+	extern prefix##Array *prefix##ArrayNew (void);						\
+	extern void prefix##ArrayAdd (prefix##Array *const current, type num); \
+	extern void prefix##ArrayRemoveLast (prefix##Array *const current);	\
+	extern void prefix##ArrayCombine (prefix##Array *const current, prefix##Array *const from);	\
+	extern void prefix##ArrayClear (prefix##Array *const current);		\
+	extern unsigned int prefix##ArrayCount (const prefix##Array *const current); \
+	extern type prefix##ArrayItem (const prefix##Array *const current, const unsigned int indx); \
+	extern type prefix##ArrayLast (const prefix##Array *const current); \
+	extern void prefix##ArrayDelete (prefix##Array *const current);		\
+	extern bool prefix##ArrayHasTest (const prefix##Array *const current, \
+									  bool (*test)(const type num, void *userData), \
+									  void *userData);					\
+	extern bool prefix##ArrayHas (const prefix##Array *const current, type num); \
+	extern void prefix##ArrayReverse (const prefix##Array *const current); \
+	extern void prefix##ArrayDeleteItem (prefix##Array* const current, unsigned int indx); \
+	\
+	extern void prefix##ArraySort (prefix##Array *const current, bool descendingOrder);
+
+declNumArray(char, Char, char);
+declNumArray(uchar, Uchar, unsigned char);
+declNumArray(int, Int, int);
+declNumArray(uint, Uint, unsigned int);
+declNumArray(long, Long, long);
+declNumArray(ulong, Ulong, unsigned long);
+
+#endif  /* CTAGS_MAIN_NUMARRAY_H */


Modified: ctags/main/objpool.c
7 lines changed, 5 insertions(+), 2 deletions(-)
===================================================================
@@ -26,20 +26,23 @@ struct sObjPool {
 	objPoolCreateFunc createFunc;
 	objPoolDeleteFunc deleteFunc;
 	objPoolClearFunc clearFunc;
+	void *createArg;
 };
 
 /*
 *   FUNCTION DEFINITIONS
 */
 extern objPool *objPoolNew (unsigned int size,
-	objPoolCreateFunc createFunc, objPoolDeleteFunc deleteFunc, objPoolClearFunc clearFunc)
+	objPoolCreateFunc createFunc, objPoolDeleteFunc deleteFunc, objPoolClearFunc clearFunc,
+	void *createArg)
 {
 	objPool* const result = xMalloc (1, objPool);
 	result->array = ptrArrayNew (deleteFunc);
 	result->size = size;
 	result->createFunc = createFunc;
 	result->deleteFunc = deleteFunc;
 	result->clearFunc = clearFunc;
+	result->createArg = createArg;
 	return result;
 }
 
@@ -59,7 +62,7 @@ extern void *objPoolGet (objPool *pool)
 		ptrArrayRemoveLast (pool->array);
 	}
 	else
-		obj = pool->createFunc ();
+		obj = pool->createFunc (pool->createArg);
 
 	if (pool->clearFunc)
 		pool->clearFunc (obj);


Modified: ctags/main/objpool.h
5 lines changed, 3 insertions(+), 2 deletions(-)
===================================================================
@@ -20,7 +20,7 @@
 /*
 *   DATA DECLARATIONS
 */
-typedef void * (*objPoolCreateFunc) (void);
+typedef void * (*objPoolCreateFunc) (void *createArg);
 typedef void (*objPoolDeleteFunc) (void *data);
 typedef void (*objPoolClearFunc) (void *data);
 
@@ -31,7 +31,8 @@ typedef struct sObjPool objPool;
 *   FUNCTION PROTOTYPES
 */
 extern objPool *objPoolNew (unsigned int size,
-	objPoolCreateFunc createFunc, objPoolDeleteFunc deleteFunc, objPoolClearFunc clearFunc);
+	objPoolCreateFunc createFunc, objPoolDeleteFunc deleteFunc, objPoolClearFunc clearFunc,
+	void *createArg);
 extern void objPoolDelete (objPool *pool);
 extern void *objPoolGet (objPool *pool);
 extern void objPoolPut (objPool *pool, void *obj);


Modified: ctags/main/options.c
11 lines changed, 8 insertions(+), 3 deletions(-)
===================================================================
@@ -1759,7 +1759,7 @@ static void processListExtraOption (
 	exit (0);
 }
 
-static void processListFileKindOption (
+static void processListFileKindDefinition (
 		const char *const option, const char *const parameter)
 {
 	if (parameter [0] == '\0' || strcasecmp (parameter, "all") == 0)
@@ -2556,7 +2556,7 @@ static parametricOption ParametricOptions [] = {
 	{ "list-extra",             processListExtraOption,        true,   STAGE_ANY },
 	{ "list-features",          processListFeaturesOption,      true,   STAGE_ANY },
 	{ "list-fields",            processListFieldsOption,        true,   STAGE_ANY },
-	{ "list-file-kind",         processListFileKindOption,      true,   STAGE_ANY },
+	{ "list-file-kind",         processListFileKindDefinition,  true,   STAGE_ANY },
 	{ "list-kinds",             processListKindsOption,         true,   STAGE_ANY },
 	{ "list-kinds-full",        processListKindsOption,         true,   STAGE_ANY },
 	{ "list-languages",         processListLanguagesOption,     true,   STAGE_ANY },
@@ -2816,7 +2816,7 @@ static void processLongOption (
 		 ;
 	else if (processParametricOption (option, parameter))
 		;
-	else if (processKindOption (option, parameter))
+	else if (processKindDefinition (option, parameter))
 		;
 	else if (processAliasOption (option, parameter))
 		;
@@ -3484,3 +3484,8 @@ extern void verbose (const char *const format, ...)
 {
 }
 /* GEANY DIFF END */
+
+extern bool canUseLineNumberAsLocator (void)
+{
+	return (Option.locate != EX_PATTERN);
+}


Modified: ctags/main/options.h
5 lines changed, 4 insertions(+), 1 deletions(-)
===================================================================
@@ -180,7 +180,7 @@ extern langType getLanguageComponentInOption (const char *const option,
 
 extern void processLanguageDefineOption (const char *const option, const char *const parameter);
 extern bool processMapOption (const char *const option, const char *const parameter);
-extern bool processKindOption (const char *const option, const char *const parameter);
+extern bool processKindDefinition (const char *const option, const char *const parameter);
 extern bool processCorpusOption (const char *const option, const char *const parameter);
 extern bool processAliasOption (const char *const option, const char *const parameter);
 #ifdef HAVE_ICONV
@@ -192,4 +192,7 @@ extern bool processXcmdOption (const char *const option, const char *const param
 typedef void (* mainLoopFunc) (cookedArgs *args, void *data);
 extern void setMainLoop (mainLoopFunc func, void *data);
 
+/* This is for emitting a tag for a commnn block of Fortran parser*/
+extern bool canUseLineNumberAsLocator (void);
+
 #endif  /* CTAGS_MAIN_OPTIONS_H */


Modified: ctags/main/parse.c
213 lines changed, 134 insertions(+), 79 deletions(-)
===================================================================
@@ -27,6 +27,7 @@
 #include "ptag.h"
 #include "read.h"
 #include "routines.h"
+#include "trashbox.h"
 #include "vstring.h"
 #ifdef HAVE_ICONV
 # include "mbcs.h"
@@ -53,6 +54,8 @@ typedef struct {
 	enum specType specType;
 }  parserCandidate;
 
+static ptrArray *parsersUsedInCurrentInput;
+
 /*
  * FUNCTION PROTOTYPES
  */
@@ -63,6 +66,8 @@ static void addParserPseudoTags (langType language);
 static void installKeywordTable (const langType language);
 static void installTagRegexTable (const langType language);
 static void installTagXpathTable (const langType language);
+static void anonResetMaybe (parserDefinition *lang);
+static void clearParsersUsedInCurrentInput (void);
 
 /*
 *   DATA DEFINITIONS
@@ -88,7 +93,7 @@ static parserDefinitionFunc* BuiltInParsers[] = {
 };
 static parserDefinition** LanguageTable = NULL;
 static unsigned int LanguageCount = 0;
-static kindOption defaultFileKind = {
+static kindDefinition defaultFileKind = {
 	.enabled     = false,
 	.letter      = KIND_FILE_DEFAULT,
 	.name        = KIND_FILE_DEFAULT_LONG,
@@ -105,34 +110,35 @@ extern unsigned int countParsers (void)
 }
 
 extern int makeSimpleTag (
-		const vString* const name, kindOption* const kinds, const int kind)
+		const vString* const name, const int kindIndex)
 {
 	int r = CORK_NIL;
 
-	if (kinds [kind].enabled  &&  name != NULL  &&  vStringLength (name) > 0)
+	if (isInputLanguageKindEnabled(kindIndex)  &&  name != NULL  &&  vStringLength (name) > 0)
 	{
 		tagEntryInfo e;
-		initTagEntry (&e, vStringValue (name), & kinds [kind]);
+		initTagEntry (&e, vStringValue (name), kindIndex);
 
 		r = makeTagEntry (&e);
 	}
 	return r;
 }
 
-extern int makeSimpleRefTag (const vString* const name, kindOption* const kinds, const int kind,
+extern int makeSimpleRefTag (const vString* const name, const int kindIndex,
 			     int roleIndex)
 {
 	int r = CORK_NIL;
 
 	if (! isXtagEnabled (XTAG_REFERENCE_TAGS))
 		return r;
 
-	Assert (roleIndex < kinds[kind].nRoles);
+	Assert (roleIndex < countInputLanguageRoles(kindIndex));
 
-	if (kinds[kind].roles[roleIndex].enabled)
+	/* do not check for kind being disabled - that happens later in makeTagEntry() */
+	if (name != NULL  &&  vStringLength (name) > 0)
 	{
 	    tagEntryInfo e;
-	    initRefTagEntry (&e, vStringValue (name), & kinds [kind], roleIndex);
+	    initRefTagEntry (&e, vStringValue (name), kindIndex, roleIndex);
 
 	    r = makeTagEntry (&e);
 	}
@@ -151,7 +157,7 @@ extern bool isLanguageEnabled (const langType language)
 
 	if ((lang->method & METHOD_XCMD) &&
 		 (!(lang->method & METHOD_XCMD_AVAILABLE)) &&
-		 (lang->kinds == NULL) &&
+		 (lang->kindTable == NULL) &&
 		 (!(lang->method & METHOD_REGEX)) &&
 		 (!(lang->method & METHOD_XPATH)))
 		return false;
@@ -168,11 +174,11 @@ extern parserDefinition* parserNew (const char* name)
 	return parserNewFull (name, 0);
 }
 
-static kindOption* fileKindNew (char letter)
+static kindDefinition* fileKindNew (char letter)
 {
-	kindOption *fileKind;
+	kindDefinition *fileKind;
 
-	fileKind = xMalloc (1, kindOption);
+	fileKind = xMalloc (1, kindDefinition);
 	*(fileKind) = defaultFileKind;
 	fileKind->letter = letter;
 	return fileKind;
@@ -216,9 +222,9 @@ extern const char *getLanguageName (const langType language)
 	return result;
 }
 
-extern kindOption* getLanguageFileKind (const langType language)
+extern kindDefinition* getLanguageFileKind (const langType language)
 {
-	kindOption* kind;
+	kindDefinition* kind;
 
 	Assert (0 <= language  &&  language < (int) LanguageCount);
 
@@ -229,6 +235,13 @@ extern kindOption* getLanguageFileKind (const langType language)
 	return kind;
 }
 
+extern kindDefinition* getLanguageKind (const langType language, int kindIndex)
+{
+	Assert (0 <= language  &&  language < (int) LanguageCount);
+
+	return (LanguageTable [language]->kindTable) + kindIndex;
+}
+
 extern langType getNamedLanguage (const char *const name, size_t len)
 {
 	langType result = LANG_IGNORE;
@@ -724,7 +737,7 @@ struct getLangCtx {
 		    (mio_memory_get_data((_glc_)->input, NULL) == NULL)) \
 		{							\
 			MIO *tmp_ = (_glc_)->input;			\
-			(_glc_)->input = mio_new_mio (tmp_, 0, 0);	\
+			(_glc_)->input = mio_new_mio (tmp_, 0, -1);	\
 			mio_free (tmp_);				\
 			if (!(_glc_)->input) {				\
 				(_glc_)->err = true;			\
@@ -1148,6 +1161,28 @@ extern langType getFileLanguage (const char *const fileName)
 	return getFileLanguageAndKeepMIO(fileName, NULL);
 }
 
+extern langType getLanguageForCommand (const char *const command, langType startFrom)
+{
+	const char *const tmp_command = baseFilename (command);
+	char *tmp_spec;
+	enum specType tmp_specType;
+
+	return getNameOrAliasesLanguageAndSpec (tmp_command, startFrom,
+											(const char **const)&tmp_spec,
+											&tmp_specType);
+}
+
+extern langType getLanguageForFilename (const char *const filename, langType startFrom)
+{
+	const char *const tmp_filename = baseFilename (filename);
+	char *tmp_spec;
+	enum specType tmp_specType;
+
+	return getPatternLanguageAndSpec (tmp_filename, startFrom,
+									  (const char **const)&tmp_spec,
+									  &tmp_specType);
+}
+
 typedef void (*languageCallback)  (langType language, void* user_data);
 static void foreachLanguage(languageCallback callback, void *user_data)
 {
@@ -1384,21 +1419,21 @@ static bool doesParserUseKind (const parserDefinition *const parser, char letter
 }
 #endif
 
-static void installFieldSpec (const langType language)
+static void installFieldDefinition (const langType language)
 {
 	unsigned int i;
 	parserDefinition * parser;
 
 	Assert (0 <= language  &&  language < (int) LanguageCount);
 	parser = LanguageTable [language];
-	if (parser->fieldSpecCount > PRE_ALLOCATED_PARSER_FIELDS)
+	if (parser->fieldCount > PRE_ALLOCATED_PARSER_FIELDS)
 		error (FATAL,
 		       "INTERNAL ERROR: in a parser, fields are defined more than PRE_ALLOCATED_PARSER_FIELDS\n");
 
-	if (parser->fieldSpecs != NULL)
+	if (parser->fieldTable != NULL)
 	{
-		for (i = 0; i < parser->fieldSpecCount; i++)
-			defineField (& parser->fieldSpecs [i], language);
+		for (i = 0; i < parser->fieldCount; i++)
+			defineField (& parser->fieldTable [i], language);
 	}
 }
 
@@ -1415,7 +1450,7 @@ static void initializeParserOne (langType lang)
 	installKeywordTable (lang);
 	installTagRegexTable (lang);
 	installTagXpathTable (lang);
-	installFieldSpec     (lang);
+	installFieldDefinition     (lang);
 
 	if (hasScopeActionInRegex (lang)
 	    || parser->requestAutomaticFQTag)
@@ -1613,45 +1648,36 @@ extern void processLanguageDefineOption (
 	}
 }
 
-static kindOption *langKindOption (const langType language, const int flag)
+static kindDefinition *langKindDefinition (const langType language, const int flag)
 {
 	unsigned int i;
-	kindOption* result = NULL;
+	kindDefinition* result = NULL;
 	const parserDefinition* lang;
 	Assert (0 <= language  &&  language < (int) LanguageCount);
 	lang = LanguageTable [language];
 	for (i=0  ;  i < lang->kindCount  &&  result == NULL  ;  ++i)
-		if (lang->kinds [i].letter == flag)
-			result = &lang->kinds [i];
+		if (lang->kindTable [i].letter == flag)
+			result = &lang->kindTable [i];
 	return result;
 }
 
-static kindOption *langKindLongOption (const langType language, const char *kindLong)
+static kindDefinition *langKindLongOption (const langType language, const char *kindLong)
 {
 	unsigned int i;
-	kindOption* result = NULL;
+	kindDefinition* result = NULL;
 	const parserDefinition* lang;
 	Assert (0 <= language  &&  language < (int) LanguageCount);
 	lang = LanguageTable [language];
 	for (i=0  ;  i < lang->kindCount  &&  result == NULL  ;  ++i)
-		if (strcmp (lang->kinds [i].name, kindLong) == 0)
-			result = &lang->kinds [i];
+		if (strcmp (lang->kindTable [i].name, kindLong) == 0)
+			result = &lang->kindTable [i];
 	return result;
 }
 
-extern bool isLanguageKindEnabled (const langType language, char kind)
+extern bool isLanguageKindEnabled (const langType language, int kindIndex)
 {
-	const kindOption *kindOpt;
-
-	if (hasRegexKind (language, kind))
-		return isRegexKindEnabled (language, kind);
-	else if (hasXcmdKind (language, kind))
-		return isXcmdKindEnabled (language, kind);
-
-	kindOpt = langKindOption (language, kind);
-	Assert (kindOpt);
-
-	return kindOpt->enabled;
+	kindDefinition * kdef = getLanguageKind (language, kindIndex);
+	return kdef->enabled;
 }
 
 
@@ -1666,15 +1692,15 @@ static void resetLanguageKinds (const langType language, const bool mode)
 	{
 		unsigned int i;
 		for (i = 0  ;  i < lang->kindCount  ;  ++i)
-			enableKind (lang->kinds + i, mode);
+			enableKind (lang->kindTable + i, mode);
 	}
 }
 
 static bool enableLanguageKind (
 		const langType language, const int kind, const bool mode)
 {
 	bool result = false;
-	kindOption* const opt = langKindOption (language, kind);
+	kindDefinition* const opt = langKindDefinition (language, kind);
 	if (opt != NULL)
 	{
 		enableKind (opt, mode);
@@ -1689,7 +1715,7 @@ static bool enableLanguageKindLong (
 	const langType language, const char * const kindLong, const bool mode)
 {
 	bool result = false;
-	kindOption* const opt = langKindLongOption (language, kindLong);
+	kindDefinition* const opt = langKindLongOption (language, kindLong);
 	if (opt != NULL)
 	{
 		enableKind (opt, mode);
@@ -1700,7 +1726,7 @@ static bool enableLanguageKindLong (
 	return result;
 }
 
-static void processLangKindOption (
+static void processLangKindDefinition (
 		const langType language, const char *const option,
 		const char *const parameter)
 {
@@ -1777,25 +1803,25 @@ static void processLangKindOption (
 	}
 }
 
-struct langKindOptionStruct {
+struct langKindDefinitionStruct {
 	const char *const option;
 	const char *const parameter;
 };
-static void processLangKindOptionEach(
+static void processLangKindDefinitionEach(
 	langType lang, void* user_data)
 {
-	struct langKindOptionStruct *arg = user_data;
-	processLangKindOption (lang, arg->option, arg->parameter);
+	struct langKindDefinitionStruct *arg = user_data;
+	processLangKindDefinition (lang, arg->option, arg->parameter);
 }
 
-extern bool processKindOption (
+extern bool processKindDefinition (
 		const char *const option, const char *const parameter)
 {
 #define PREFIX "kinds-"
 #define PREFIX_LEN strlen(PREFIX)
 
 	bool handled = false;
-	struct langKindOptionStruct arg = {
+	struct langKindDefinitionStruct arg = {
 		.option = option,
 		.parameter = parameter,
 	};
@@ -1808,7 +1834,7 @@ extern bool processKindOption (
 		size_t len = dash - option;
 
 		if ((len == 1) && (*option == '*'))
-			foreachLanguage(processLangKindOptionEach, &arg);
+			foreachLanguage(processLangKindDefinitionEach, &arg);
 		else
 		{
 			vString* langName = vStringNew ();
@@ -1817,7 +1843,7 @@ extern bool processKindOption (
 			if (language == LANG_IGNORE)
 				error (WARNING, "Unknown language \"%s\" in \"%s\" option", vStringValue (langName), option);
 			else
-				processLangKindOption (language, option, parameter);
+				processLangKindDefinition (language, option, parameter);
 			vStringDelete (langName);
 		}
 		handled = true;
@@ -1833,7 +1859,7 @@ extern bool processKindOption (
 			error (WARNING, "No language given in \"%s\" option", option);
 		else if (len == 1 && lang[0] == '*')
 		{
-			foreachLanguage(processLangKindOptionEach, &arg);
+			foreachLanguage(processLangKindDefinitionEach, &arg);
 			handled = true;
 		}
 		else
@@ -1843,7 +1869,7 @@ extern bool processKindOption (
 				error (WARNING, "Unknown language \"%s\" in \"%s\" option", lang, option);
 			else
 			{
-				processLangKindOption (language, option, parameter);
+				processLangKindDefinition (language, option, parameter);
 				handled = true;
 			}
 		}
@@ -1865,15 +1891,15 @@ static void printRoles (const langType language, const char* letters, bool allow
 	for (c = letters; *c != '\0'; c++)
 	{
 		unsigned int i;
-		const kindOption *k;
+		const kindDefinition *k;
 
 		for (i = 0; i < lang->kindCount; ++i)
 		{
-			k = lang->kinds + i;
+			k = lang->kindTable + i;
 			if (*c == KIND_WILDCARD || k->letter == *c)
 			{
 				int j;
-				const roleDesc *r;
+				const roleDefinition *r;
 
 				for (j = 0; j < k->nRoles; j++)
 				{
@@ -1925,14 +1951,14 @@ static void printKinds (langType language, bool allKindFields, bool indent)
 
 	initializeParser (language);
 	lang = LanguageTable [language];
-	if (lang->kinds != NULL)
+	if (lang->kindTable != NULL)
 	{
 		unsigned int i;
 		for (i = 0  ;  i < lang->kindCount  ;  ++i)
 		{
 			if (allKindFields && indent)
 				printf (Option.machinable? "%s": PR_KIND_FMT (LANG,s), lang->name);
-			printKind (lang->kinds + i, allKindFields, indent, Option.machinable);
+			printKind (lang->kindTable + i, allKindFields, indent, Option.machinable);
 		}
 	}
 	printRegexKinds (language, allKindFields, indent, Option.machinable);
@@ -2095,7 +2121,7 @@ static void printLanguage (const langType language, parserDefinition** ltable)
 	if (lang->method & METHOD_XCMD)
 		initializeParser (lang->id);
 
-	if (lang->kinds != NULL  ||  (lang->method & METHOD_REGEX) || (lang->method & METHOD_XCMD))
+	if (lang->kindTable != NULL  ||  (lang->method & METHOD_REGEX) || (lang->method & METHOD_XCMD))
 		printf ("%s%s\n", lang->name, isLanguageEnabled (lang->id) ? "" : " [disabled]");
 }
 
@@ -2153,6 +2179,8 @@ static bool createTagsWithFallback1 (const langType language)
 	addParserPseudoTags (language);
 	tagFilePosition (&tagfpos);
 
+	anonResetMaybe (LanguageTable [language]);
+
 	while ( ( whyRescan =
 		  createTagsForFile (language, ++passCount) )
 		!= RESCAN_NONE)
@@ -2199,6 +2227,8 @@ static bool createTagsWithFallback1 (const langType language,
 	if (LanguageTable [language]->useCork)
 		corkTagFile();
 
+	anonResetMaybe (LanguageTable [language]);
+
 	passCallback(userData);
 	while ( ( whyRescan =
 		  createTagsForFile (language, ++passCount) )
@@ -2284,10 +2314,13 @@ extern void createTagsWithFallback(unsigned char *buffer, size_t bufferSize,
 	if ((!buffer && openInputFile (fileName, language, NULL)) ||
 		(buffer && bufferOpen (fileName, language, buffer, bufferSize)))
 	{
+		initParserTrashBox ();
+		clearParsersUsedInCurrentInput ();
 		setTagEntryFunction(tagCallback, userData);
 		createTagsWithFallback1 (language, passCallback, userData);
 		forcePromises ();
 		closeInputFile ();
+		finiParserTrashBox ();
 	}
 	else
 		error (WARNING, "Unable to open %s", fileName);
@@ -2459,6 +2492,9 @@ extern bool parseFile (const char *const fileName)
 #endif
 
 		setupWriter ();
+
+		clearParsersUsedInCurrentInput ();
+
 #ifndef CTAGS_LIB
 		tagFileResized = createTagsWithFallback (fileName, language, mio);
 #endif
@@ -2581,15 +2617,15 @@ extern bool makeKindSeparatorsPseudoTags (const langType language,
 					     const ptagDesc *pdesc)
 {
 	parserDefinition* lang;
-	kindOption *kinds;
+	kindDefinition *kinds;
 	unsigned int kindCount;
 	unsigned int i, j;
 
 	bool r = false;
 
 	Assert (0 <= language  &&  language < (int) LanguageCount);
 	lang = LanguageTable [language];
-	kinds = lang->kinds;
+	kinds = lang->kindTable;
 	kindCount = lang->kindCount;
 
 	if (kinds == NULL)
@@ -2605,17 +2641,17 @@ extern bool makeKindSeparatorsPseudoTags (const langType language,
 		for (j = 0; j < kinds[i].separatorCount; ++j)
 		{
 			char name[5] = {[0] = '/', [3] = '/', [4] = '\0'};
-			const kindOption *upperKind;
+			const kindDefinition *upperKind;
 			const scopeSeparator *sep;
 
 			sep = kinds[i].separators + j;
 
-			if (sep->parentLetter == KIND_WILDCARD)
+			if (sep->parentKindIndex == KIND_WILDCARD_INDEX)
 			{
 				name[1] = KIND_WILDCARD;
 				name[2] = kinds[i].letter;
 			}
-			else if (sep->parentLetter == KIND_NULL)
+			else if (sep->parentKindIndex == KIND_GHOST_INDEX)
 			{
 				/* This is root separator: no upper item is here. */
 				name[1] = kinds[i].letter;
@@ -2624,8 +2660,8 @@ extern bool makeKindSeparatorsPseudoTags (const langType language,
 			}
 			else
 			{
-				upperKind = langKindOption (language,
-							    sep->parentLetter);
+				upperKind = langKindDefinition (language,
+							    sep->parentKindIndex);
 				if (!upperKind)
 					continue;
 
@@ -2651,7 +2687,7 @@ struct makeKindDescriptionPseudoTagData {
 	bool written;
 };
 
-static bool makeKindDescriptionPseudoTag (kindOption *kind,
+static bool makeKindDescriptionPseudoTag (kindDefinition *kind,
 					     void *user_data)
 {
 	struct makeKindDescriptionPseudoTagData *data = user_data;
@@ -2685,13 +2721,13 @@ extern bool makeKindDescriptionsPseudoTags (const langType language,
 {
 
 	parserDefinition* lang;
-	kindOption *kinds;
+	kindDefinition *kinds;
 	unsigned int kindCount, i;
 	struct makeKindDescriptionPseudoTagData data;
 
 	Assert (0 <= language  &&  language < (int) LanguageCount);
 	lang = LanguageTable [language];
-	kinds = lang->kinds;
+	kinds = lang->kindTable;
 	kindCount = lang->kindCount;
 
 	data.langName = lang->name;
@@ -2716,12 +2752,25 @@ extern bool makeKindDescriptionsPseudoTags (const langType language,
 *   Anonymous name generator
 */
 
-extern void anonReset (void)
+static void clearParsersUsedInCurrentInput (void)
 {
-	parserDefinition* lang = LanguageTable [getInputLanguage ()];
+	if (parsersUsedInCurrentInput)
+		ptrArrayClear (parsersUsedInCurrentInput);
+	else
+		parsersUsedInCurrentInput = ptrArrayNew (NULL);
+}
+
+static void anonResetMaybe (parserDefinition *lang)
+{
+	if (ptrArrayHas (parsersUsedInCurrentInput, lang))
+		return;
+
 	lang -> anonumousIdentiferId = 0;
+	ptrArrayAdd (parsersUsedInCurrentInput, lang);
 }
 
+/* GEANY DIFF */
+#if 0
 static unsigned int anonHash(const unsigned char *str)
 {
 	unsigned int hash = 5381;
@@ -2732,6 +2781,8 @@ static unsigned int anonHash(const unsigned char *str)
 
 	return hash ;
 }
+#endif
+/* GEANY DIFF END */
 
 extern void anonGenerate (vString *buffer, const char *prefix, int kind)
 {
@@ -2742,8 +2793,12 @@ extern void anonGenerate (vString *buffer, const char *prefix, int kind)
 
 	vStringCopyS(buffer, prefix);
 
-	unsigned int uHash = anonHash((const unsigned char *)getInputFileName());
-	sprintf(szNum,"%08x%02x%02x",uHash,lang -> anonumousIdentiferId, kind);
+/* GEANY DIFF */
+/*	unsigned int uHash = anonHash((const unsigned char *)getInputFileName());
+	sprintf(szNum,"%08x%02x%02x",uHash,lang -> anonumousIdentiferId, kind); */
+	sprintf(szNum,"%u", lang -> anonumousIdentiferId);
+/* GEANY DIFF END */
+
 	vStringCatS(buffer,szNum);
 }
 
@@ -2760,11 +2815,11 @@ typedef enum {
 	R_BROKEN_REF,
 } CTST_BrokenRole;
 
-static roleDesc CTST_BrokenRoles [] = {
+static roleDefinition CTST_BrokenRoles [] = {
 	{true, "broken", "broken" },
 };
 
-static kindOption CTST_Kinds[KIND_COUNT] = {
+static kindDefinition CTST_Kinds[KIND_COUNT] = {
 	{true, 'b', "broken tag", "name with unwanted characters",
 	 .referenceOnly = false, ATTACH_ROLES (CTST_BrokenRoles) },
 };
@@ -2785,7 +2840,7 @@ static void createCTSTTags (void)
 				switch (i)
 				{
 					case K_BROKEN:
-						initTagEntry (&e, "one\nof\rbroken\tname", &CTST_Kinds[i]);
+						initTagEntry (&e, "one\nof\rbroken\tname", i);
 						e.extensionFields.scopeKind = & (CTST_Kinds [K_BROKEN]);
 						e.extensionFields.scopeName = "\\Broken\tContext";
 						makeTagEntry (&e);
@@ -2801,7 +2856,7 @@ static parserDefinition *CTagsSelfTestParser (void)
 	static const char *const extensions[] = { NULL };
 	parserDefinition *const def = parserNew ("CTagsSelfTest");
 	def->extensions = extensions;
-	def->kinds = CTST_Kinds;
+	def->kindTable = CTST_Kinds;
 	def->kindCount = KIND_COUNT;
 	def->parser = createCTSTTags;
 	def->invisible = true;


Modified: ctags/main/parse.h
26 lines changed, 14 insertions(+), 12 deletions(-)
===================================================================
@@ -127,9 +127,9 @@ typedef struct {
 struct sParserDefinition {
 	/* defined by parser */
 	char* name;                    /* name of language */
-	kindOption* kinds;             /* tag kinds handled by parser */
+	kindDefinition* kindTable;     /* tag kinds handled by parser */
 	unsigned int kindCount;        /* size of `kinds' list */
-	kindOption* fileKind;          /* kind for overriding the default fileKind */
+	kindDefinition* fileKind;      /* kind for overriding the default fileKind */
 	const char *const *extensions; /* list of default extensions */
 	const char *const *patterns;   /* list of default file name patterns */
 	const char *const *aliases;    /* list of default aliases (alternative names) */
@@ -149,8 +149,8 @@ struct sParserDefinition {
 	tagXpathTableTable *tagXpathTableTable;
 	unsigned int tagXpathTableCount;
 	bool invisible;
-	fieldSpec *fieldSpecs;
-	unsigned int fieldSpecCount;
+	fieldDefinition *fieldTable;
+	unsigned int fieldCount;
 
 	parserDependency * dependencies;
 	unsigned int dependencyCount;
@@ -204,19 +204,22 @@ extern parserDefinitionFunc YAML_PARSER_LIST;
 
 
 /* Language processing and parsing */
-extern int makeSimpleTag (const vString* const name, kindOption* const kinds, const int kind);
-extern int makeSimpleRefTag (const vString* const name, kindOption* const kinds, const int kind,
+extern int makeSimpleTag (const vString* const name, const int kind);
+extern int makeSimpleRefTag (const vString* const name, const int kindIndexS,
 			     int roleIndex);
 extern parserDefinition* parserNew (const char* name);
 extern parserDefinition* parserNewFull (const char* name, char fileKind);
+extern kindDefinition* getLanguageKind(const langType language, int kindIndex);
 extern bool doesLanguageAllowNullTag (const langType language);
 extern bool doesLanguageRequestAutomaticFQTag (const langType language);
 extern const char *getLanguageName (const langType language);
-extern kindOption* getLanguageFileKind (const langType language);
+extern kindDefinition* getLanguageFileKind (const langType language);
 extern langType getNamedLanguage (const char *const name, size_t len);
 extern langType getFileLanguage (const char *const fileName);
+extern langType getLanguageForCommand (const char *const command, langType startFrom);
+extern langType getLanguageForFilename (const char *const filename, langType startFrom);
 extern bool isLanguageEnabled (const langType language);
-extern bool isLanguageKindEnabled (const langType language, char kind);
+extern bool isLanguageKindEnabled (const langType language, int kindIndex);
 
 extern void installLanguageMapDefault (const langType language);
 extern void installLanguageMapDefaults (void);
@@ -282,7 +285,7 @@ extern bool isRegexKindEnabled (const langType language, const int kind);
 extern bool hasRegexKind (const langType language, const int kind);
 extern void printRegexKinds (const langType language, bool allKindFields, bool indent,
 			     bool tabSeparated);
-extern void foreachRegexKinds (const langType language, bool (* func) (kindOption*, void*), void *data);
+extern void foreachRegexKinds (const langType language, bool (* func) (kindDefinition*, void*), void *data);
 extern void freeRegexResources (void);
 extern bool checkRegex (void);
 extern void useRegexMethod (const langType language);
@@ -301,15 +304,15 @@ extern bool isXcmdKindEnabled (const langType language, const int kind);
 extern bool hasXcmdKind (const langType language, const int kind);
 extern void printXcmdKinds (const langType language, bool allKindFields, bool indent,
 			    bool tabSeparated);
-extern void foreachXcmdKinds (const langType language, bool (* func) (kindOption*, void*), void *data);
+extern void foreachXcmdKinds (const langType language, bool (* func) (kindDefinition*, void*), void *data);
 extern void freeXcmdResources (void);
 extern void useXcmdMethod (const langType language);
 extern void notifyAvailabilityXcmdMethod (const langType language);
 
 /* Xpath interface */
 extern void findXMLTags (xmlXPathContext *ctx, xmlNode *root,
 			 const tagXpathTableTable *xpathTableTable,
-			 const kindOption* const kinds, void *userData);
+			 const kindDefinition* const kinds, void *userData);
 extern void addTagXpath (const langType language, tagXpathTable *xpathTable);
 
 
@@ -318,7 +321,6 @@ extern bool makeKindSeparatorsPseudoTags (const langType language,
 extern bool makeKindDescriptionsPseudoTags (const langType language,
 					       const ptagDesc *pdesc);
 
-extern void anonReset (void);
 extern void anonGenerate (vString *buffer, const char *prefix, int kind);
 
 #endif  /* CTAGS_MAIN_PARSE_H */


Modified: ctags/main/parsers.h
8 lines changed, 4 insertions(+), 4 deletions(-)
===================================================================
@@ -23,7 +23,7 @@
 	PerlParser, \
 	PhpParser, \
 	PythonParser, \
-	LaTeXParser, \
+	TexParser, \
 	AsmParser, \
 	ConfParser, \
 	SqlParser, \
@@ -42,13 +42,13 @@
 	JavaScriptParser, \
 	HaskellParser, \
 	CsharpParser, \
-	FreeBasicParser,\
+	BasicParser,\
 	HaxeParser,\
-	RestParser, \
+	RstParser, \
 	HtmlParser, \
 	F77Parser, \
 	GLSLParser, \
-	MatlabParser, \
+	MatLabParser, \
 	ValaParser, \
 	ActionScriptParser, \
 	NsisParser, \


Modified: ctags/main/promise.c
4 lines changed, 4 insertions(+), 0 deletions(-)
===================================================================
@@ -38,8 +38,12 @@ int  makePromise   (const char *parser,
 	int r;
 	langType lang;
 
+/* GEANY DIFF */
+/*
 	if (!isXtagEnabled (XTAG_TAGS_GENERATED_BY_SUB_PARSERS))
 		return -1;
+*/
+/* GEANY DIFF END */
 
 	lang = getNamedLanguage (parser, 0);
 	if (lang == LANG_IGNORE)


Modified: ctags/main/ptrarray.c
28 lines changed, 28 insertions(+), 0 deletions(-)
===================================================================
@@ -13,9 +13,11 @@
 #include "general.h"  /* must always come first */
 
 #include <string.h>
+#include <stdlib.h>
 
 #include "debug.h"
 #include "ptrarray.h"
+#include "routines.h"
 
 /*
 *   DATA DECLARATIONS
@@ -125,6 +127,16 @@ extern bool ptrArrayHasTest (const ptrArray *const current,
 	return result;
 }
 
+static bool ptrEq (const void *ptr, void *userData)
+{
+	return (ptr == userData);
+}
+
+extern bool ptrArrayHas (const ptrArray *const current, void *ptr)
+{
+	return ptrArrayHasTest (current, ptrEq, ptr);
+}
+
 extern void ptrArrayReverse (const ptrArray *const current)
 {
 	unsigned int i, j;
@@ -150,3 +162,19 @@ extern void ptrArrayDeleteItem (ptrArray* const current, unsigned int indx)
 			(current->count - indx) * sizeof (*current->array));
 	--current->count;
 }
+
+static int (*ptrArraySortCompareVar)(const void *, const void *);
+
+static int ptrArraySortCompare(const void *a0, const void *b0)
+{
+	void *const *a = (void *const *)a0;
+	void *const *b = (void *const *)b0;
+
+	return ptrArraySortCompareVar (*a, *b);
+}
+
+extern void ptrArraySort (ptrArray *const current, int (*compare)(const void *, const void *))
+{
+	ptrArraySortCompareVar = compare;
+	qsort (current->array, current->count, sizeof (void *), ptrArraySortCompare);
+}


Modified: ctags/main/ptrarray.h
6 lines changed, 4 insertions(+), 2 deletions(-)
===================================================================
@@ -13,6 +13,7 @@
 *   INCLUDE FILES
 */
 #include "general.h"  /* must always come first */
+#include "types.h"
 
 /*
 *   DATA DECLARATIONS
@@ -21,7 +22,6 @@
 typedef void (*ptrArrayDeleteFunc) (void *data);
 
 struct sPtrArray;
-typedef struct sPtrArray ptrArray;
 
 /*
 *   FUNCTION PROTOTYPES
@@ -36,11 +36,13 @@ extern unsigned int ptrArrayCount (const ptrArray *const current);
 extern void* ptrArrayItem (const ptrArray *const current, const unsigned int indx);
 extern void* ptrArrayLast (const ptrArray *const current);
 extern void ptrArrayDelete (ptrArray *const current);
-extern bool ptrArrayHasInsensitive (const ptrArray *const current, const void *const ptr);
 extern bool ptrArrayHasTest (const ptrArray *const current,
 				  bool (*test)(const void *ptr, void *userData),
 				  void *userData);
+extern bool ptrArrayHas (const ptrArray *const current, void *ptr);
 extern void ptrArrayReverse (const ptrArray *const current);
 extern void ptrArrayDeleteItem (ptrArray* const current, unsigned int indx);
 
+extern void ptrArraySort (ptrArray *const current, int (*compare)(const void *, const void *));
+
 #endif  /* CTAGS_MAIN_PTRARRAY_H */


Modified: ctags/main/read.c
12 lines changed, 7 insertions(+), 5 deletions(-)
===================================================================
@@ -108,6 +108,7 @@ typedef struct sInputFile {
 	inputLineFposMap lineFposMap;
 } inputFile;
 
+static langType sourceLang;
 
 /*
 *   FUNCTION DECLARATIONS
@@ -183,17 +184,17 @@ extern bool isInputHeaderFile (void)
 	return File.input.isHeader;
 }
 
-extern bool isInputLanguageKindEnabled (char c)
+extern bool isInputLanguageKindEnabled (int kindIndex)
 {
-	return isLanguageKindEnabled (getInputLanguage (), c);
+	return isLanguageKindEnabled (getInputLanguage (), kindIndex);
 }
 
 extern bool doesInputLanguageAllowNullTag (void)
 {
 	return doesLanguageAllowNullTag (getInputLanguage ());
 }
 
-extern kindOption *getInputLanguageFileKind (void)
+extern kindDefinition *getInputLanguageFileKind (void)
 {
 	return getLanguageFileKind (getInputLanguage ());
 }
@@ -208,9 +209,9 @@ extern const char *getSourceFileTagPath (void)
 	return vStringValue (File.source.tagPath);
 }
 
-extern const char *getSourceLanguageName (void)
+extern langType getSourceLanguage (void)
 {
-	return getLanguageName (File.source.langInfo.type);
+	return sourceLang;
 }
 
 extern unsigned long getSourceLineNumber (void)
@@ -370,6 +371,7 @@ static void setSourceFileParameters (vString *const fileName, const langType lan
 	setInputFileParametersCommon (&File.source, fileName,
 				      language, setLangToType,
 				      File.sourceTagPathHolder);
+	sourceLang = language;
 }
 
 static bool setSourceFileName (vString *const fileName)


Modified: ctags/main/read.h
6 lines changed, 3 insertions(+), 3 deletions(-)
===================================================================
@@ -64,9 +64,9 @@ extern const char *getInputLanguageName (void);
 extern const char *getInputFileTagPath (void);
 extern bool isInputLanguage (langType lang);
 extern bool isI@@ Diff output truncated at 100000 characters. @@

--------------
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