[geany/geany] 7fbe6a: Merge pull request #957 from techee/ctags_hook

Colomban Wendling git-noreply at xxxxx
Fri Jun 10 21:09:09 UTC 2016


Branch:      refs/heads/master
Author:      Colomban Wendling <ban at herbesfolles.org>
Committer:   Colomban Wendling <ban at herbesfolles.org>
Date:        Fri, 10 Jun 2016 21:09:09 UTC
Commit:      7fbe6ad83242fad6ef32ac56e64ab0ff7882e467
             https://github.com/geany/geany/commit/7fbe6ad83242fad6ef32ac56e64ab0ff7882e467

Log Message:
-----------
Merge pull request #957 from techee/ctags_hook

TagManager cleanups


Modified Paths:
--------------
    src/Makefile.am
    src/libmain.c
    tagmanager/Makefile.am
    tagmanager/ctags/Makefile.am
    tagmanager/ctags/actionscript.c
    tagmanager/ctags/asm.c
    tagmanager/ctags/basic.c
    tagmanager/ctags/c.c
    tagmanager/ctags/cobol.c
    tagmanager/ctags/css.c
    tagmanager/ctags/entry.c
    tagmanager/ctags/entry.h
    tagmanager/ctags/erlang.c
    tagmanager/ctags/fortran.c
    tagmanager/ctags/go.c
    tagmanager/ctags/html.c
    tagmanager/ctags/js.c
    tagmanager/ctags/json.c
    tagmanager/ctags/make.c
    tagmanager/ctags/parse.c
    tagmanager/ctags/parse.h
    tagmanager/ctags/pascal.c
    tagmanager/ctags/perl.c
    tagmanager/ctags/php.c
    tagmanager/ctags/python.c
    tagmanager/ctags/r.c
    tagmanager/ctags/ruby.c
    tagmanager/ctags/rust.c
    tagmanager/ctags/sql.c
    tagmanager/ctags/tcl.c
    tagmanager/ctags/verilog.c
    tagmanager/ctags/vhdl.c
    tagmanager/mio/Makefile.am
    tagmanager/src/Makefile.am
    tagmanager/src/tm_ctags_wrappers.c
    tagmanager/src/tm_ctags_wrappers.h
    tagmanager/src/tm_parser.c
    tagmanager/src/tm_parser.h
    tagmanager/src/tm_source_file.c
    tagmanager/src/tm_source_file.h
    tagmanager/src/tm_tag.c
    tagmanager/src/tm_tag.h
    tagmanager/src/tm_tagmanager.h
    tagmanager/src/tm_workspace.c
    tagmanager/src/tm_workspace.h

Modified: src/Makefile.am
2 lines changed, 0 insertions(+), 2 deletions(-)
===================================================================
@@ -120,8 +120,6 @@ libgeany_la_LDFLAGS = @LIBGEANY_LDFLAGS@
 
 libgeany_la_LIBADD = \
 	$(top_builddir)/scintilla/libscintilla.la \
-	$(top_builddir)/tagmanager/ctags/libctags.la \
-	$(top_builddir)/tagmanager/mio/libmio.la \
 	$(top_builddir)/tagmanager/src/libtagmanager.la \
 	@GTK_LIBS@ \
 	@GTHREAD_LIBS@ \


Modified: src/libmain.c
3 lines changed, 2 insertions(+), 1 deletions(-)
===================================================================
@@ -251,7 +251,6 @@ static void main_init(void)
 	file_prefs.tab_order_beside		= FALSE;
 	main_status.quitting			= FALSE;
 	ignore_callback	= FALSE;
-	app->tm_workspace		= tm_get_workspace();
 	ui_prefs.recent_queue				= g_queue_new();
 	ui_prefs.recent_projects_queue		= g_queue_new();
 	main_status.opening_session_files	= FALSE;
@@ -1047,6 +1046,8 @@ gint main_lib(gint argc, gchar **argv)
 #ifdef ENABLE_NLS
 	main_locale_init(utils_resource_dir(RESOURCE_DIR_LOCALE), GETTEXT_PACKAGE);
 #endif
+	/* initialize TM before parsing command-line - needed for tag file generation */
+	app->tm_workspace = tm_get_workspace();
 	parse_command_line_options(&argc, &argv);
 
 #if ! GLIB_CHECK_VERSION(2, 32, 0)


Modified: tagmanager/Makefile.am
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -1,3 +1,3 @@
 ## Process this file with automake to produce Makefile.in
 
-SUBDIRS = ctags mio src
+SUBDIRS = mio ctags src


Modified: tagmanager/ctags/Makefile.am
2 lines changed, 2 insertions(+), 0 deletions(-)
===================================================================
@@ -11,6 +11,8 @@ EXTRA_DIST = \
 
 noinst_LTLIBRARIES = libctags.la
 
+libctags_la_LIBADD = ../mio/libmio.la
+
 parsers = \
 	abaqus.c \
 	abc.c \


Modified: tagmanager/ctags/actionscript.c
4 lines changed, 2 insertions(+), 2 deletions(-)
===================================================================
@@ -50,7 +50,7 @@ static void installActionScriptRegex (const langType language)
 
 	/* Getters and setters */
 	addTagRegex (language, "^[ \t]*[(public|static|internal|final|override)( \t)]*function[ \t]+(set|get)[ \t]+([A-Za-z0-9_]+)[ \t]*\\(",
-		"\\2 \\1", "f,field,fields", NULL);
+		"\\2 \\1", "l,field,fields", NULL);
 
 	/* Variables */
 	addTagRegex (language, "^[ \t]*[(private|public|static|protected|internal)( \t)]*var[ \t]+([A-Za-z0-9_]+)([ \t]*\\:[ \t]*([A-Za-z0-9_]+))*[ \t]*",
@@ -82,7 +82,7 @@ static void installActionScriptRegex (const langType language)
 
 	/* Prototypes (Put this in for AS1 compatibility...) */
     addTagRegex (language, ".*\\.prototype\\.([A-Za-z0-9 ]+)[ \t]*\\=([ \t]*)function( [ \t]?)*\\(",
-	    "\\1", "p,prototype", NULL);
+	    "\\1", "r,prototype", NULL);
 }
 
 /* Create parser definition structure */


Modified: tagmanager/ctags/asm.c
8 lines changed, 4 insertions(+), 4 deletions(-)
===================================================================
@@ -65,10 +65,10 @@ typedef struct {
 static langType Lang_asm;
 
 static kindOption AsmKinds [] = {
-	{ TRUE, 'd', "macro", "defines" },
-	{ TRUE, 'l', "namespace",  "labels"  },
-	{ TRUE, 'm', "function",  "macros"  },
-	{ TRUE, 't', "struct",   "types (structs and records)"   }
+	{ TRUE, 'd', "define", "defines" },
+	{ TRUE, 'l', "label",  "labels"  },
+	{ TRUE, 'm', "macro",  "macros"  },
+	{ TRUE, 't', "type",   "types (structs and records)"   }
 };
 
 static const asmKeyword AsmKeywords [] = {


Modified: tagmanager/ctags/basic.c
8 lines changed, 4 insertions(+), 4 deletions(-)
===================================================================
@@ -39,12 +39,12 @@ typedef struct {
 } KeyWord;
 
 static kindOption BasicKinds[] = {
-	{TRUE, 'c', "macro", "constants"},
+	{TRUE, 'c', "constant", "constants"},
 	{TRUE, 'f', "function", "functions"},
-	{TRUE, 'l', "namespace", "labels"},
-	{TRUE, 't', "struct", "types"},
+	{TRUE, 'l', "label", "labels"},
+	{TRUE, 't', "type", "types"},
 	{TRUE, 'v', "variable", "variables"},
-	{TRUE, 'g', "externvar", "enumerations"}
+	{TRUE, 'g', "enum", "enumerations"}
 };
 
 static KeyWord freebasic_keywords[] = {


Modified: tagmanager/ctags/c.c
14 lines changed, 7 insertions(+), 7 deletions(-)
===================================================================
@@ -332,13 +332,13 @@ typedef enum
 } javaKind;
 
 static kindOption JavaKinds [] = {
-	{ TRUE,  'c', "class", "classes"},
-	{ TRUE,  'f', "field", "fields"},
-	{ TRUE,  'i', "interface", "interfaces"},
-	{ TRUE,  'm', "method", "methods"},
-	{ TRUE,  'p', "package", "packages"},
-	{ TRUE,  'e', "enumerator", "enumerators (values inside an enumeration)"},
-	{ TRUE,  'g', "enum",       "enumeration names"},
+	{ TRUE,  'c', "class",         "classes"},
+	{ TRUE,  'f', "field",         "fields"},
+	{ TRUE,  'i', "interface",     "interfaces"},
+	{ TRUE,  'm', "method",        "methods"},
+	{ TRUE,  'p', "package",       "packages"},
+	{ TRUE,  'e', "enumConstant",  "enum constants"},
+	{ TRUE,  'g', "enum",          "enum types"},
 };
 
 typedef enum


Modified: tagmanager/ctags/cobol.c
14 lines changed, 7 insertions(+), 7 deletions(-)
===================================================================
@@ -20,18 +20,18 @@
 
 static void installCobolRegex (const langType language)
 {
-   addTagRegex (language, "^[ \t]*[0-9]+[ \t]+([A-Z0-9][A-Z0-9-]*)[ \t]+(BLANK|OCCURS|IS|JUST|PIC|REDEFINES|RENAMES|SIGN|SYNC|USAGE|VALUE)",
-		"\\1", "d,variable,data items", "i");
+	addTagRegex (language, "^[ \t]*[0-9]+[ \t]+([A-Z0-9][A-Z0-9-]*)[ \t]+(BLANK|OCCURS|IS|JUST|PIC|REDEFINES|RENAMES|SIGN|SYNC|USAGE|VALUE)",
+		"\\1", "d,data,data items", "i");
 	addTagRegex (language, "^[ \t]*[FSR]D[ \t]+([A-Z0-9][A-Z0-9-]*)\\.",
-		"\\1", "f,function,file descriptions (FD, SD, RD)", "i");
+		"\\1", "f,file,file descriptions (FD, SD, RD)", "i");
 	addTagRegex (language, "^[ \t]*[0-9]+[ \t]+([A-Z0-9][A-Z0-9-]*)\\.",
-		"\\1", "g,struct,group items", "i");
+		"\\1", "g,group,group items", "i");
 	addTagRegex (language, "^[ \t]*([A-Z0-9][A-Z0-9-]*)\\.",
-		"\\1", "p,macro,paragraphs", "i");
+		"\\1", "p,paragraph,paragraphs", "i");
 	addTagRegex (language, "^[ \t]*PROGRAM-ID\\.[ \t]+([A-Z0-9][A-Z0-9-]*)\\.",
-		"\\1", "P,class,program ids", "i");
+		"\\1", "P,program,program ids", "i");
 	addTagRegex (language, "^[ \t]*([A-Z0-9][A-Z0-9-]*)[ \t]+SECTION\\.",
-		"\\1", "n,namespace,sections", "i");
+		"\\1", "s,section,sections", "i");
 }
 
 extern parserDefinition* CobolParser (void)


Modified: tagmanager/ctags/css.c
4 lines changed, 2 insertions(+), 2 deletions(-)
===================================================================
@@ -19,8 +19,8 @@ typedef enum eCssKinds {
 
 static kindOption CssKinds [] = {
 	{ TRUE, 'c', "class",		"classes" },
-	{ TRUE, 's', "struct",		"selectors" },
-	{ TRUE, 'v', "variable",	"identities" }
+	{ TRUE, 's', "selector",	"selectors" },
+	{ TRUE, 'i', "id",			"identities" }
 };
 
 typedef enum {


Modified: tagmanager/ctags/entry.c
8 lines changed, 1 insertions(+), 7 deletions(-)
===================================================================
@@ -393,19 +393,13 @@ extern void makeTagEntry (const tagEntryInfo *const tag)
 	int length = 0;
 
 	if (NULL != TagEntryFunction)
-		length = TagEntryFunction(tag);
+		length = TagEntryFunction(tag, TagEntryUserData);
 
 	++TagFile.numTags.added;
 	rememberMaxLengths (strlen (tag->name), (size_t) length);
     }
 }
 
-extern void setTagArglistByName (const char *tag_name, const char *arglist)
-{
-    if (NULL != TagEntrySetArglistFunction)
-	TagEntrySetArglistFunction(tag_name, arglist);
-}
-
 extern void initTagEntry (tagEntryInfo *const e, const char *const name)
 {
     Assert (File.source.name != NULL);


Modified: tagmanager/ctags/entry.h
1 lines changed, 0 insertions(+), 1 deletions(-)
===================================================================
@@ -95,7 +95,6 @@ extern void closeTagFile (const boolean resize);
 extern void beginEtagsFile (void);
 extern void endEtagsFile (const char *const name);
 extern void makeTagEntry (const tagEntryInfo *const tag);
-extern void setTagArglistByName (const char *tag_name, const char *arglist);
 extern void initTagEntry (tagEntryInfo *const e, const char *const name);
 
 #endif	/* _ENTRY_H */


Modified: tagmanager/ctags/erlang.c
4 lines changed, 2 insertions(+), 2 deletions(-)
===================================================================
@@ -32,8 +32,8 @@ static kindOption ErlangKinds[] = {
 	{TRUE, 'd', "macro",    "macro definitions"},
 	{TRUE, 'f', "function", "functions"},
 	{TRUE, 'm', "module",   "modules"},
-	{TRUE, 'r', "struct",   "record definitions"},
-	{TRUE, 't', "typedef",     "type definitions"},
+	{TRUE, 'r', "record",   "record definitions"},
+	{TRUE, 't', "type",     "type definitions"},
 };
 
 /*


Modified: tagmanager/ctags/fortran.c
16 lines changed, 8 insertions(+), 8 deletions(-)
===================================================================
@@ -215,22 +215,22 @@ static unsigned int contextual_fake_count = 0;
 
 /* indexed by tagType */
 static kindOption FortranKinds [TAG_COUNT] = {
-	{ TRUE,  'b', "block data",	"block data"},
-	{ TRUE,  'c', "macro",		"common blocks"},
+	{ TRUE,  'b', "blockData",	"block data"},
+	{ TRUE,  'c', "common",		"common blocks"},
 	{ TRUE,  'e', "entry",		"entry points"},
 	{ TRUE,  'f', "function",	"functions"},
 	{ TRUE,  'i', "interface",	"interface contents, generic names, and operators"},
-	{ TRUE,  'k', "member",	"type and structure components"},
+	{ TRUE,  'k', "component",	"type and structure components"},
 	{ TRUE,  'l', "label",		"labels"},
 	{ FALSE, 'L', "local",		"local, common block, and namelist variables"},
-	{ TRUE,  'm', "namespace",	"modules"},
+	{ TRUE,  'm', "module",	"modules"},
 	{ TRUE,  'n', "namelist",	"namelists"},
-	{ TRUE,  'p', "struct",	"programs"},
-	{ TRUE,  's', "method",	"subroutines"},
-	{ TRUE,  't', "class",	"derived types and structures"},
+	{ TRUE,  'p', "program",	"programs"},
+	{ TRUE,  's', "subroutine",	"subroutines"},
+	{ TRUE,  't', "type",	"derived types and structures"},
 	{ TRUE,  'v', "variable",	"program (global) and module variables"},
 	{ TRUE,  'E', "enum",	"enumerations"},
-	{ TRUE,  'F', "enumerator",	"enumeration values"},
+	{ TRUE,  'N', "enumerator",	"enumeration values"},
 };
 
 /* For efinitions of Fortran 77 with extensions:


Modified: tagmanager/ctags/go.c
10 lines changed, 5 insertions(+), 5 deletions(-)
===================================================================
@@ -93,11 +93,11 @@ typedef enum {
 } goKind;
 
 static kindOption GoKinds[] = {
-	{TRUE, 'p', "namespace", "packages"},
-	{TRUE, 'f', "function", "functions"},
-	{TRUE, 'c', "macro", "constants"},
-	{TRUE, 't', "typedef", "types"},
-	{TRUE, 'v', "variable", "variables"},
+	{TRUE, 'p', "package", "packages"},
+	{TRUE, 'f', "func", "functions"},
+	{TRUE, 'c', "const", "constants"},
+	{TRUE, 't', "type", "types"},
+	{TRUE, 'v', "var", "variables"},
 	{TRUE, 's', "struct", "structs"},
 	{TRUE, 'i', "interface", "interfaces"},
 	{TRUE, 'm', "member", "struct members"}


Modified: tagmanager/ctags/html.c
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -28,7 +28,7 @@ static void installHtmlRegex (const langType language)
 		"[ \t]+name=\"?([^>\"]+)\"?"
 		POSSIBLE_ATTRIBUTES
 		"[ \t]*>",
-		"\\2", "m,member,named anchors", "i");
+		"\\2", "a,anchor,named anchors", "i");
 
 	addTagRegex (language, "^[ \t]*function[ \t]*([A-Za-z0-9_]+)[ \t]*\\(",
 		"\\1", "f,function,JavaScript functions", NULL);


Modified: tagmanager/ctags/js.c
4 lines changed, 2 insertions(+), 2 deletions(-)
===================================================================
@@ -138,8 +138,8 @@ static kindOption JsKinds [] = {
 	{ TRUE,  'f', "function",	  "functions"		   },
 	{ TRUE,  'c', "class",		  "classes"			   },
 	{ TRUE,  'm', "method",		  "methods"			   },
-	{ TRUE,  'p', "member",		  "properties"		   },
-	{ TRUE,  'C', "macro",		  "constants"		   },
+	{ TRUE,  'p', "property",	  "properties"		   },
+	{ TRUE,  'C', "constant",	  "constants"		   },
 	{ TRUE,  'v', "variable",	  "global variables"   }
 };
 


Modified: tagmanager/ctags/json.c
12 lines changed, 6 insertions(+), 6 deletions(-)
===================================================================
@@ -69,12 +69,12 @@ typedef enum {
 static langType Lang_json;
 
 static kindOption JsonKinds [] = {
-	{ TRUE,  'o', "member",		"objects"	},
-	{ TRUE,  'a', "member",		"arrays"	},
-	{ TRUE,  'n', "member",		"numbers"	},
-	{ TRUE,  's', "member",		"strings"	},
-	{ TRUE,  'b', "member",		"booleans"	},
-	{ TRUE,  'z', "member",		"nulls"		}
+	{ TRUE,  'o', "object",		"objects"	},
+	{ TRUE,  'a', "array",		"arrays"	},
+	{ TRUE,  'n', "number",		"numbers"	},
+	{ TRUE,  's', "string",		"strings"	},
+	{ TRUE,  'b', "boolean",	"booleans"	},
+	{ TRUE,  'z', "null",		"nulls"		}
 };
 
 static tokenInfo *newToken (void)


Modified: tagmanager/ctags/make.c
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -30,7 +30,7 @@ typedef enum {
 
 static kindOption MakeKinds [] = {
 	{ TRUE, 'm', "macro",  "macros"},
-	{ TRUE, 't', "function", "targets"}
+	{ TRUE, 't', "target", "targets"}
 };
 
 /*


Modified: tagmanager/ctags/parse.c
11 lines changed, 9 insertions(+), 2 deletions(-)
===================================================================
@@ -31,14 +31,21 @@
 */
 static parserDefinitionFunc* BuiltInParsers[] = { PARSER_LIST };
 parserDefinition** LanguageTable = NULL;
-static unsigned int LanguageCount = 0;
+unsigned int LanguageCount = 0;
 tagEntryFunction TagEntryFunction = NULL;
-tagEntrySetArglistFunction TagEntrySetArglistFunction = NULL;
+void *TagEntryUserData = NULL;
 
 /*
 *   FUNCTION DEFINITIONS
 */
 
+extern void setTagEntryFunction(tagEntryFunction entry_function, void *user_data)
+{
+    TagEntryFunction = entry_function;
+    TagEntryUserData = user_data;
+}
+
+
 extern void makeSimpleTag (const vString* const name,
 			   kindOption* const kinds, const int kind)
 {


Modified: tagmanager/ctags/parse.h
8 lines changed, 4 insertions(+), 4 deletions(-)
===================================================================
@@ -36,8 +36,7 @@ typedef void (*createRegexTag) (const vString* const name);
 typedef void (*simpleParser) (void);
 typedef boolean (*rescanParser) (const unsigned int passCount);
 typedef void (*parserInitialize) (langType language);
-typedef int (*tagEntryFunction) (const tagEntryInfo *const tag);
-typedef void (*tagEntrySetArglistFunction) (const char *tag_name, const char *arglist);
+typedef int (*tagEntryFunction) (const tagEntryInfo *const tag, void *user_data);
 
 typedef struct sKindOption {
     boolean enabled;			/* are tags for kind enabled? */
@@ -84,6 +83,7 @@ typedef void (*regexCallback) (const char *line, const regexMatch *matches, unsi
  */
 extern parserDefinitionFunc PARSER_LIST;
 extern parserDefinition** LanguageTable;
+extern unsigned int LanguageCount;
 /* Legacy interface */
 extern boolean includingDefineTags (void);
 extern void processLegacyKindOption (const char *const parameter);
@@ -129,8 +129,8 @@ extern void checkRegex (void);
 
 /* Extra stuff for Tag Manager */
 extern tagEntryFunction TagEntryFunction;
-extern tagEntrySetArglistFunction TagEntrySetArglistFunction;
-extern void setTagEntryFunction(tagEntryFunction entry_function);
+extern void *TagEntryUserData;
+extern void setTagEntryFunction(tagEntryFunction entry_function, void *user_data);
 
 #endif	/* _PARSE_H */
 


Modified: tagmanager/ctags/pascal.c
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -30,7 +30,7 @@ typedef enum {
 
 static kindOption PascalKinds [] = {
     { TRUE, 'f', "function", "functions"},
-    { TRUE, 'f', "function", "procedures"}
+    { TRUE, 'p', "procedure", "procedures"}
 };
 
 /*


Modified: tagmanager/ctags/perl.c
12 lines changed, 6 insertions(+), 6 deletions(-)
===================================================================
@@ -38,12 +38,12 @@ typedef enum {
 } perlKind;
 
 static kindOption PerlKinds [] = {
-	{ TRUE,  'e', "enum",       "constants" },
-	{ TRUE,  'o', "other",      "formats" },
-	{ TRUE,  'm', "macro",      "labels" },
-	{ TRUE,  'p', "package",    "packages" },
-	{ TRUE,  'f', "function",   "subroutines" },
-	{ FALSE, 'p', "prototype",  "subroutine declarations" },
+	{ TRUE,  'c', "constant",               "constants" },
+	{ TRUE,  'f', "format",                 "formats" },
+	{ TRUE,  'l', "label",                  "labels" },
+	{ TRUE,  'p', "package",                "packages" },
+	{ TRUE,  's', "subroutine",             "subroutines" },
+	{ FALSE, 'd', "subroutineDeclaration",  "subroutine declarations" },
 };
 
 /*


Modified: tagmanager/ctags/php.c
4 lines changed, 2 insertions(+), 2 deletions(-)
===================================================================
@@ -114,12 +114,12 @@ typedef enum {
 
 static kindOption PhpKinds[COUNT_KIND] = {
 	{ TRUE, 'c', "class",		"classes" },
-	{ TRUE, 'm', "macro",		"constant definitions" },
+	{ TRUE, 'd', "define",		"constant definitions" },
 	{ TRUE, 'f', "function",	"functions" },
 	{ TRUE, 'i', "interface",	"interfaces" },
 	{ FALSE, 'l', "local",		"local variables" },
 	{ TRUE, 'n', "namespace",	"namespaces" },
-	{ TRUE, 's', "struct",		"traits" },
+	{ TRUE, 't', "trait",		"traits" },
 	{ TRUE, 'v', "variable",	"variables" }
 };
 


Modified: tagmanager/ctags/python.c
36 lines changed, 2 insertions(+), 34 deletions(-)
===================================================================
@@ -31,11 +31,9 @@ typedef enum {
 static kindOption PythonKinds[] = {
 	{TRUE, 'c', "class",    "classes"},
 	{TRUE, 'f', "function", "functions"},
-	{TRUE, 'm', "method",   "class methods"},
+	{TRUE, 'm', "member",   "class members"},
     {TRUE, 'v', "variable", "variables"},
-    /* defined as externvar to get those excluded as forward type in symbols.c:goto_tag()
-     * so we can jump to the real implementation (if known) instead of to the import statement */
-    {TRUE, 'x', "externvar", "imports"}
+    {TRUE, 'x', "unknown", "name referring a classe/variable/function/module defined in other module"}
 };
 
 typedef enum {
@@ -63,29 +61,6 @@ static boolean isIdentifierCharacter (int c)
 	return (boolean) (isalnum (c) || c == '_');
 }
 
-static const char *get_class_name_from_parent (const char *parent)
-{
-	const char *result;
-
-	if (parent == NULL)
-		return NULL;
-
-	result = strrchr (parent, '.');
-	if (result != NULL)
-	{
-		result++;
-		parent = result;
-	}
-
-	result = strrchr (parent, '/');
-	if (result != NULL)
-		result++;
-	else
-		result = parent;
-
-	return result;
-}
-
 /* follows PEP-8, and always reports single-underscores as protected
  * See:
  * - http://www.python.org/dev/peps/pep-0008/#method-names-and-instance-variables
@@ -140,13 +115,6 @@ static void makeFunctionTag (vString *const function,
 	tag.kindName = PythonKinds[K_FUNCTION].name;
 	tag.kind = PythonKinds[K_FUNCTION].letter;
 	tag.extensionFields.arglist = arglist;
-	/* add argument list of __init__() methods to the class tag */
-	if (strcmp (vStringValue (function), "__init__") == 0 && parent != NULL)
-	{
-		const char *parent_tag_name = get_class_name_from_parent (vStringValue (parent));
-		if (parent_tag_name != NULL)
-			setTagArglistByName (parent_tag_name, arglist);
-	}
 
 	if (vStringLength (parent) > 0)
 	{


Modified: tagmanager/ctags/r.c
6 lines changed, 3 insertions(+), 3 deletions(-)
===================================================================
@@ -36,8 +36,8 @@ typedef enum {
 
 static kindOption RKinds [KIND_COUNT] = {
   { TRUE, 'f', "function",  "functions" },
-  { TRUE, 's', "other",  "libraries" },
-  { TRUE, 's', "other",  "sources" },
+  { TRUE, 'l', "library",  "libraries" },
+  { TRUE, 's', "source",  "sources" },
 };
 #endif
 
@@ -190,7 +190,7 @@ extern parserDefinition* RParser (void)
   parserDefinition* const def = parserNew ("R");
 #ifndef R_REGEX
   def->kinds      = RKinds;
-  def->kindCount  = 4;
+  def->kindCount  = KIND_COUNT (RKinds);
 #endif
   def->extensions = extensions;
 #ifndef R_REGEX


Modified: tagmanager/ctags/ruby.c
4 lines changed, 2 insertions(+), 2 deletions(-)
===================================================================
@@ -36,8 +36,8 @@ typedef enum {
 static kindOption RubyKinds [] = {
 	{ TRUE, 'c', "class",  "classes" },
 	{ TRUE, 'f', "method", "methods" },
-	{ TRUE, 'm', "namespace", "modules" },
-	{ TRUE, 'F', "member", "singleton methods" },
+	{ TRUE, 'm', "module", "modules" },
+	{ TRUE, 'F', "singletonMethod", "singleton methods" },
 #if 0
 	/* Following two kinds are reserved. */
 	{ TRUE, 'd', "describe", "describes and contexts for Rspec" },


Modified: tagmanager/ctags/rust.c
4 lines changed, 2 insertions(+), 2 deletions(-)
===================================================================
@@ -47,10 +47,10 @@ typedef enum {
 } RustKind;
 
 static kindOption rustKinds[] = {
-	{TRUE, 'n', "namespace", "module"},
+	{TRUE, 'n', "module", "module"},
 	{TRUE, 's', "struct", "structural type"},
 	{TRUE, 'i', "interface", "trait interface"},
-	{TRUE, 'c', "class", "implementation"},
+	{TRUE, 'c', "implementation", "implementation"},
 	{TRUE, 'f', "function", "Function"},
 	{TRUE, 'g', "enum", "Enum"},
 	{TRUE, 't', "typedef", "Type Alias"},


Modified: tagmanager/ctags/sql.c
10 lines changed, 5 insertions(+), 5 deletions(-)
===================================================================
@@ -218,18 +218,18 @@ static kindOption SqlKinds [] = {
 	{ FALSE, 'l', "local",		  "local variables"		   },
 	{ TRUE,  'L', "label",		  "block label"			   },
 	{ TRUE,  'P', "package",	  "packages"			   },
-	{ TRUE,  'n', "namespace",	  "procedures"			   },
+	{ TRUE,  'p', "procedure",	  "procedures"			   },
 	{ FALSE, 'r', "record",		  "records"				   },
 	{ TRUE,  's', "subtype",	  "subtypes"			   },
-	{ TRUE,  't', "class",		  "tables"				   },
-	{ TRUE,  'T', "macro",	  "triggers"			   },
+	{ TRUE,  't', "table",		  "tables"				   },
+	{ TRUE,  'T', "trigger",	  "triggers"			   },
 	{ TRUE,  'v', "variable",	  "variables"			   },
-	{ TRUE,  'i', "struct",		  "indexes"				   },
+	{ TRUE,  'i', "index",		  "indexes"				   },
 	{ TRUE,  'e', "event",		  "events"				   },
 	{ TRUE,  'U', "publication",  "publications"		   },
 	{ TRUE,  'R', "service",	  "services"			   },
 	{ TRUE,  'D', "domain",		  "domains"				   },
-	{ TRUE,  'm', "member",		  "views"				   },
+	{ TRUE,  'V', "view",		  "views"				   },
 	{ TRUE,  'n', "synonym",	  "synonyms"			   },
 	{ TRUE,  'x', "mltable",	  "MobiLink Table Scripts" },
 	{ TRUE,  'y', "mlconn",		  "MobiLink Conn Scripts"  },


Modified: tagmanager/ctags/tcl.c
6 lines changed, 3 insertions(+), 3 deletions(-)
===================================================================
@@ -27,9 +27,9 @@ typedef enum {
 
 static kindOption TclKinds [] = {
 	{ TRUE, 'c', "class",     "classes" },
-	{ TRUE, 'f', "member",    "methods" },
-	{ TRUE, 'p', "function",  "procedures" },
-	{ TRUE, 'm', "namespace", "modules" }
+	{ TRUE, 'm', "method",    "methods" },
+	{ TRUE, 'p', "procedure", "procedures" },
+	{ TRUE, 'n', "module",    "modules" }
 };
 
 /*


Modified: tagmanager/ctags/verilog.c
14 lines changed, 7 insertions(+), 7 deletions(-)
===================================================================
@@ -58,14 +58,14 @@ static int Lang_verilog;
 static jmp_buf Exception;
 
 static kindOption VerilogKinds [] = {
- { TRUE, 'c', "variable",  "constants (define, parameter, specparam)" },
- { TRUE, 'e', "typedef",     "events" },
+ { TRUE, 'c', "constant",  "constants (define, parameter, specparam)" },
+ { TRUE, 'e', "event",     "events" },
  { TRUE, 'f', "function",  "functions" },
- { TRUE, 'm', "class",    "modules" },
- { TRUE, 'n', "variable",  "net data types" },
- { TRUE, 'p', "variable",  "ports" },
- { TRUE, 'r', "variable",  "register data types" },
- { TRUE, 't', "function",  "tasks" }
+ { TRUE, 'm', "module",    "modules" },
+ { TRUE, 'n', "net",       "net data types" },
+ { TRUE, 'p', "port",      "ports" },
+ { TRUE, 'r', "register",  "register data types" },
+ { TRUE, 't', "task",      "tasks" }
 };
 
 static keywordAssoc VerilogKeywordTable [] = {


Modified: tagmanager/ctags/vhdl.c
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -79,7 +79,7 @@ static kindOption VhdlKinds [] = {
  { TRUE, 'o', "struct",       "architecture" },
  { TRUE, 'u', "port",         "ports" },
  { TRUE, 'b', "member",       "blocks" },
- { TRUE, 'v', "typedef",      "alias" }
+ { TRUE, 'A', "typedef",      "alias" }
  };
 
 static keywordAssoc VhdlKeywordTable [] = {


Modified: tagmanager/mio/Makefile.am
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -3,6 +3,7 @@ noinst_LTLIBRARIES = libmio.la
 AM_CPPFLAGS = -DG_LOG_DOMAIN=\"MIO\" #-DMIO_DEBUG
 AM_CFLAGS   = $(GTK_CFLAGS) @LIBGEANY_CFLAGS@
 
+libmio_la_LIBADD = $(GTK_LIBS)
 libmio_la_SOURCES = mio.c
 
 EXTRA_DIST = \


Modified: tagmanager/src/Makefile.am
9 lines changed, 6 insertions(+), 3 deletions(-)
===================================================================
@@ -17,17 +17,20 @@ tagmanager_includedir = $(includedir)/geany/tagmanager
 tagmanager_include_HEADERS = \
 	tm_source_file.h \
 	tm_tag.h \
-	tm_tagmanager.h \
 	tm_workspace.h \
 	tm_parser.h
 
 
 libtagmanager_la_SOURCES =\
-	tm_tagmanager.h \
 	tm_parser.h \
+	tm_parser.c \
 	tm_source_file.h \
 	tm_source_file.c \
 	tm_tag.h \
 	tm_tag.c \
 	tm_workspace.h \
-	tm_workspace.c
+	tm_workspace.c \
+	tm_ctags_wrappers.h \
+	tm_ctags_wrappers.c
+
+libtagmanager_la_LIBADD = ../ctags/libctags.la $(GTK_LIBS)


Modified: tagmanager/src/tm_ctags_wrappers.c
171 lines changed, 171 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,171 @@
+/*
+ *      tm_ctags_wrappers.c - this file is part of Geany, a fast and lightweight IDE
+ *
+ *      Copyright 2016 Jiri Techet <techet(at)gmail(dot)com>
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License along
+ *      with this program; if not, write to the Free Software Foundation, Inc.,
+ *      51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "tm_ctags_wrappers.h"
+
+#include "general.h"
+#include "entry.h"
+#include "parse.h"
+#include "read.h"
+
+
+typedef struct {
+	TMCtagsNewTagCallback tag_callback;
+	gpointer user_data;
+} CallbackUserData;
+
+
+void tm_ctags_init(void)
+{
+	initializeParsing();
+	installLanguageMapDefaults();
+}
+
+
+static gboolean parse_callback(const tagEntryInfo *tag, gpointer user_data)
+{
+	CallbackUserData *callback_data = user_data;
+
+	return callback_data->tag_callback(tag, callback_data->user_data);
+}
+
+
+void tm_ctags_parse(guchar *buffer, gsize buffer_size,
+	const gchar *file_name, TMParserType lang, TMCtagsNewTagCallback tag_callback,
+	TMCtagsPassStartCallback pass_callback, gpointer user_data)
+{
+	CallbackUserData callback_data = {tag_callback, user_data};
+	gboolean retry = TRUE;
+	guint passCount = 0;
+
+	g_return_if_fail(buffer || file_name);
+
+	if (! LanguageTable [lang]->enabled)
+	{
+#ifdef TM_DEBUG
+		g_warning("ignoring %s (language disabled)\n", file_name);
+#endif
+		return;
+	}
+
+	setTagEntryFunction(parse_callback, &callback_data);
+	while (retry && passCount < 3)
+	{
+		pass_callback(user_data);
+		if (!buffer && fileOpen (file_name, lang))
+		{
+			if (LanguageTable [lang]->parser != NULL)
+			{
+				LanguageTable [lang]->parser ();
+				fileClose ();
+				retry = FALSE;
+				break;
+			}
+			else if (LanguageTable [lang]->parser2 != NULL)
+				retry = LanguageTable [lang]->parser2 (passCount);
+			fileClose ();
+		}
+		else if (buffer && bufferOpen (buffer, buffer_size, file_name, lang))
+		{
+			if (LanguageTable [lang]->parser != NULL)
+			{
+				LanguageTable [lang]->parser ();
+				bufferClose ();
+				retry = FALSE;
+				break;
+			}
+			else if (LanguageTable [lang]->parser2 != NULL)
+				retry = LanguageTable [lang]->parser2 (passCount);
+			bufferClose ();
+		}
+		else
+		{
+			g_warning("Unable to open %s", file_name);
+			return;
+		}
+		++ passCount;
+	}
+}
+
+
+const gchar *tm_ctags_get_lang_name(TMParserType lang)
+{
+	return getLanguageName(lang);
+}
+
+
+TMParserType tm_ctags_get_named_lang(const gchar *name)
+{
+	return getNamedLanguage(name);
+}
+
+
+const gchar *tm_ctags_get_lang_kinds(TMParserType lang)
+{
+	guint i;
+	parserDefinition *def = LanguageTable[lang];
+	static gchar kinds[257];
+
+	for (i = 0; i < def->kindCount; i++)
+		kinds[i] = def->kinds[i].letter;
+	kinds[i] = '\0';
+
+	return kinds;
+}
+
+
+const gchar *tm_ctags_get_kind_name(gchar kind, TMParserType lang)
+{
+	guint i;
+	parserDefinition *def = LanguageTable[lang];
+
+	for (i = 0; i < def->kindCount; i++)
+	{
+		if (def->kinds[i].letter == kind)
+			return def->kinds[i].name;
+	}
+	return "unknown";
+}
+
+
+gchar tm_ctags_get_kind_from_name(const gchar *name, TMParserType lang)
+{
+	guint i;
+	parserDefinition *def = LanguageTable[lang];
+
+	for (i = 0; i < def->kindCount; i++)
+	{
+		if (g_strcmp0(def->kinds[i].name, name) == 0)
+			return def->kinds[i].letter;
+	}
+	return '-';
+}
+
+
+gboolean tm_ctags_is_using_regex_parser(TMParserType lang)
+{
+	return LanguageTable[lang]->regex;
+}
+
+
+guint tm_ctags_get_lang_count(void)
+{
+	return LanguageCount;
+}


Modified: tagmanager/src/tm_ctags_wrappers.h
65 lines changed, 65 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,65 @@
+/*
+ *      tm_ctags_wrappers.h - this file is part of Geany, a fast and lightweight IDE
+ *
+ *      Copyright 2016 Jiri Techet <techet(at)gmail(dot)com>
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License along
+ *      with this program; if not, write to the Free Software Foundation, Inc.,
+ *      51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef TM_CTAGS_WRAPPERS
+#define TM_CTAGS_WRAPPERS
+
+#include <glib.h>
+
+#include "tm_parser.h"
+
+#include "entry.h" /* for sTagEntryInfo */
+
+
+G_BEGIN_DECLS
+
+/* Callback invoked for every tag found by the parser. The return value is
+ * currently unused. */
+typedef gboolean (*TMCtagsNewTagCallback) (const tagEntryInfo *const tag,
+	void *user_data);
+
+/* Callback invoked at the beginning of every parsing pass. The return value is
+ * currently unused */
+typedef gboolean (*TMCtagsPassStartCallback) (void *user_data);
+
+
+void tm_ctags_init(void);
+
+void tm_ctags_parse(guchar *buffer, gsize buffer_size,
+	const gchar *file_name, TMParserType lang, TMCtagsNewTagCallback tag_callback,
+	TMCtagsPassStartCallback pass_callback, gpointer user_data);
+
+const gchar *tm_ctags_get_lang_name(TMParserType lang);
+
+TMParserType tm_ctags_get_named_lang(const gchar *name);
+
+const gchar *tm_ctags_get_lang_kinds(TMParserType lang);
+
+const gchar *tm_ctags_get_kind_name(gchar kind, TMParserType lang);
+
+gchar tm_ctags_get_kind_from_name(const gchar *name, TMParserType lang);
+
+gboolean tm_ctags_is_using_regex_parser(TMParserType lang);
+
+guint tm_ctags_get_lang_count(void);
+
+G_END_DECLS
+
+#endif /* TM_CTAGS_WRAPPERS */


Modified: tagmanager/src/tm_parser.c
652 lines changed, 652 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,652 @@
+/*
+ *      tm_parser.c - this file is part of Geany, a fast and lightweight IDE
+ *
+ *      Copyright 2016 Jiri Techet <techet(at)gmail(dot)com>
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License along
+ *      with this program; if not, write to the Free Software Foundation, Inc.,
+ *      51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "tm_parser.h"
+#include "tm_ctags_wrappers.h"
+
+#include <string.h>
+
+
+typedef struct
+{
+    const gchar kind;
+    TMTagType type;
+} TMParserMapEntry;
+
+
+static TMParserMapEntry map_C[] = {
+	{'c', tm_tag_class_t},
+	{'d', tm_tag_macro_t},
+	{'e', tm_tag_enumerator_t},
+	{'f', tm_tag_function_t},
+	{'g', tm_tag_enum_t},
+	{'m', tm_tag_member_t},
+	{'n', tm_tag_namespace_t},
+	{'p', tm_tag_prototype_t},
+	{'s', tm_tag_struct_t},
+	{'t', tm_tag_typedef_t},
+	{'u', tm_tag_union_t},
+	{'v', tm_tag_variable_t},
+	{'x', tm_tag_externvar_t},
+};
+
+/* C++, same as C */
+#define map_CPP map_C
+
+static TMParserMapEntry map_JAVA[] = {
+	{'c', tm_tag_class_t},
+	{'f', tm_tag_field_t},
+	{'i', tm_tag_interface_t},
+	{'m', tm_tag_method_t},
+	{'p', tm_tag_package_t},
+	{'e', tm_tag_enumerator_t},
+	{'g', tm_tag_enum_t},
+};
+
+static TMParserMapEntry map_MAKEFILE[] = {
+	{'m', tm_tag_macro_t},
+	{'t', tm_tag_function_t},
+};
+
+static TMParserMapEntry map_PASCAL[] = {
+	{'f', tm_tag_function_t},
+	{'p', tm_tag_function_t},
+};
+
+static TMParserMapEntry map_PERL[] = {
+	{'c', tm_tag_enum_t},
+	{'f', tm_tag_other_t},
+	{'l', tm_tag_macro_t},
+	{'p', tm_tag_package_t},
+	{'s', tm_tag_function_t},
+	{'d', tm_tag_prototype_t},
+};
+
+static TMParserMapEntry map_PHP[] = {
+	{'c', tm_tag_class_t},
+	{'d', tm_tag_macro_t},
+	{'f', tm_tag_function_t},
+	{'i', tm_tag_interface_t},
+	{'l', tm_tag_undef_t},
+	{'n', tm_tag_namespace_t},
+	{'t', tm_tag_struct_t},
+	{'v', tm_tag_variable_t},
+};
+
+static TMParserMapEntry map_PYTHON[] = {
+	{'c', tm_tag_class_t},
+	{'f', tm_tag_function_t},
+	{'m', tm_tag_method_t},
+	{'v', tm_tag_variable_t},
+    /* defined as externvar to get those excluded as forward type in symbols.c:goto_tag()
+     * so we can jump to the real implementation (if known) instead of to the import statement */
+	{'x', tm_tag_externvar_t},
+};
+
+/* different parser than tex.c from universal-ctags */
+static TMParserMapEntry map_LATEX[] = {
+	{'f', tm_tag_function_t},
+	{'c', tm_tag_class_t},
+	{'m', tm_tag_member_t},
+	{'d', tm_tag_macro_t},
+	{'v', tm_tag_variable_t},
+	{'n', tm_tag_namespace_t},
+	{'s', tm_tag_struct_t},
+};
+
+static TMParserMapEntry map_ASM[] = {
+	{'d', tm_tag_macro_t},
+	{'l', tm_tag_namespace_t},
+	{'m', tm_tag_function_t},
+	{'t', tm_tag_struct_t},
+};
+
+/* not in universal-ctags */
+static TMParserMapEntry map_CONF[] = {
+	{'n', tm_tag_namespace_t},
+	{'m', tm_tag_macro_t},
+};
+
+static TMParserMapEntry map_SQL[] = {
+	{'c', tm_tag_undef_t},
+	{'d', tm_tag_prototype_t},
+	{'f', tm_tag_function_t},
+	{'F', tm_tag_field_t},
+	{'l', tm_tag_undef_t},
+	{'L', tm_tag_undef_t},
+	{'P', tm_tag_package_t},
+	{'p', tm_tag_namespace_t},
+	{'r', tm_tag_undef_t},
+	{'s', tm_tag_undef_t},
+	{'t', tm_tag_class_t},
+	{'T', tm_tag_macro_t},
+	{'v', tm_tag_variable_t},
+	{'i', tm_tag_struct_t},
+	{'e', tm_tag_undef_t},
+	{'U', tm_tag_undef_t},
+	{'R', tm_tag_undef_t},
+	{'D', tm_tag_undef_t},
+	{'V', tm_tag_member_t},
+	{'n', tm_tag_undef_t},
+	{'x', tm_tag_undef_t},
+	{'y', tm_tag_undef_t},
+	{'z', tm_tag_undef_t},
+};
+
+/* not in universal-ctags */
+static TMParserMapEntry map_DOCBOOK[] = {
+	{'f', tm_tag_function_t},
+	{'c', tm_tag_class_t},
+	{'m', tm_tag_member_t},
+	{'d', tm_tag_macro_t},
+	{'v', tm_tag_variable_t},
+	{'s', tm_tag_struct_t},
+};
+
+static TMParserMapEntry map_ERLANG[] = {
+	{'d', tm_tag_macro_t},
+	{'f', tm_tag_function_t},
+	{'m', tm_tag_undef_t},
+	{'r', tm_tag_struct_t},
+	{'t', tm_tag_typedef_t},
+};
+
+static TMParserMapEntry map_CSS[] = {
+	{'c', tm_tag_class_t},
+	{'s', tm_tag_struct_t},
+	{'i', tm_tag_variable_t},
+};
+
+static TMParserMapEntry map_RUBY[] = {
+	{'c', tm_tag_class_t},
+	{'f', tm_tag_method_t},
+	{'m', tm_tag_namespace_t},
+	{'F', tm_tag_member_t},
+};
+
+static TMParserMapEntry map_TCL[] = {
+	{'c', tm_tag_class_t},
+	{'m', tm_tag_member_t},
+	{'p', tm_tag_function_t},
+	{'n', tm_tag_namespace_t},
+};
+
+static TMParserMapEntry map_SH[] = {
+	{'f', tm_tag_function_t},
+};
+
+static TMParserMapEntry map_D[] = {
+	{'c', tm_tag_class_t},
+	{'e', tm_tag_enumerator_t},
+	{'f', tm_tag_function_t},
+	{'g', tm_tag_enum_t},
+	{'i', tm_tag_interface_t},
+	{'m', tm_tag_member_t},
+	{'n', tm_tag_namespace_t},
+	{'p', tm_tag_prototype_t},
+	{'s', tm_tag_struct_t},
+	{'t', tm_tag_typedef_t},
+	{'u', tm_tag_union_t},
+	{'v', tm_tag_variable_t},
+	{'x', tm_tag_externvar_t},
+};
+
+static TMParserMapEntry map_DIFF[] = {
+	{'f', tm_tag_function_t},
+};
+
+/* different parser than in universal-ctags */
+static TMParserMapEntry map_VHDL[] = {
+	{'c', tm_tag_variable_t},
+	{'t', tm_tag_typedef_t},
+	{'v', tm_tag_variable_t},
+	{'a', tm_tag_undef_t},
+	{'s', tm_tag_variable_t},
+	{'f', tm_tag_function_t},
+	{'p', tm_tag_function_t},
+	{'k', tm_tag_member_t},
+	{'l', tm_tag_namespace_t},
+	{'m', tm_tag_member_t},
+	{'n', tm_tag_class_t},
+	{'o', tm_tag_struct_t},
+	{'u', tm_tag_undef_t},
+	{'b', tm_tag_member_t},
+	{'A', tm_tag_typedef_t},
+};
+
+static TMParserMapEntry map_LUA[] = {
+	{'f', tm_tag_function_t},
+};
+
+static TMParserMapEntry map_JAVASCRIPT[] = {
+	{'f', tm_tag_function_t},
+	{'c', tm_tag_class_t},
+	{'m', tm_tag_method_t},
+	{'p', tm_tag_member_t},
+	{'C', tm_tag_macro_t},
+	{'v', tm_tag_variable_t},
+};
+
+/* not in universal-ctags */
+static TMParserMapEntry map_HASKELL[] = {
+	{'t', tm_tag_typedef_t},
+	{'c', tm_tag_macro_t},
+	{'f', tm_tag_function_t},
+	{'m', tm_tag_namespace_t},
+};
+
+static TMParserMapEntry map_CSHARP[] = {
+	{'c', tm_tag_class_t},
+	{'d', tm_tag_macro_t},
+	{'e', tm_tag_enumerator_t},
+	{'E', tm_tag_undef_t},
+	{'f', tm_tag_field_t},
+	{'g', tm_tag_enum_t},
+	{'i', tm_tag_interface_t},
+	{'l', tm_tag_undef_t},
+	{'m', tm_tag_method_t},
+	{'n', tm_tag_namespace_t},
+	{'p', tm_tag_undef_t},
+	{'s', tm_tag_struct_t},
+	{'t', tm_tag_typedef_t},
+};
+
+static TMParserMapEntry map_FREEBASIC[] = {
+	{'c', tm_tag_macro_t},
+	{'f', tm_tag_function_t},
+	{'l', tm_tag_namespace_t},
+	{'t', tm_tag_struct_t},
+	{'v', tm_tag_variable_t},
+	{'g', tm_tag_externvar_t},
+};
+
+/* not in universal-ctags */
+static TMParserMapEntry map_HAXE[] = {
+	{'m', tm_tag_method_t},
+	{'c', tm_tag_class_t},
+	{'e', tm_tag_enum_t},
+	{'v', tm_tag_variable_t},
+	{'i', tm_tag_interface_t},
+	{'t', tm_tag_typedef_t},
+};
+
+/* not in universal-ctags */
+static TMParserMapEntry map_REST[] = {
+	{'n', tm_tag_namespace_t},
+	{'m', tm_tag_member_t},
+	{'d', tm_tag_macro_t},
+	{'v', tm_tag_variable_t},
+};
+
+static TMParserMapEntry map_HTML[] = {
+	{'a', tm_tag_member_t},
+	{'f', tm_tag_function_t},
+	{'n', tm_tag_namespace_t},
+	{'c', tm_tag_class_t},
+	{'v', tm_tag_variable_t},
+};
+
+static TMParserMapEntry map_F77[] = {
+	{'b', tm_tag_undef_t},
+	{'c', tm_tag_macro_t},
+	{'e', tm_tag_undef_t},
+	{'f', tm_tag_function_t},
+	{'i', tm_tag_interface_t},
+	{'k', tm_tag_member_t},
+	{'l', tm_tag_undef_t},
+	{'L', tm_tag_undef_t},
+	{'m', tm_tag_namespace_t},
+	{'n', tm_tag_undef_t},
+	{'p', tm_tag_struct_t},
+	{'s', tm_tag_method_t},
+	{'t', tm_tag_class_t},
+	{'v', tm_tag_variable_t},
+	{'E', tm_tag_enum_t},
+	{'N', tm_tag_enumerator_t},
+};
+
+#define map_FORTRAN map_F77
+
+#define map_FERITE map_C
+
+/* different parser than in universal-ctags */
+static TMParserMapEntry map_MATLAB[] = {
+	{'f', tm_tag_function_t},
+	{'s', tm_tag_struct_t},
+};
+
+#define map_GLSL map_C
+
+/* not in universal-ctags */
+static TMParserMapEntry map_VALA[] = {
+	{'c', tm_tag_class_t},
+	{'d', tm_tag_macro_t},
+	{'e', tm_tag_enumerator_t},
+	{'f', tm_tag_field_t},
+	{'g', tm_tag_enum_t},
+	{'i', tm_tag_interface_t},
+	{'l', tm_tag_undef_t},
+	{'m', tm_tag_method_t},
+	{'n', tm_tag_namespace_t},
+	{'p', tm_tag_undef_t},
+	{'S', tm_tag_undef_t},
+	{'s', tm_tag_struct_t},
+};
+
+/* not in universal-ctags */
+static TMParserMapEntry map_ACTIONSCRIPT[] = {
+	{'f', tm_tag_function_t},
+	{'l', tm_tag_field_t},
+	{'v', tm_tag_variable_t},
+	{'m', tm_tag_macro_t},
+	{'c', tm_tag_class_t},
+	{'i', tm_tag_interface_t},
+	{'p', tm_tag_package_t},
+	{'o', tm_tag_other_t},
+	{'r', tm_tag_prototype_t},
+};
+
+/* not in universal-ctags */
+static TMParserMapEntry map_NSIS[] = {
+	{'n', tm_tag_namespace_t},
+	{'f', tm_tag_function_t},
+	{'v', tm_tag_variable_t},
+};
+
+/* not in universal-ctags */
+static TMParserMapEntry map_MARKDOWN[] = {
+	{'v', tm_tag_variable_t},
+};
+
+/* not in universal-ctags */
+static TMParserMapEntry map_TXT2TAGS[] = {
+	{'m', tm_tag_member_t},
+};
+
+/* not in universal-ctags */
+static TMParserMapEntry map_ABC[] = {
+	{'m', tm_tag_member_t},
+	{'s', tm_tag_struct_t},
+};
+
+static TMParserMapEntry map_VERILOG[] = {
+	{'c', tm_tag_variable_t},
+	{'e', tm_tag_typedef_t},
+	{'f', tm_tag_function_t},
+	{'m', tm_tag_class_t},
+	{'n', tm_tag_variable_t},
+	{'p', tm_tag_variable_t},
+	{'r', tm_tag_variable_t},
+	{'t', tm_tag_function_t},
+};
+
+static TMParserMapEntry map_R[] = {
+	{'f', tm_tag_function_t},
+	{'l', tm_tag_other_t},
+	{'s', tm_tag_other_t},
+};
+
+static TMParserMapEntry map_COBOL[] = {
+	{'d', tm_tag_variable_t},
+	{'f', tm_tag_function_t},
+	{'g', tm_tag_struct_t},
+	{'p', tm_tag_macro_t},
+	{'P', tm_tag_class_t},
+	{'s', tm_tag_namespace_t},
+};
+
+static TMParserMapEntry map_OBJC[] = {
+	{'i', tm_tag_interface_t},
+	{'I', tm_tag_undef_t},
+	{'P', tm_tag_undef_t},
+	{'m', tm_tag_method_t},
+	{'c', tm_tag_class_t},
+	{'v', tm_tag_variable_t},
+	{'F', tm_tag_field_t},
+	{'f', tm_tag_function_t},
+	{'p', tm_tag_undef_t},
+	{'t', tm_tag_typedef_t},
+	{'s', tm_tag_struct_t},
+	{'e', tm_tag_enum_t},
+	{'M', tm_tag_macro_t},
+};
+
+/* not in universal-ctags */
+static TMParserMapEntry map_ASCIIDOC[] = {
+	{'n', tm_tag_namespace_t},
+	{'m', tm_tag_member_t},
+	{'d', tm_tag_macro_t},
+	{'v', tm_tag_variable_t},
+	{'s', tm_tag_struct_t},
+};
+
+/* not in universal-ctags */
+static TMParserMapEntry map_ABAQUS[] = {
+	{'c', tm_tag_class_t},
+	{'m', tm_tag_member_t},
+	{'n', tm_tag_interface_t},
+};
+
+static TMParserMapEntry map_RUST[] = {
+	{'n', tm_tag_namespace_t},
+	{'s', tm_tag_struct_t},
+	{'i', tm_tag_interface_t},
+	{'c', tm_tag_class_t},
+	{'f', tm_tag_function_t},
+	{'g', tm_tag_enum_t},
+	{'t', tm_tag_typedef_t},
+	{'v', tm_tag_variable_t},
+	{'M', tm_tag_macro_t},
+	{'m', tm_tag_field_t},
+	{'e', tm_tag_enumerator_t},
+	{'F', tm_tag_method_t},
+};
+
+static TMParserMapEntry map_GO[] = {
+	{'p', tm_tag_namespace_t},
+	{'f', tm_tag_function_t},
+	{'c', tm_tag_macro_t},
+	{'t', tm_tag_typedef_t},
+	{'v', tm_tag_variable_t},
+	{'s', tm_tag_struct_t},
+	{'i', tm_tag_interface_t},
+	{'m', tm_tag_member_t},
+};
+
+static TMParserMapEntry map_JSON[] = {
+	{'o', tm_tag_member_t},
+	{'a', tm_tag_member_t},
+	{'n', tm_tag_member_t},
+	{'s', tm_tag_member_t},
+	{'b', tm_tag_member_t},
+	{'z', tm_tag_member_t},
+};
+
+/* Zephir, same as PHP */
+#define map_ZEPHIR map_PHP
+
+/* not in universal-ctags */
+static TMParserMapEntry map_POWERSHELL[] = {
+	{'f', tm_tag_function_t},
+	{'v', tm_tag_variable_t},
+};
+
+
+typedef struct
+{
+    TMParserMapEntry *entries;
+    guint size;
+} TMParserMap;
+
+#define MAP_ENTRY(lang) [TM_PARSER_##lang] = {map_##lang, G_N_ELEMENTS(map_##lang)}
+
+/* keep in sync with TM_PARSER_* definitions in the header */
+static TMParserMap parser_map[] = {
+	MAP_ENTRY(C),
+	MAP_ENTRY(CPP),
+	MAP_ENTRY(JAVA),
+	MAP_ENTRY(MAKEFILE),
+	MAP_ENTRY(PASCAL),
+	MAP_ENTRY(PERL),
+	MAP_ENTRY(PHP),
+	MAP_ENTRY(PYTHON),
+	MAP_ENTRY(LATEX),
+	MAP_ENTRY(ASM),
+	MAP_ENTRY(CONF),
+	MAP_ENTRY(SQL),
+	MAP_ENTRY(DOCBOOK),
+	MAP_ENTRY(ERLANG),
+	MAP_ENTRY(CSS),
+	MAP_ENTRY(RUBY),
+	MAP_ENTRY(TCL),
+	MAP_ENTRY(SH),
+	MAP_ENTRY(D),
+	MAP_ENTRY(FORTRAN),
+	MAP_ENTRY(FERITE),
+	MAP_ENTRY(DIFF),
+	MAP_ENTRY(VHDL),
+	MAP_ENTRY(LUA),
+	MAP_ENTRY(JAVASCRIPT),
+	MAP_ENTRY(HASKELL),
+	MAP_ENTRY(CSHARP),
+	MAP_ENTRY(FREEBASIC),
+	MAP_ENTRY(HAXE),
+	MAP_ENTRY(REST),
+	MAP_ENTRY(HTML),
+	MAP_ENTRY(F77),
+	MAP_ENTRY(GLSL),
+	MAP_ENTRY(MATLAB),
+	MAP_ENTRY(VALA),
+	MAP_ENTRY(ACTIONSCRIPT),
+	MAP_ENTRY(NSIS),
+	MAP_ENTRY(MARKDOWN),
+	MAP_ENTRY(TXT2TAGS),
+	MAP_ENTRY(ABC),
+	MAP_ENTRY(VERILOG),
+	MAP_ENTRY(R),
+	MAP_ENTRY(COBOL),
+	MAP_ENTRY(OBJC),
+	MAP_ENTRY(ASCIIDOC),
+	MAP_ENTRY(ABAQUS),
+	MAP_ENTRY(RUST),
+	MAP_ENTRY(GO),
+	MAP_ENTRY(JSON),
+	MAP_ENTRY(ZEPHIR),
+	MAP_ENTRY(POWERSHELL),
+};
+/* make sure the parser map is consistent and complete */
+G_STATIC_ASSERT(G_N_ELEMENTS(parser_map) == TM_PARSER_COUNT);
+
+
+TMTagType tm_parser_get_tag_type(gchar kind, TMParserType lang)
+{
+	TMParserMap *map = &parser_map[lang];
+	guint i;
+
+	for (i = 0; i < map->size; i++)
+	{
+		TMParserMapEntry *entry = &map->entries[i];
+
+		if (entry->kind == kind)
+			return entry->type;
+	}
+	return tm_tag_undef_t;
+}
+
+
+gchar tm_parser_get_tag_kind(TMTagType type, TMParserType lang)
+{
+	TMParserMap *map = &parser_map[lang];
+	guint i;
+
+	for (i = 0; i < map->size; i++)
+	{
+		TMParserMapEntry *entry = &map->entries[i];
+
+		if (entry->type == type)
+			return entry->kind;
+	}
+	return '\0';
+}
+
+
+void tm_parser_verify_type_mappings(void)
+{
+	TMParserType lang;
+
+	if (TM_PARSER_COUNT > tm_ctags_get_lang_count())
+		g_error("More parsers defined in Geany than in ctags");
+
+	for (lang = 0; lang < TM_PARSER_COUNT; lang++)
+	{
+		const gchar *kinds = tm_ctags_get_lang_kinds(lang);
+		TMParserMap *map = &parser_map[lang];
+		gchar presence_map[256];
+		guint i;
+
+		if (! map->entries || map->size < 1)
+			g_error("No tag types in TM for %s, is the language listed in parser_map?",
+					tm_ctags_get_lang_name(lang));
+
+		/* TODO: check also regex parser mappings. At the moment there's no way
+		 * to access regex parser definitions in ctags */
+		if (tm_ctags_is_using_regex_parser(lang))
+			continue;
+
+		if (map->size != strlen(kinds))
+			g_error("Different number of tag types in TM (%d) and ctags (%d) for %s",
+				map->size, (int)strlen(kinds), tm_ctags_get_lang_name(lang));
+
+		memset(presence_map, 0, sizeof(presence_map));
+		for (i = 0; i < map->size; i++)
+		{
+			gboolean ctags_found = FALSE;
+			gboolean tm_found = FALSE;
+			guint j;
+
+			for (j = 0; j < map->size; j++)
+			{
+				/* check that for every type in TM there's a type in ctags */
+				if (map->entries[i].kind == kinds[j])
+					ctags_found = TRUE;
+				/* check that for every type in ctags there's a type in TM */
+				if (map->entries[j].kind == kinds[i])
+					tm_found = TRUE;
+				if (ctags_found && tm_found)
+					break;
+			}
+			if (!ctags_found)
+				g_error("Tag type '%c' found in TM but not in ctags for %s",
+					map->entries[i].kind, tm_ctags_get_lang_name(lang));
+			if (!tm_found)
+				g_error("Tag type '%c' found in ctags but not in TM for %s",
+					kinds[i], tm_ctags_get_lang_name(lang));
+
+			presence_map[(unsigned char) map->entries[i].kind]++;
+		}
+
+		for (i = 0; i < sizeof(presence_map); i++)
+		{
+			if (presence_map[i] > 1)
+				g_error("Duplicate tag type '%c' found for %s",
+					(gchar)i, tm_ctags_get_lang_name(lang));
+		}
+	}
+}


Modified: tagmanager/src/tm_parser.h
45 lines changed, 45 insertions(+), 0 deletions(-)
===================================================================
@@ -10,6 +10,42 @@
 #ifndef TM_PARSER_H
 #define TM_PARSER_H
 
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+/**
+ Types of tags. It is a bitmask so that multiple tag types can
+ be used simultaneously by 'OR'-ing them bitwise.
+ e.g. tm_tag_class_t | tm_tag_struct_t
+*/
+typedef enum
+{
+	tm_tag_undef_t = 0, /**< Unknown type */
+	tm_tag_class_t = 1, /**< Class declaration */
+	tm_tag_enum_t = 2, /**< Enum declaration */
+	tm_tag_enumerator_t = 4, /**< Enumerator value */
+	tm_tag_field_t = 8, /**< Field (Java only) */
+	tm_tag_function_t = 16, /**< Function definition */
+	tm_tag_interface_t = 32, /**< Interface (Java only) */
+	tm_tag_member_t = 64, /**< Member variable of class/struct */
+	tm_tag_method_t = 128, /**< Class method (Java only) */
+	tm_tag_namespace_t = 256, /**< Namespace declaration */
+	tm_tag_package_t = 512, /**< Package (Java only) */
+	tm_tag_prototype_t = 1024, /**< Function prototype */
+	tm_tag_struct_t = 2048, /**< Struct declaration */
+	tm_tag_typedef_t = 4096, /**< Typedef */
+	tm_tag_union_t = 8192, /**< Union */
+	tm_tag_variable_t = 16384, /**< Variable */
+	tm_tag_externvar_t = 32768, /**< Extern or forward declaration */
+	tm_tag_macro_t = 65536, /**<  Macro (without arguments) */
+	tm_tag_macro_with_arg_t = 131072, /**< Parameterized macro */
+	tm_tag_file_t = 262144, /**< File (Pseudo tag) - obsolete */
+	tm_tag_other_t = 524288, /**< Other (non C/C++/Java tag) */
+	tm_tag_max_t = 1048575 /**< Maximum value of TMTagType */
+} TMTagType;
+
+
 /** @gironly
  * A integral type which can hold known parser type IDs
  **/
@@ -76,6 +112,15 @@ enum
 	TM_PARSER_COUNT
 };
 
+
+void tm_parser_verify_type_mappings(void);
+
+TMTagType tm_parser_get_tag_type(gchar kind, TMParserType lang);
+
+gchar tm_parser_get_tag_kind(TMTagType type, TMParserType lang);
+
 #endif /* GEANY_PRIVATE */
 
+G_END_DECLS
+
 #endif /* TM_PARSER_H */


Modified: tagmanager/src/tm_source_file.c
696 lines changed, 546 insertions(+), 150 deletions(-)
===================================================================
@@ -18,6 +18,7 @@
 #include <limits.h>
 #include <stdlib.h>
 #include <string.h>
+#include <ctype.h>
 #include <sys/stat.h>
 #include <glib/gstdio.h>
 #ifdef G_OS_WIN32
@@ -26,27 +27,49 @@
 # include <windows.h> /* for GetFullPathName */
 #endif
 
-#include "general.h"
-#include "entry.h"
-#include "parse.h"
-#include "read.h"
-
-#define LIBCTAGS_DEFINED
 #include "tm_source_file.h"
 #include "tm_tag.h"
 #include "tm_parser.h"
+#include "tm_ctags_wrappers.h"
 
 typedef struct
 {
 	TMSourceFile public;
 	guint refcount;
 } TMSourceFilePriv;
 
+
+typedef enum {
+	TM_FILE_FORMAT_TAGMANAGER,
+	TM_FILE_FORMAT_PIPE,
+	TM_FILE_FORMAT_CTAGS
+} TMFileFormat;
+
+/* Note: To preserve binary compatibility, it is very important
+	that you only *append* to this list ! */
+enum
+{
+	TA_NAME = 200,
+	TA_LINE,
+	TA_LOCAL,
+	TA_POS, /* Obsolete */
+	TA_TYPE,
+	TA_ARGLIST,
+	TA_SCOPE,
+	TA_VARTYPE,
+	TA_INHERITS,
+	TA_TIME,
+	TA_ACCESS,
+	TA_IMPL,
+	TA_LANG,
+	TA_INACTIVE, /* Obsolete */
+	TA_POINTER
+};
+
+
 #define SOURCE_FILE_NEW(S) ((S) = g_slice_new(TMSourceFilePriv))
 #define SOURCE_FILE_FREE(S) g_slice_free(TMSourceFilePriv, (TMSourceFilePriv *) S)
 
-static TMSourceFile *current_source_file = NULL;
-
 static int get_path_max(const char *path)
 {
 #ifdef PATH_MAX
@@ -109,46 +132,534 @@ gchar *tm_get_real_path(const gchar *file_name)
 	return NULL;
 }
 
+static char get_tag_impl(const char *impl)
+{
+	if ((0 == strcmp("virtual", impl))
+	 || (0 == strcmp("pure virtual", impl)))
+		return TAG_IMPL_VIRTUAL;
+
+#ifdef TM_DEBUG
+		g_warning("Unknown implementation %s", impl);
+#endif
+	return TAG_IMPL_UNKNOWN;
+}
+
+static char get_tag_access(const char *access)
+{
+	if (0 == strcmp("public", access))
+		return TAG_ACCESS_PUBLIC;
+	else if (0 == strcmp("protected", access))
+		return TAG_ACCESS_PROTECTED;
+	else if (0 == strcmp("private", access))
+		return TAG_ACCESS_PRIVATE;
+	else if (0 == strcmp("friend", access))
+		return TAG_ACCESS_FRIEND;
+	else if (0 == strcmp("default", access))
+		return TAG_ACCESS_DEFAULT;
+
+#ifdef TM_DEBUG
+	g_warning("Unknown access type %s", access);
+#endif
+	return TAG_ACCESS_UNKNOWN;
+}
+
+/*
+ Initializes a TMTag structure with information from a tagEntryInfo struct
+ used by the ctags parsers. Note that the TMTag structure must be malloc()ed
+ before calling this function.
+ @param tag The TMTag structure to initialize
+ @param file Pointer to a TMSourceFile struct (it is assigned to the file member)
+ @param tag_entry Tag information gathered by the ctags parser
+ @return TRUE on success, FALSE on failure
+*/
+static gboolean init_tag(TMTag *tag, TMSourceFile *file, const tagEntryInfo *tag_entry)
+{
+	TMTagType type;
+
+	if (!tag_entry)
+		return FALSE;
+
+	type = tm_parser_get_tag_type(tag_entry->kind, file->lang);
+	if (!tag_entry->name || type == tm_tag_undef_t)
+		return FALSE;
+
+	tag->name = g_strdup(tag_entry->name);
+	tag->type = type;
+	tag->local = tag_entry->isFileScope;
+	tag->pointerOrder = 0;	/* backward compatibility (use var_type instead) */
+	tag->line = tag_entry->lineNumber;
+	if (NULL != tag_entry->extensionFields.arglist)
+		tag->arglist = g_strdup(tag_entry->extensionFields.arglist);
+	if ((NULL != tag_entry->extensionFields.scope[1]) &&
+		(0 != tag_entry->extensionFields.scope[1][0]))
+		tag->scope = g_strdup(tag_entry->extensionFields.scope[1]);
+	if (tag_entry->extensionFields.inheritance != NULL)
+		tag->inheritance = g_strdup(tag_entry->extensionFields.inheritance);
+	if (tag_entry->extensionFields.varType != NULL)
+		tag->var_type = g_strdup(tag_entry->extensionFields.varType);
+	if (tag_entry->extensionFields.access != NULL)
+		tag->access = get_tag_access(tag_entry->extensionFields.access);
+	if (tag_entry->extensionFields.implementation != NULL)
+		tag->impl = get_tag_impl(tag_entry->extensionFields.implementation);
+	if ((tm_tag_macro_t == tag->type) && (NULL != tag->arglist))
+		tag->type = tm_tag_macro_with_arg_t;
+	tag->file = file;
+	tag->lang = file->lang;
+	return TRUE;
+}
+
 /*
- This function is registered into the ctags parser when a file is parsed for
- the first time. The function is then called by the ctags parser each time
- it finds a new tag. You should not have to use this function.
- @see tm_source_file_parse()
+ Initializes an already malloc()ed TMTag structure by reading a tag entry
+ line from a file. The structure should be allocated beforehand.
+ @param tag The TMTag structure to populate
+ @param file The TMSourceFile struct (assigned to the file member)
+ @param fp FILE pointer from where the tag line is read
+ @return TRUE on success, FALSE on FAILURE
 */
-static int tm_source_file_tags(const tagEntryInfo *tag)
+static gboolean init_tag_from_file(TMTag *tag, TMSourceFile *file, FILE *fp)
 {
-	if (NULL == current_source_file)
-		return 0;
-	g_ptr_array_add(current_source_file->tags_array, 
-		tm_tag_new(current_source_file, tag));
+	guchar buf[BUFSIZ];
+	guchar *start, *end;
+	gboolean status;
+	guchar changed_char = TA_NAME;
+
+	tag->refcount = 1;
+	if ((NULL == fgets((gchar*)buf, BUFSIZ, fp)) || ('\0' == *buf))
+		return FALSE;
+	for (start = end = buf, status = TRUE; (TRUE == status); start = end, ++ end)
+	{
+		while ((*end < TA_NAME) && (*end != '\0') && (*end != '\n'))
+			++ end;
+		if (('\0' == *end) || ('\n' == *end))
+			status = FALSE;
+		changed_char = *end;
+		*end = '\0';
+		if (NULL == tag->name)
+		{
+			if (!isprint(*start))
+				return FALSE;
+			else
+				tag->name = g_strdup((gchar*)start);
+		}
+		else
+		{
+			switch (*start)
+			{
+				case TA_LINE:
+					tag->line = atol((gchar*)start + 1);
+					break;
+				case TA_LOCAL:
+					tag->local = atoi((gchar*)start + 1);
+					break;
+				case TA_TYPE:
+					tag->type = (TMTagType) atoi((gchar*)start + 1);
+					break;
+				case TA_ARGLIST:
+					tag->arglist = g_strdup((gchar*)start + 1);
+					break;
+				case TA_SCOPE:
+					tag->scope = g_strdup((gchar*)start + 1);
+					break;
+				case TA_POINTER:
+					tag->pointerOrder = atoi((gchar*)start + 1);
+					break;
+				case TA_VARTYPE:
+					tag->var_type = g_strdup((gchar*)start + 1);
+					break;
+				case TA_INHERITS:
+					tag->inheritance = g_strdup((gchar*)start + 1);
+					break;
+				case TA_TIME:  /* Obsolete */
+					break;
+				case TA_LANG:  /* Obsolete */
+					break;
+				case TA_INACTIVE:  /* Obsolete */
+					break;
+				case TA_ACCESS:
+					tag->access = (char) *(start + 1);
+					break;
+				case TA_IMPL:
+					tag->impl = (char) *(start + 1);
+					break;
+				default:
+#ifdef GEANY_DEBUG
+					g_warning("Unknown attribute %s", start + 1);
+#endif
+					break;
+			}
+		}
+		*end = changed_char;
+	}
+	if (NULL == tag->name)
+		return FALSE;
+	tag->file = file;
 	return TRUE;
 }
 
-/* Set the argument list of tag identified by its name */
-static void tm_source_file_set_tag_arglist(const char *tag_name, const char *arglist)
+/* alternative parser for Pascal and LaTeX global tags files with the following format
+ * tagname|return value|arglist|description\n */
+static gboolean init_tag_from_file_alt(TMTag *tag, TMSourceFile *file, FILE *fp)
+{
+	guchar buf[BUFSIZ];
+	guchar *start, *end;
+	gboolean status;
+	/*guchar changed_char = TA_NAME;*/
+
+	tag->refcount = 1;
+	if ((NULL == fgets((gchar*)buf, BUFSIZ, fp)) || ('\0' == *buf))
+		return FALSE;
+	{
+		gchar **fields;
+		guint field_len;
+		for (start = end = buf, status = TRUE; (TRUE == status); start = end, ++ end)
+		{
+			while ((*end < TA_NAME) && (*end != '\0') && (*end != '\n'))
+				++ end;
+			if (('\0' == *end) || ('\n' == *end))
+				status = FALSE;
+			/*changed_char = *end;*/
+			*end = '\0';
+			if (NULL == tag->name && !isprint(*start))
+					return FALSE;
+
+			fields = g_strsplit((gchar*)start, "|", -1);
+			field_len = g_strv_length(fields);
+
+			if (field_len >= 1) tag->name = g_strdup(fields[0]);
+			else tag->name = NULL;
+			if (field_len >= 2 && fields[1] != NULL) tag->var_type = g_strdup(fields[1]);
+			if (field_len >= 3 && fields[2] != NULL) tag->arglist = g_strdup(fields[2]);
+			tag->type = tm_tag_prototype_t;
+			g_strfreev(fields);
+		}
+	}
+
+	if (NULL == tag->name)
+		return FALSE;
+	tag->file = file;
+	return TRUE;
+}
+
+/*
+ CTags tag file format (http://ctags.sourceforge.net/FORMAT)
+*/
+static gboolean init_tag_from_file_ctags(TMTag *tag, TMSourceFile *file, FILE *fp, TMParserType lang)
+{
+	gchar buf[BUFSIZ];
+	gchar *p, *tab;
+
+	tag->refcount = 1;
+	tag->type = tm_tag_function_t; /* default type is function if no kind is specified */
+	do
+	{
+		if ((NULL == fgets(buf, BUFSIZ, fp)) || ('\0' == *buf))
+			return FALSE;
+	}
+	while (strncmp(buf, "!_TAG_", 6) == 0); /* skip !_TAG_ lines */
+
+	p = buf;
+
+	/* tag name */
+	if (! (tab = strchr(p, '\t')) || p == tab)
+		return FALSE;
+	tag->name = g_strndup(p, (gsize)(tab - p));
+	p = tab + 1;
+
+	/* tagfile, unused */
+	if (! (tab = strchr(p, '\t')))
+	{
+		g_free(tag->name);
+		tag->name = NULL;
+		return FALSE;
+	}
+	p = tab + 1;
+	/* Ex command, unused */
+	if (*p == '/' || *p == '?')
+	{
+		gchar c = *p;
+		for (++p; *p && *p != c; p++)
+		{
+			if (*p == '\\' && p[1])
+				p++;
+		}
+	}
+	else /* assume a line */
+		tag->line = atol(p);
+	tab = strstr(p, ";\"");
+	/* read extension fields */
+	if (tab)
+	{
+		p = tab + 2;
+		while (*p && *p != '\n' && *p != '\r')
+		{
+			gchar *end;
+			const gchar *key, *value = NULL;
+
+			/* skip leading tabulations */
+			while (*p && *p == '\t') p++;
+			/* find the separator (:) and end (\t) */
+			key = end = p;
+			while (*end && *end != '\t' && *end != '\n' && *end != '\r')
+			{
+				if (*end == ':' && ! value)
+				{
+					*end = 0; /* terminate the key */
+					value = end + 1;
+				}
+				end++;
+			}
+			/* move p paste the so we won't stop parsing by setting *end=0 below */
+			p = *end ? end + 1 : end;
+			*end = 0; /* terminate the value (or key if no value) */
+
+			if (! value || 0 == strcmp(key, "kind")) /* tag kind */
+			{
+				const gchar *kind = value ? value : key;
+
+				if (kind[0] && kind[1])
+					tag->type = tm_parser_get_tag_type(tm_ctags_get_kind_from_name(kind, lang), lang);
+				else
+					tag->type = tm_parser_get_tag_type(*kind, lang);
+			}
+			else if (0 == strcmp(key, "inherits")) /* comma-separated list of classes this class inherits from */
+			{
+				g_free(tag->inheritance);
+				tag->inheritance = g_strdup(value);
+			}
+			else if (0 == strcmp(key, "implementation")) /* implementation limit */
+				tag->impl = get_tag_impl(value);
+			else if (0 == strcmp(key, "line")) /* line */
+				tag->line = atol(value);
+			else if (0 == strcmp(key, "access")) /* access */
+				tag->access = get_tag_access(value);
+			else if (0 == strcmp(key, "class") ||
+					 0 == strcmp(key, "enum") ||
+					 0 == strcmp(key, "function") ||
+					 0 == strcmp(key, "struct") ||
+					 0 == strcmp(key, "union")) /* Name of the class/enum/function/struct/union in which this tag is a member */
+			{
+				g_free(tag->scope);
+				tag->scope = g_strdup(value);
+			}
+			else if (0 == strcmp(key, "file")) /* static (local) tag */
+				tag->local = TRUE;
+			else if (0 == strcmp(key, "signature")) /* arglist */
+			{
+				g_free(tag->arglist);
+				tag->arglist = g_strdup(value);
+			}
+		}
+	}
+
+	tag->file = file;
+	return TRUE;
+}
+
+static TMTag *new_tag_from_tags_file(TMSourceFile *file, FILE *fp, TMParserType mode, TMFileFormat format)
+{
+	TMTag *tag = tm_tag_new();
+	gboolean result = FALSE;
+
+	switch (format)
+	{
+		case TM_FILE_FORMAT_TAGMANAGER:
+			result = init_tag_from_file(tag, file, fp);
+			break;
+		case TM_FILE_FORMAT_PIPE:
+			result = init_tag_from_file_alt(tag, file, fp);
+			break;
+		case TM_FILE_FORMAT_CTAGS:
+			result = init_tag_from_file_ctags(tag, file, fp, mode);
+			break;
+	}
+
+	if (! result)
+	{
+		tm_tag_unref(tag);
+		return NULL;
+	}
+	tag->lang = mode;
+	return tag;
+}
+
+/*
+ Writes tag information to the given FILE *.
+ @param tag The tag information to write.
+ @param file FILE pointer to which the tag information is written.
+ @param attrs Attributes to be written (bitmask).
+ @return TRUE on success, FALSE on failure.
+*/
+static gboolean write_tag(TMTag *tag, FILE *fp, TMTagAttrType attrs)
+{
+	fprintf(fp, "%s", tag->name);
+	if (attrs & tm_tag_attr_type_t)
+		fprintf(fp, "%c%d", TA_TYPE, tag->type);
+	if ((attrs & tm_tag_attr_arglist_t) && (NULL != tag->arglist))
+		fprintf(fp, "%c%s", TA_ARGLIST, tag->arglist);
+	if (attrs & tm_tag_attr_line_t)
+		fprintf(fp, "%c%ld", TA_LINE, tag->line);
+	if (attrs & tm_tag_attr_local_t)
+		fprintf(fp, "%c%d", TA_LOCAL, tag->local);
+	if ((attrs & tm_tag_attr_scope_t) && (NULL != tag->scope))
+		fprintf(fp, "%c%s", TA_SCOPE, tag->scope);
+	if ((attrs & tm_tag_attr_inheritance_t) && (NULL != tag->inheritance))
+		fprintf(fp, "%c%s", TA_INHERITS, tag->inheritance);
+	if (attrs & tm_tag_attr_pointer_t)
+		fprintf(fp, "%c%d", TA_POINTER, tag->pointerOrder);
+	if ((attrs & tm_tag_attr_vartype_t) && (NULL != tag->var_type))
+		fprintf(fp, "%c%s", TA_VARTYPE, tag->var_type);
+	if ((attrs & tm_tag_attr_access_t) && (TAG_ACCESS_UNKNOWN != tag->access))
+		fprintf(fp, "%c%c", TA_ACCESS, tag->access);
+	if ((attrs & tm_tag_attr_impl_t) && (TAG_IMPL_UNKNOWN != tag->impl))
+		fprintf(fp, "%c%c", TA_IMPL, tag->impl);
+
+	if (fprintf(fp, "\n"))
+		return TRUE;
+	else
+		return FALSE;
+}
+
+GPtrArray *tm_source_file_read_tags_file(const gchar *tags_file, TMParserType mode)
+{
+	guchar buf[BUFSIZ];
+	FILE *fp;
+	GPtrArray *file_tags;
+	TMTag *tag;
+	TMFileFormat format = TM_FILE_FORMAT_TAGMANAGER;
+
+	if (NULL == (fp = g_fopen(tags_file, "r")))
+		return NULL;
+	if ((NULL == fgets((gchar*) buf, BUFSIZ, fp)) || ('\0' == *buf))
+	{
+		fclose(fp);
+		return NULL; /* early out on error */
+	}
+	else
+	{	/* We read the first line for the format specification. */
+		if (buf[0] == '#' && strstr((gchar*) buf, "format=pipe") != NULL)
+			format = TM_FILE_FORMAT_PIPE;
+		else if (buf[0] == '#' && strstr((gchar*) buf, "format=tagmanager") != NULL)
+			format = TM_FILE_FORMAT_TAGMANAGER;
+		else if (buf[0] == '#' && strstr((gchar*) buf, "format=ctags") != NULL)
+			format = TM_FILE_FORMAT_CTAGS;
+		else if (strncmp((gchar*) buf, "!_TAG_", 6) == 0)
+			format = TM_FILE_FORMAT_CTAGS;
+		else
+		{	/* We didn't find a valid format specification, so we try to auto-detect the format
+			 * by counting the pipe characters on the first line and asumme pipe format when
+			 * we find more than one pipe on the line. */
+			guint i, pipe_cnt = 0, tab_cnt = 0;
+			for (i = 0; i < BUFSIZ && buf[i] != '\0' && pipe_cnt < 2; i++)
+			{
+				if (buf[i] == '|')
+					pipe_cnt++;
+				else if (buf[i] == '\t')
+					tab_cnt++;
+			}
+			if (pipe_cnt > 1)
+				format = TM_FILE_FORMAT_PIPE;
+			else if (tab_cnt > 1)
+				format = TM_FILE_FORMAT_CTAGS;
+		}
+		rewind(fp); /* reset the file pointer, to start reading again from the beginning */
+	}
+
+	file_tags = g_ptr_array_new();
+	while (NULL != (tag = new_tag_from_tags_file(NULL, fp, mode, format)))
+		g_ptr_array_add(file_tags, tag);
+	fclose(fp);
+
+	return file_tags;
+}
+
+gboolean tm_source_file_write_tags_file(const gchar *tags_file, GPtrArray *tags_array)
 {
 	guint i;
+	FILE *fp;
+	gboolean ret = TRUE;
+
+	g_return_val_if_fail(tags_array && tags_file, FALSE);
+
+	fp = g_fopen(tags_file, "w");
+	if (!fp)
+		return FALSE;
 
-	if (NULL == arglist ||
-		NULL == tag_name ||
-		NULL == current_source_file)
+	fprintf(fp, "# format=tagmanager\n");
+	for (i = 0; i < tags_array->len; i++)
 	{
-		return;
+		TMTag *tag = TM_TAG(tags_array->pdata[i]);
+
+		ret = write_tag(tag, fp, tm_tag_attr_type_t
+		  | tm_tag_attr_scope_t | tm_tag_attr_arglist_t | tm_tag_attr_vartype_t
+		  | tm_tag_attr_pointer_t);
+
+		if (!ret)
+			break;
 	}
+	fclose(fp);
+
+	return ret;
+}
+
+/* add argument list of __init__() Python methods to the class tag */
+static void update_python_arglist(const TMTag *tag, TMSourceFile *current_source_file)
+{
+	guint i;
+	const char *parent_tag_name;
+
+	if (tag->type != tm_tag_method_t || tag->scope == NULL ||
+		g_strcmp0(tag->name, "__init__") != 0)
+		return;
+
+	parent_tag_name = strrchr(tag->scope, '.');
+	if (parent_tag_name)
+		parent_tag_name++;
+	else
+		parent_tag_name = tag->scope;
 
 	/* going in reverse order because the tag was added recently */
 	for (i = current_source_file->tags_array->len; i > 0; i--)
 	{
-		TMTag *tag = (TMTag *) current_source_file->tags_array->pdata[i - 1];
-		if (g_strcmp0(tag->name, tag_name) == 0)
+		TMTag *prev_tag = (TMTag *) current_source_file->tags_array->pdata[i - 1];
+		if (g_strcmp0(prev_tag->name, parent_tag_name) == 0)
 		{
-			g_free(tag->arglist);
-			tag->arglist = g_strdup(arglist);
+			g_free(prev_tag->arglist);
+			prev_tag->arglist = g_strdup(tag->arglist);
 			break;
 		}
 	}
 }
 
+/* new parsing pass ctags callback function */
+static gboolean ctags_pass_start(void *user_data)
+{
+	TMSourceFile *current_source_file = user_data;
+
+	tm_tags_array_free(current_source_file->tags_array, FALSE);
+	return TRUE;
+}
+
+/* new tag ctags callback function */
+static gboolean ctags_new_tag(const tagEntryInfo *const tag,
+	void *user_data)
+{
+	TMSourceFile *current_source_file = user_data;
+	TMTag *tm_tag = tm_tag_new();
+
+	if (!init_tag(tm_tag, current_source_file, tag))
+	{
+		tm_tag_unref(tm_tag);
+		return TRUE;
+	}
+
+	if (tm_tag->lang == TM_PARSER_PYTHON)
+		update_python_arglist(tm_tag, current_source_file);
+
+	g_ptr_array_add(current_source_file->tags_array, tm_tag);
+
+	return TRUE;
+}
+
 /* Initializes a TMSourceFile structure from a file name. */
 static gboolean tm_source_file_init(TMSourceFile *source_file, const char *file_name, 
 	const char* name)
@@ -183,20 +694,10 @@ static gboolean tm_source_file_init(TMSourceFile *source_file, const char *file_
 
 	source_file->tags_array = g_ptr_array_new();
 
-	if (NULL == LanguageTable)
-	{
-		initializeParsing();
-		installLanguageMapDefaults();
-		if (NULL == TagEntryFunction)
-			TagEntryFunction = tm_source_file_tags;
-		if (NULL == TagEntrySetArglistFunction)
-			TagEntrySetArglistFunction = tm_source_file_set_tag_arglist;
-	}
-
 	if (name == NULL)
 		source_file->lang = TM_PARSER_NONE;
 	else
-		source_file->lang = getNamedLanguage(name);
+		source_file->lang = tm_ctags_get_named_lang(name);
 
 	return TRUE;
 }
@@ -333,63 +834,11 @@ gboolean tm_source_file_parse(TMSourceFile *source_file, guchar* text_buf, gsize
 		return TRUE;
 	}
 
-	if (NULL == LanguageTable)
-	{
-		initializeParsing();
-		installLanguageMapDefaults();
-		if (NULL == TagEntryFunction)
-			TagEntryFunction = tm_source_file_tags;
-		if (NULL == TagEntrySetArglistFunction)
-			TagEntrySetArglistFunction = tm_source_file_set_tag_arglist;
-	}
-	current_source_file = source_file;
-	if (! LanguageTable [source_file->lang]->enabled)
-	{
-#ifdef TM_DEBUG
-		g_warning("ignoring %s (language disabled)\n", file_name);
-#endif
-	}
-	else
-	{
-		guint passCount = 0;
-		while (retry && passCount < 3)
-		{
-			tm_tags_array_free(source_file->tags_array, FALSE);
-			if (parse_file && fileOpen (file_name, source_file->lang))
-			{
-				if (LanguageTable [source_file->lang]->parser != NULL)
-				{
-					LanguageTable [source_file->lang]->parser ();
-					fileClose ();
-					retry = FALSE;
-					break;
-				}
-				else if (LanguageTable [source_file->lang]->parser2 != NULL)
-					retry = LanguageTable [source_file->lang]->parser2 (passCount);
-				fileClose ();
-			}
-			else if (!parse_file && bufferOpen (text_buf, buf_size, file_name, source_file->lang))
-			{
-				if (LanguageTable [source_file->lang]->parser != NULL)
-				{
-					LanguageTable [source_file->lang]->parser ();
-					bufferClose ();
-					retry = FALSE;
-					break;
-				}
-				else if (LanguageTable [source_file->lang]->parser2 != NULL)
-					retry = LanguageTable [source_file->lang]->parser2 (passCount);
-				bufferClose ();
-			}
-			else
-			{
-				g_warning("Unable to open %s", file_name);
-				return FALSE;
-			}
-			++ passCount;
-		}
-	}
-	
+	tm_tags_array_free(source_file->tags_array, FALSE);
+
+	tm_ctags_parse(parse_file ? NULL : text_buf, buf_size, file_name,
+		source_file->lang, ctags_new_tag, ctags_pass_start, source_file);
+
 	if (free_buf)
 		g_free(text_buf);
 	return !retry;
@@ -401,16 +850,7 @@ gboolean tm_source_file_parse(TMSourceFile *source_file, guchar* text_buf, gsize
 */
 const gchar *tm_source_file_get_lang_name(TMParserType lang)
 {
-	if (NULL == LanguageTable)
-	{
-		initializeParsing();
-		installLanguageMapDefaults();
-		if (NULL == TagEntryFunction)
-			TagEntryFunction = tm_source_file_tags;
-		if (NULL == TagEntrySetArglistFunction)
-			TagEntrySetArglistFunction = tm_source_file_set_tag_arglist;
-	}
-	return getLanguageName(lang);
+	return tm_ctags_get_lang_name(lang);
 }
 
 /* Gets the language index for \a name.
@@ -419,49 +859,5 @@ const gchar *tm_source_file_get_lang_name(TMParserType lang)
 */
 TMParserType tm_source_file_get_named_lang(const gchar *name)
 {
-	if (NULL == LanguageTable)
-	{
-		initializeParsing();
-		installLanguageMapDefaults();
-		if (NULL == TagEntryFunction)
-			TagEntryFunction = tm_source_file_tags;
-		if (NULL == TagEntrySetArglistFunction)
-			TagEntrySetArglistFunction = tm_source_file_set_tag_arglist;
-	}
-	return getNamedLanguage(name);
+	return tm_ctags_get_named_lang(name);
 }
-
-#if 0
-/*
- Writes all tags of a source file (including the file tag itself) to the passed
- file pointer.
- @param source_file The source file to write.
- @param fp The file pointer to write to.
- @param attrs The attributes to write.
- @return TRUE on success, FALSE on failure.
-*/
-static gboolean tm_source_file_write(TMSourceFile *source_file, FILE *fp, guint attrs)
-{
-	TMTag *tag;
-	guint i;
-
-	if (NULL != source_file)
-	{
-		if (NULL != (tag = tm_tag_new(source_file, NULL)))
-		{
-			tm_tag_write(tag, fp, tm_tag_attr_max_t);
-			tm_tag_unref(tag);
-			if (NULL != source_file->tags_array)
-			{
-				for (i=0; i < source_file->tags_array->len; ++i)
-				{
-					tag = TM_TAG(source_file->tags_array->pdata[i]);
-					if (TRUE != tm_tag_write(tag, fp, attrs))
-						return FALSE;
-				}
-			}
-		}
-	}
-	return TRUE;
-}
-#endif


Modified: tagmanager/src/tm_source_file.h
18 lines changed, 6 insertions(+), 12 deletions(-)
===================================================================
@@ -16,14 +16,7 @@
 
 #include "tm_parser.h"
 
-#ifndef LIBCTAGS_DEFINED
-typedef void tagEntryInfo;
-#endif
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
+G_BEGIN_DECLS
 
 /* Casts a pointer to a pointer to a TMSourceFile structure */
 #define TM_SOURCE_FILE(source_file) ((TMSourceFile *) source_file)
@@ -51,7 +44,6 @@ void tm_source_file_free(TMSourceFile *source_file);
 
 gchar *tm_get_real_path(const gchar *file_name);
 
-
 #ifdef GEANY_PRIVATE
 
 const gchar *tm_source_file_get_lang_name(TMParserType lang);
@@ -61,10 +53,12 @@ TMParserType tm_source_file_get_named_lang(const gchar *name);
 gboolean tm_source_file_parse(TMSourceFile *source_file, guchar* text_buf, gsize buf_size,
 	gboolean use_buffer);
 
+GPtrArray *tm_source_file_read_tags_file(const gchar *tags_file, TMParserType mode);
+
+gboolean tm_source_file_write_tags_file(const gchar *tags_file, GPtrArray *tags_array);
+
 #endif /* GEANY_PRIVATE */
 
-#ifdef __cplusplus
-}
-#endif
+G_END_DECLS
 
 #endif /* TM_SOURCE_FILE_H */


Modified: tagmanager/src/tm_tag.c
607 lines changed, 23 insertions(+), 584 deletions(-)
===================================================================
@@ -11,13 +11,8 @@
 #include <string.h>
 #include <glib-object.h>
 
-#include "general.h"
-#include "entry.h"
-#include "parse.h"
-#include "read.h"
-#define LIBCTAGS_DEFINED
 #include "tm_tag.h"
-#include "tm_parser.h"
+#include "tm_ctags_wrappers.h"
 
 
 #define TAG_NEW(T)	((T) = g_slice_new0(TMTag))
@@ -79,32 +74,6 @@ static void log_tag_free(TMTag *tag)
 #endif /* DEBUG_TAG_REFS */
 
 
-const TMTagType TM_GLOBAL_TYPE_MASK =
-	tm_tag_class_t | tm_tag_enum_t | tm_tag_interface_t |
-	tm_tag_struct_t | tm_tag_typedef_t | tm_tag_union_t | tm_tag_namespace_t;
-
-
-/* Note: To preserve binary compatibility, it is very important
-	that you only *append* to this list ! */
-enum
-{
-	TA_NAME = 200,
-	TA_LINE,
-	TA_LOCAL,
-	TA_POS, /* Obsolete */
-	TA_TYPE,
-	TA_ARGLIST,
-	TA_SCOPE,
-	TA_VARTYPE,
-	TA_INHERITS,
-	TA_TIME,
-	TA_ACCESS,
-	TA_IMPL,
-	TA_LANG,
-	TA_INACTIVE, /* Obsolete */
-	TA_POINTER
-};
-
 typedef struct
 {
 	guint *sort_attrs;
@@ -113,48 +82,6 @@ typedef struct
 	gboolean first;
 } TMSortOptions;
 
-static const char *s_tag_type_names[] = {
-	"class", /* classes */
-	"enum", /* enumeration names */
-	"enumerator", /* enumerators (values inside an enumeration) */
-	"externvar", /* external variable declarations */
-	"field", /* fields */
-	"function", /*  function definitions */
-	"interface", /* interfaces */
-	"macro", /* macro definitions */
-	"member", /* class, struct, and union members */
-	"method", /* methods */
-	"namespace", /* namespaces */
-	"package", /* packages */
-	"prototype", /* function prototypes */
-	"struct", /* structure names */
-	"typedef", /* typedefs */
-	"union", /* union names */
-	"variable", /* variable definitions */
-	"other" /* Other tag type (non C/C++/Java) */
-};
-
-static TMTagType s_tag_types[] = {
-	tm_tag_class_t,
-	tm_tag_enum_t,
-	tm_tag_enumerator_t,
-	tm_tag_externvar_t,
-	tm_tag_field_t,
-	tm_tag_function_t,
-	tm_tag_interface_t,
-	tm_tag_macro_t,
-	tm_tag_member_t,
-	tm_tag_method_t,
-	tm_tag_namespace_t,
-	tm_tag_package_t,
-	tm_tag_prototype_t,
-	tm_tag_struct_t,
-	tm_tag_typedef_t,
-	tm_tag_union_t,
-	tm_tag_variable_t,
-	tm_tag_other_t
-};
-
 /* Gets the GType for a TMTag */
 GType tm_tag_get_type(void)
 {
@@ -167,470 +94,21 @@ GType tm_tag_get_type(void)
 	return gtype;
 }
 
-static TMTagType get_tag_type(const char *tag_name)
-{
-	unsigned int i;
-	int cmp;
-	g_return_val_if_fail(tag_name, 0);
-	for (i=0; i < sizeof(s_tag_type_names)/sizeof(char *); ++i)
-	{
-		cmp = strcmp(tag_name, s_tag_type_names[i]);
-		if (0 == cmp)
-			return s_tag_types[i];
-		else if (cmp < 0)
-			break;
-	}
-	/* other is not checked above as it is last, not sorted alphabetically */
-	if (strcmp(tag_name, "other") == 0)
-		return tm_tag_other_t;
-#ifdef TM_DEBUG
-	fprintf(stderr, "Unknown tag type %s\n", tag_name);
-#endif
-	return tm_tag_undef_t;
-}
-
-static char get_tag_impl(const char *impl)
-{
-	if ((0 == strcmp("virtual", impl))
-	 || (0 == strcmp("pure virtual", impl)))
-		return TAG_IMPL_VIRTUAL;
-
-#ifdef TM_DEBUG
-		g_warning("Unknown implementation %s", impl);
-#endif
-	return TAG_IMPL_UNKNOWN;
-}
-
-static char get_tag_access(const char *access)
-{
-	if (0 == strcmp("public", access))
-		return TAG_ACCESS_PUBLIC;
-	else if (0 == strcmp("protected", access))
-		return TAG_ACCESS_PROTECTED;
-	else if (0 == strcmp("private", access))
-		return TAG_ACCESS_PRIVATE;
-	else if (0 == strcmp("friend", access))
-		return TAG_ACCESS_FRIEND;
-	else if (0 == strcmp("default", access))
-		return TAG_ACCESS_DEFAULT;
-
-#ifdef TM_DEBUG
-	g_warning("Unknown access type %s", access);
-#endif
-	return TAG_ACCESS_UNKNOWN;
-}
-
 /*
- Initializes a TMTag structure with information from a tagEntryInfo struct
- used by the ctags parsers. Note that the TMTag structure must be malloc()ed
- before calling this function. This function is called by tm_tag_new() - you
- should not need to call this directly.
- @param tag The TMTag structure to initialize
- @param file Pointer to a TMSourceFile struct (it is assigned to the file member)
- @param tag_entry Tag information gathered by the ctags parser
- @return TRUE on success, FALSE on failure
-*/
-static gboolean tm_tag_init(TMTag *tag, TMSourceFile *file, const tagEntryInfo *tag_entry)
-{
-	tag->refcount = 1;
-	if (NULL == tag_entry)
-		return FALSE;
-		
-	/* This is a normal tag entry */
-	if (NULL == tag_entry->name)
-		return FALSE;
-	tag->name = g_strdup(tag_entry->name);
-	tag->type = get_tag_type(tag_entry->kindName);
-	tag->local = tag_entry->isFileScope;
-	tag->pointerOrder = 0;	/* backward compatibility (use var_type instead) */
-	tag->line = tag_entry->lineNumber;
-	if (NULL != tag_entry->extensionFields.arglist)
-		tag->arglist = g_strdup(tag_entry->extensionFields.arglist);
-	if ((NULL != tag_entry->extensionFields.scope[1]) &&
-		(0 != tag_entry->extensionFields.scope[1][0]))
-		tag->scope = g_strdup(tag_entry->extensionFields.scope[1]);
-	if (tag_entry->extensionFields.inheritance != NULL)
-		tag->inheritance = g_strdup(tag_entry->extensionFields.inheritance);
-	if (tag_entry->extensionFields.varType != NULL)
-		tag->var_type = g_strdup(tag_entry->extensionFields.varType);
-	if (tag_entry->extensionFields.access != NULL)
-		tag->access = get_tag_access(tag_entry->extensionFields.access);
-	if (tag_entry->extensionFields.implementation != NULL)
-		tag->impl = get_tag_impl(tag_entry->extensionFields.implementation);
-	if ((tm_tag_macro_t == tag->type) && (NULL != tag->arglist))
-		tag->type = tm_tag_macro_with_arg_t;
-	tag->file = file;
-	tag->lang = file->lang;
-	return TRUE;
-}
-
-/*
- Creates a new tag structure from a tagEntryInfo pointer and a TMSOurceFile pointer
- and returns a pointer to it.
- @param file - Pointer to the TMSourceFile structure containing the tag
- @param tag_entry Contains tag information generated by ctags
+ Creates a new tag structure and returns a pointer to it.
  @return the new TMTag structure. This should be free()-ed using tm_tag_free()
 */
-TMTag *tm_tag_new(TMSourceFile *file, const tagEntryInfo *tag_entry)
+TMTag *tm_tag_new(void)
 {
 	TMTag *tag;
 
 	TAG_NEW(tag);
-	if (FALSE == tm_tag_init(tag, file, tag_entry))
-	{
-		TAG_FREE(tag);
-		return NULL;
-	}
-	return tag;
-}
-
-/*
- Initializes an already malloc()ed TMTag structure by reading a tag entry
- line from a file. The structure should be allocated beforehand.
- @param tag The TMTag structure to populate
- @param file The TMSourceFile struct (assigned to the file member)
- @param fp FILE pointer from where the tag line is read
- @return TRUE on success, FALSE on FAILURE
-*/
-static gboolean tm_tag_init_from_file(TMTag *tag, TMSourceFile *file, FILE *fp)
-{
-	guchar buf[BUFSIZ];
-	guchar *start, *end;
-	gboolean status;
-	guchar changed_char = TA_NAME;
-
-	tag->refcount = 1;
-	if ((NULL == fgets((gchar*)buf, BUFSIZ, fp)) || ('\0' == *buf))
-		return FALSE;
-	for (start = end = buf, status = TRUE; (TRUE == status); start = end, ++ end)
-	{
-		while ((*end < TA_NAME) && (*end != '\0') && (*end != '\n'))
-			++ end;
-		if (('\0' == *end) || ('\n' == *end))
-			status = FALSE;
-		changed_char = *end;
-		*end = '\0';
-		if (NULL == tag->name)
-		{
-			if (!isprint(*start))
-				return FALSE;
-			else
-				tag->name = g_strdup((gchar*)start);
-		}
-		else
-		{
-			switch (*start)
-			{
-				case TA_LINE:
-					tag->line = atol((gchar*)start + 1);
-					break;
-				case TA_LOCAL:
-					tag->local = atoi((gchar*)start + 1);
-					break;
-				case TA_TYPE:
-					tag->type = (TMTagType) atoi((gchar*)start + 1);
-					break;
-				case TA_ARGLIST:
-					tag->arglist = g_strdup((gchar*)start + 1);
-					break;
-				case TA_SCOPE:
-					tag->scope = g_strdup((gchar*)start + 1);
-					break;
-				case TA_POINTER:
-					tag->pointerOrder = atoi((gchar*)start + 1);
-					break;
-				case TA_VARTYPE:
-					tag->var_type = g_strdup((gchar*)start + 1);
-					break;
-				case TA_INHERITS:
-					tag->inheritance = g_strdup((gchar*)start + 1);
-					break;
-				case TA_TIME:  /* Obsolete */
-					break;
-				case TA_LANG:  /* Obsolete */
-					break;
-				case TA_INACTIVE:  /* Obsolete */
-					break;
-				case TA_ACCESS:
-					tag->access = (char) *(start + 1);
-					break;
-				case TA_IMPL:
-					tag->impl = (char) *(start + 1);
-					break;
-				default:
-#ifdef GEANY_DEBUG
-					g_warning("Unknown attribute %s", start + 1);
-#endif
-					break;
-			}
-		}
-		*end = changed_char;
-	}
-	if (NULL == tag->name)
-		return FALSE;
-	tag->file = file;
-	return TRUE;
-}
-
-/* alternative parser for Pascal and LaTeX global tags files with the following format
- * tagname|return value|arglist|description\n */
-static gboolean tm_tag_init_from_file_alt(TMTag *tag, TMSourceFile *file, FILE *fp)
-{
-	guchar buf[BUFSIZ];
-	guchar *start, *end;
-	gboolean status;
-	/*guchar changed_char = TA_NAME;*/
-
 	tag->refcount = 1;
-	if ((NULL == fgets((gchar*)buf, BUFSIZ, fp)) || ('\0' == *buf))
-		return FALSE;
-	{
-		gchar **fields;
-		guint field_len;
-		for (start = end = buf, status = TRUE; (TRUE == status); start = end, ++ end)
-		{
-			while ((*end < TA_NAME) && (*end != '\0') && (*end != '\n'))
-				++ end;
-			if (('\0' == *end) || ('\n' == *end))
-				status = FALSE;
-			/*changed_char = *end;*/
-			*end = '\0';
-			if (NULL == tag->name && !isprint(*start))
-					return FALSE;
-
-			fields = g_strsplit((gchar*)start, "|", -1);
-			field_len = g_strv_length(fields);
-
-			if (field_len >= 1) tag->name = g_strdup(fields[0]);
-			else tag->name = NULL;
-			if (field_len >= 2 && fields[1] != NULL) tag->var_type = g_strdup(fields[1]);
-			if (field_len >= 3 && fields[2] != NULL) tag->arglist = g_strdup(fields[2]);
-			tag->type = tm_tag_prototype_t;
-			g_strfreev(fields);
-		}
-	}
 
-	if (NULL == tag->name)
-		return FALSE;
-	tag->file = file;
-	return TRUE;
-}
-
-/*
- Same as tm_tag_init_from_file(), but parsing CTags tag file format
- (http://ctags.sourceforge.net/FORMAT) 
-*/
-static gboolean tm_tag_init_from_file_ctags(TMTag *tag, TMSourceFile *file, FILE *fp)
-{
-	gchar buf[BUFSIZ];
-	gchar *p, *tab;
-
-	tag->refcount = 1;
-	tag->type = tm_tag_function_t; /* default type is function if no kind is specified */
-	do
-	{
-		if ((NULL == fgets(buf, BUFSIZ, fp)) || ('\0' == *buf))
-			return FALSE;
-	}
-	while (strncmp(buf, "!_TAG_", 6) == 0); /* skip !_TAG_ lines */
-
-	p = buf;
-
-	/* tag name */
-	if (! (tab = strchr(p, '\t')) || p == tab)
-		return FALSE;
-	tag->name = g_strndup(p, (gsize)(tab - p));
-	p = tab + 1;
-
-	/* tagfile, unused */
-	if (! (tab = strchr(p, '\t')))
-	{
-		g_free(tag->name);
-		tag->name = NULL;
-		return FALSE;
-	}
-	p = tab + 1;
-	/* Ex command, unused */
-	if (*p == '/' || *p == '?')
-	{
-		gchar c = *p;
-		for (++p; *p && *p != c; p++)
-		{
-			if (*p == '\\' && p[1])
-				p++;
-		}
-	}
-	else /* assume a line */
-		tag->line = atol(p);
-	tab = strstr(p, ";\"");
-	/* read extension fields */
-	if (tab)
-	{
-		p = tab + 2;
-		while (*p && *p != '\n' && *p != '\r')
-		{
-			gchar *end;
-			const gchar *key, *value = NULL;
-
-			/* skip leading tabulations */
-			while (*p && *p == '\t') p++;
-			/* find the separator (:) and end (\t) */
-			key = end = p;
-			while (*end && *end != '\t' && *end != '\n' && *end != '\r')
-			{
-				if (*end == ':' && ! value)
-				{
-					*end = 0; /* terminate the key */
-					value = end + 1;
-				}
-				end++;
-			}
-			/* move p paste the so we won't stop parsing by setting *end=0 below */
-			p = *end ? end + 1 : end;
-			*end = 0; /* terminate the value (or key if no value) */
-
-			if (! value || 0 == strcmp(key, "kind")) /* tag kind */
-			{
-				const gchar *kind = value ? value : key;
-
-				if (kind[0] && kind[1])
-					tag->type = get_tag_type(kind);
-				else
-				{
-					switch (*kind)
-					{
-						case 'c': tag->type = tm_tag_class_t; break;
-						case 'd': tag->type = tm_tag_macro_t; break;
-						case 'e': tag->type = tm_tag_enumerator_t; break;
-						case 'F': tag->type = tm_tag_other_t; break;  /* Obsolete */
-						case 'f': tag->type = tm_tag_function_t; break;
-						case 'g': tag->type = tm_tag_enum_t; break;
-						case 'I': tag->type = tm_tag_class_t; break;
-						case 'i': tag->type = tm_tag_interface_t; break;
-						case 'l': tag->type = tm_tag_variable_t; break;
-						case 'M': tag->type = tm_tag_macro_t; break;
-						case 'm': tag->type = tm_tag_member_t; break;
-						case 'n': tag->type = tm_tag_namespace_t; break;
-						case 'P': tag->type = tm_tag_package_t; break;
-						case 'p': tag->type = tm_tag_prototype_t; break;
-						case 's': tag->type = tm_tag_struct_t; break;
-						case 't': tag->type = tm_tag_typedef_t; break;
-						case 'u': tag->type = tm_tag_union_t; break;
-						case 'v': tag->type = tm_tag_variable_t; break;
-						case 'x': tag->type = tm_tag_externvar_t; break;
-						default:
-#ifdef TM_DEBUG
-							g_warning("Unknown tag kind %c", *kind);
-#endif
-							tag->type = tm_tag_other_t; break;
-					}
-				}
-			}
-			else if (0 == strcmp(key, "inherits")) /* comma-separated list of classes this class inherits from */
-			{
-				g_free(tag->inheritance);
-				tag->inheritance = g_strdup(value);
-			}
-			else if (0 == strcmp(key, "implementation")) /* implementation limit */
-				tag->impl = get_tag_impl(value);
-			else if (0 == strcmp(key, "line")) /* line */
-				tag->line = atol(value);
-			else if (0 == strcmp(key, "access")) /* access */
-				tag->access = get_tag_access(value);
-			else if (0 == strcmp(key, "class") ||
-					 0 == strcmp(key, "enum") ||
-					 0 == strcmp(key, "function") ||
-					 0 == strcmp(key, "struct") ||
-					 0 == strcmp(key, "union")) /* Name of the class/enum/function/struct/union in which this tag is a member */
-			{
-				g_free(tag->scope);
-				tag->scope = g_strdup(value);
-			}
-			else if (0 == strcmp(key, "file")) /* static (local) tag */
-				tag->local = TRUE;
-			else if (0 == strcmp(key, "signature")) /* arglist */
-			{
-				g_free(tag->arglist);
-				tag->arglist = g_strdup(value);
-			}
-		}
-	}
-
-	tag->file = file;
-	return TRUE;
-}
-
-/*
- Same as tm_tag_new() except that the tag attributes are read from file.
- @param mode TMParserType to use for the tag.
-*/
-TMTag *tm_tag_new_from_file(TMSourceFile *file, FILE *fp, TMParserType mode, TMFileFormat format)
-{
-	TMTag *tag;
-	gboolean result = FALSE;
-
-	TAG_NEW(tag);
-
-	switch (format)
-	{
-		case TM_FILE_FORMAT_TAGMANAGER:
-			result = tm_tag_init_from_file(tag, file, fp);
-			break;
-		case TM_FILE_FORMAT_PIPE:
-			result = tm_tag_init_from_file_alt(tag, file, fp);
-			break;
-		case TM_FILE_FORMAT_CTAGS:
-			result = tm_tag_init_from_file_ctags(tag, file, fp);
-			break;
-	}
-
-	if (! result)
-	{
-		TAG_FREE(tag);
-		return NULL;
-	}
-	tag->lang = mode;
 	return tag;
 }
 
 /*
- Writes tag information to the given FILE *.
- @param tag The tag information to write.
- @param file FILE pointer to which the tag information is written.
- @param attrs Attributes to be written (bitmask).
- @return TRUE on success, FALSE on failure.
-*/
-gboolean tm_tag_write(TMTag *tag, FILE *fp, TMTagAttrType attrs)
-{
-	fprintf(fp, "%s", tag->name);
-	if (attrs & tm_tag_attr_type_t)
-		fprintf(fp, "%c%d", TA_TYPE, tag->type);
-	if ((attrs & tm_tag_attr_arglist_t) && (NULL != tag->arglist))
-		fprintf(fp, "%c%s", TA_ARGLIST, tag->arglist);
-	if (attrs & tm_tag_attr_line_t)
-		fprintf(fp, "%c%ld", TA_LINE, tag->line);
-	if (attrs & tm_tag_attr_local_t)
-		fprintf(fp, "%c%d", TA_LOCAL, tag->local);
-	if ((attrs & tm_tag_attr_scope_t) && (NULL != tag->scope))
-		fprintf(fp, "%c%s", TA_SCOPE, tag->scope);
-	if ((attrs & tm_tag_attr_inheritance_t) && (NULL != tag->inheritance))
-		fprintf(fp, "%c%s", TA_INHERITS, tag->inheritance);
-	if (attrs & tm_tag_attr_pointer_t)
-		fprintf(fp, "%c%d", TA_POINTER, tag->pointerOrder);
-	if ((attrs & tm_tag_attr_vartype_t) && (NULL != tag->var_type))
-		fprintf(fp, "%c%s", TA_VARTYPE, tag->var_type);
-	if ((attrs & tm_tag_attr_access_t) && (TAG_ACCESS_UNKNOWN != tag->access))
-		fprintf(fp, "%c%c", TA_ACCESS, tag->access);
-	if ((attrs & tm_tag_attr_impl_t) && (TAG_IMPL_UNKNOWN != tag->impl))
-		fprintf(fp, "%c%c", TA_IMPL, tag->impl);
-
-	if (fprintf(fp, "\n"))
-		return TRUE;
-	else
-		return FALSE;
-}
-
-/*
  Destroys a TMTag structure, i.e. frees all elements except the tag itself.
  @param tag The TMTag structure to destroy
  @see tm_tag_free()
@@ -759,18 +237,19 @@ gboolean tm_tags_equal(const TMTag *a, const TMTag *b)
  Removes NULL tag entries from an array of tags. Called after tm_tags_dedup() since 
  this function substitutes duplicate entries with NULL
  @param tags_array Array of tags to dedup
- @return TRUE on success, FALSE on failure
 */
-gboolean tm_tags_prune(GPtrArray *tags_array)
+void tm_tags_prune(GPtrArray *tags_array)
 {
 	guint i, count;
+
+	g_return_if_fail(tags_array);
+
 	for (i=0, count = 0; i < tags_array->len; ++i)
 	{
 		if (NULL != tags_array->pdata[i])
 			tags_array->pdata[count++] = tags_array->pdata[i];
 	}
 	tags_array->len = count;
-	return TRUE;
 }
 
 /*
@@ -779,15 +258,16 @@ gboolean tm_tags_prune(GPtrArray *tags_array)
  @param tags_array Array of tags to dedup.
  @param sort_attributes Attributes the array is sorted on. They will be deduped
  on the same criteria.
- @return TRUE on success, FALSE on failure
 */
-gboolean tm_tags_dedup(GPtrArray *tags_array, TMTagAttrType *sort_attributes, gboolean unref_duplicates)
+void tm_tags_dedup(GPtrArray *tags_array, TMTagAttrType *sort_attributes, gboolean unref_duplicates)
 {
 	TMSortOptions sort_options;
 	guint i;
 
-	if ((!tags_array) || (!tags_array->len))
-		return TRUE;
+	g_return_if_fail(tags_array);
+	if (tags_array->len < 2)
+		return;
+
 	sort_options.sort_attrs = sort_attributes;
 	sort_options.partial = FALSE;
 	for (i = 1; i < tags_array->len; ++i)
@@ -800,7 +280,6 @@ gboolean tm_tags_dedup(GPtrArray *tags_array, TMTagAttrType *sort_attributes, gb
 		}
 	}
 	tm_tags_prune(tags_array);
-	return TRUE;
 }
 
 /*
@@ -809,21 +288,19 @@ gboolean tm_tags_dedup(GPtrArray *tags_array, TMTagAttrType *sort_attributes, gb
  @param tags_array The array of tags to be sorted
  @param sort_attributes Attributes to be sorted on (int array terminated by 0)
  @param dedup Whether to deduplicate the sorted array
- @return TRUE on success, FALSE on failure
 */
-gboolean tm_tags_sort(GPtrArray *tags_array, TMTagAttrType *sort_attributes, 
+void tm_tags_sort(GPtrArray *tags_array, TMTagAttrType *sort_attributes,
 	gboolean dedup, gboolean unref_duplicates)
 {
 	TMSortOptions sort_options;
-	
-	if ((!tags_array) || (!tags_array->len))
-		return TRUE;
+
+	g_return_if_fail(tags_array);
+
 	sort_options.sort_attrs = sort_attributes;
 	sort_options.partial = FALSE;
 	g_ptr_array_sort_with_data(tags_array, tm_tag_compare, &sort_options);
 	if (dedup)
 		tm_tags_dedup(tags_array, sort_attributes, unref_duplicates);
-	return TRUE;
 }
 
 void tm_tags_remove_file_tags(TMSourceFile *source_file, GPtrArray *tags_array)
@@ -1024,8 +501,9 @@ GPtrArray *tm_tags_extract(GPtrArray *tags_array, TMTagType tag_types)
 {
 	GPtrArray *new_tags;
 	guint i;
-	if (NULL == tags_array)
-		return NULL;
+
+	g_return_val_if_fail(tags_array, NULL);
+
 	new_tags = g_ptr_array_new();
 	for (i=0; i < tags_array->len; ++i)
 	{
@@ -1251,58 +729,19 @@ gboolean tm_tag_langs_compatible(TMParserType lang, TMParserType other)
 const char *tm_tag_type_name(const TMTag *tag)
 {
 	g_return_val_if_fail(tag, NULL);
-	switch(tag->type)
-	{
-		case tm_tag_class_t: return "class";
-		case tm_tag_enum_t: return "enum";
-		case tm_tag_enumerator_t: return "enumval";
-		case tm_tag_field_t: return "field";
-		case tm_tag_function_t: return "function";
-		case tm_tag_interface_t: return "interface";
-		case tm_tag_member_t: return "member";
-		case tm_tag_method_t: return "method";
-		case tm_tag_namespace_t: return "namespace";
-		case tm_tag_package_t: return "package";
-		case tm_tag_prototype_t: return "prototype";
-		case tm_tag_struct_t: return "struct";
-		case tm_tag_typedef_t: return "typedef";
-		case tm_tag_union_t: return "union";
-		case tm_tag_variable_t: return "variable";
-		case tm_tag_externvar_t: return "extern";
-		case tm_tag_macro_t: return "define";
-		case tm_tag_macro_with_arg_t: return "macro";
-		default: return NULL;
-	}
-	return NULL;
+
+	return tm_ctags_get_kind_name(tm_parser_get_tag_kind(tag->type, tag->lang), tag->lang);
 }
 
 /*
  Returns the TMTagType given the name of the type. Reverse of tm_tag_type_name.
  @param tag_name Name of the tag type
 */
-TMTagType tm_tag_name_type(const char* tag_name)
+TMTagType tm_tag_name_type(const char* tag_name, TMParserType lang)
 {
 	g_return_val_if_fail(tag_name, tm_tag_undef_t);
 
-	if (strcmp(tag_name, "class") == 0) return tm_tag_class_t;
-	else if (strcmp(tag_name, "enum") == 0) return tm_tag_enum_t;
-	else if (strcmp(tag_name, "enumval") == 0) return tm_tag_enumerator_t;
-	else if (strcmp(tag_name, "field") == 0) return tm_tag_field_t;
-	else if (strcmp(tag_name, "function") == 0) return tm_tag_function_t;
-	else if (strcmp(tag_name, "interface") == 0) return tm_tag_interface_t;
-	else if (strcmp(tag_name, "member") == 0) return tm_tag_member_t;
-	else if (strcmp(tag_name, "method") == 0) return tm_tag_method_t;
-	else if (strcmp(tag_name, "namespace") == 0) return tm_tag_namespace_t;
-	else if (strcmp(tag_name, "package") == 0) return tm_tag_package_t;
-	else if (strcmp(tag_name, "prototype") == 0) return tm_tag_prototype_t;
-	else if (strcmp(tag_name, "struct") == 0) return tm_tag_struct_t;
-	else if (strcmp(tag_name, "typedef") == 0) return tm_tag_typedef_t;
-	else if (strcmp(tag_name, "union") == 0) return tm_tag_union_t;
-	else if (strcmp(tag_name, "variable") == 0) return tm_tag_variable_t;
-	else if (strcmp(tag_name, "extern") == 0) return tm_tag_externvar_t;
-	else if (strcmp(tag_name, "define") == 0) return tm_tag_macro_t;
-	else if (strcmp(tag_name, "macro") == 0) return tm_tag_macro_with_arg_t;
-	else return tm_tag_undef_t;
+	return tm_parser_get_tag_type(tm_ctags_get_kind_from_name(tag_name, lang), lang);
 }
 
 static const char *tm_tag_impl_name(TMTag *tag)


Modified: tagmanager/src/tm_tag.h
70 lines changed, 7 insertions(+), 63 deletions(-)
===================================================================
@@ -30,48 +30,15 @@
 */
 
 #include "tm_source_file.h"
+#include "tm_parser.h"
 #include <glib-object.h>
 
-#ifdef __cplusplus
-extern "C"
-{
-#endif
+G_BEGIN_DECLS
 
 /** Use the TM_TAG() macro to cast a pointer to (TMTag *) */
 #define TM_TAG(tag) ((TMTag *) tag)
 
 /**
- Types of tags. It is a bitmask so that multiple tag types can
- be used simultaneously by 'OR'-ing them bitwise.
- e.g. tm_tag_class_t | tm_tag_struct_t
-*/
-typedef enum
-{
-	tm_tag_undef_t = 0, /**< Unknown type */
-	tm_tag_class_t = 1, /**< Class declaration */
-	tm_tag_enum_t = 2, /**< Enum declaration */
-	tm_tag_enumerator_t = 4, /**< Enumerator value */
-	tm_tag_field_t = 8, /**< Field (Java only) */
-	tm_tag_function_t = 16, /**< Function definition */
-	tm_tag_interface_t = 32, /**< Interface (Java only) */
-	tm_tag_member_t = 64, /**< Member variable of class/struct */
-	tm_tag_method_t = 128, /**< Class method (Java only) */
-	tm_tag_namespace_t = 256, /**< Namespace declaration */
-	tm_tag_package_t = 512, /**< Package (Java only) */
-	tm_tag_prototype_t = 1024, /**< Function prototype */
-	tm_tag_struct_t = 2048, /**< Struct declaration */
-	tm_tag_typedef_t = 4096, /**< Typedef */
-	tm_tag_union_t = 8192, /**< Union */
-	tm_tag_variable_t = 16384, /**< Variable */
-	tm_tag_externvar_t = 32768, /**< Extern or forward declaration */
-	tm_tag_macro_t = 65536, /**<  Macro (without arguments) */
-	tm_tag_macro_with_arg_t = 131072, /**< Parameterized macro */
-	tm_tag_file_t = 262144, /**< File (Pseudo tag) - obsolete */
-	tm_tag_other_t = 524288, /**< Other (non C/C++/Java tag) */
-	tm_tag_max_t = 1048575 /**< Maximum value of TMTagType */
-} TMTagType;
-
-/**
  Tag Attributes. Note that some attributes are available to file
  pseudotags only. Attributes are useful for specifying as arguments
  to the builtin sort and dedup functions, and during printing or writing
@@ -113,13 +80,6 @@ typedef enum
 #define TAG_IMPL_VIRTUAL 'v' /**< Virtual implementation */
 #define TAG_IMPL_UNKNOWN 'x' /**< Unknown implementation */
 
-/**
- This structure holds all information about a tag, including the file
- pseudo tag. It should always be created indirectly with one of the tag
- creation functions such as tm_source_file_parse() or tm_tag_new_from_file().
- Once created, they can be sorted, deduped, etc. using functions such as
- tm_tags_sort() or tm_tags_dedup()
-*/
 typedef struct _TMTag
 {
 	char *name; /**< Name of tag */
@@ -143,40 +103,26 @@ typedef struct _TMTag
 
 #ifdef GEANY_PRIVATE
 
-extern const TMTagType TM_GLOBAL_TYPE_MASK;
-
-
-typedef enum {
-	TM_FILE_FORMAT_TAGMANAGER,
-	TM_FILE_FORMAT_PIPE,
-	TM_FILE_FORMAT_CTAGS
-} TMFileFormat;
-
-
 /* The GType for a TMTag */
 #define TM_TYPE_TAG (tm_tag_get_type())
 
 GType tm_tag_get_type(void) G_GNUC_CONST;
 
-TMTag *tm_tag_new(TMSourceFile *file, const tagEntryInfo *tag_entry);
-
-TMTag *tm_tag_new_from_file(TMSourceFile *file, FILE *fp, TMParserType mode, TMFileFormat format);
-
-gboolean tm_tag_write(TMTag *tag, FILE *file, guint attrs);
+TMTag *tm_tag_new(void);
 
 void tm_tags_remove_file_tags(TMSourceFile *source_file, GPtrArray *tags_array);
 
 GPtrArray *tm_tags_merge(GPtrArray *big_array, GPtrArray *small_array, 
 	TMTagAttrType *sort_attributes, gboolean unref_duplicates);
 
-gboolean tm_tags_sort(GPtrArray *tags_array, TMTagAttrType *sort_attributes, 
+void tm_tags_sort(GPtrArray *tags_array, TMTagAttrType *sort_attributes,
 	gboolean dedup, gboolean unref_duplicates);@@ 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