[geany/geany] 103d2c: Move code related to various tag file formats into tm_source_file.c

Jiří Techet git-noreply at xxxxx
Fri Jun 10 21:57:23 UTC 2016


Branch:      refs/heads/master
Author:      Jiří Techet <techet at gmail.com>
Committer:   Jiří Techet <techet at gmail.com>
Date:        Mon, 21 Mar 2016 17:28:36 UTC
Commit:      103d2c535862ae2682022dcfd714c2ffd983c42f
             https://github.com/geany/geany/commit/103d2c535862ae2682022dcfd714c2ffd983c42f

Log Message:
-----------
Move code related to various tag file formats into tm_source_file.c

This patch moves code related to reading/writing various tag file formats
into form TMTag and TMWorkspace to TMSourceFile. The benefits of this
change are:

* only tm_source_file.c interfaces with ctags after this change
* tagEntryInfo is removed from headers, no redefinitions needed any more
* source code is more evenly distributed among tm_source_file.c,
  tm_tag.c and tm_workspace.c after the change (tm_tag.c got smaller)
* all tag reading/writing is at a single place

Despite its size, this patch mostly just moves code. Notable changes are:

* tm_tag_new() now creates just an empty tag. The tag is filled by various
  init_* functions inside tm_source_file.c
* there are new functions tm_source_file_read_tags_file() and
  tm_source_file_write_tags_file() - these hide tags file
  reading/writing details from tm_workspace.c
* tm_source_file_write() debugging function got removed -
  tm_source_file_write_tags_file() does a similar thing and there's no
  need to keep around two functions doing the same.


Modified Paths:
--------------
    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_workspace.c

Modified: tagmanager/src/tm_source_file.c
624 lines changed, 587 insertions(+), 37 deletions(-)
===================================================================
@@ -31,7 +31,6 @@
 #include "parse.h"
 #include "read.h"
 
-#define LIBCTAGS_DEFINED
 #include "tm_source_file.h"
 #include "tm_tag.h"
 #include "tm_parser.h"
@@ -42,6 +41,77 @@ typedef struct
 	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
+};
+
+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
+};
+
+
 #define SOURCE_FILE_NEW(S) ((S) = g_slice_new(TMSourceFilePriv))
 #define SOURCE_FILE_FREE(S) g_slice_free(TMSourceFilePriv, (TMSourceFilePriv *) S)
 
@@ -107,6 +177,519 @@ gchar *tm_get_real_path(const gchar *file_name)
 	return NULL;
 }
 
+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 init_tag(TMTag *tag, TMSourceFile *file, const tagEntryInfo *tag_entry)
+{
+	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;
+}
+
+/*
+ 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 init_tag_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 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)
+{
+	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;
+}
+
+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);
+			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, *new_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;
+
+	g_return_val_if_fail(tags_array && tags_file, FALSE);
+
+	fp = g_fopen(tags_file, "w");
+	if (!fp)
+		return FALSE;
+
+	fprintf(fp, "# format=tagmanager\n");
+	for (i = 0; i < tags_array->len; i++)
+	{
+		TMTag *tag = TM_TAG(tags_array->pdata[i]);
+
+		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);
+	}
+	fclose(fp);
+
+	return TRUE;
+}
+
 /* add argument list of __init__() Python methods to the class tag */
 static void update_python_arglist(const TMTag *tag, TMSourceFile *current_source_file)
 {
@@ -145,7 +728,9 @@ static void update_python_arglist(const TMTag *tag, TMSourceFile *current_source
 static int tm_source_file_tags(const tagEntryInfo *tag, void *user_data)
 {
 	TMSourceFile *current_source_file = user_data;
-	TMTag *tm_tag = tm_tag_new(current_source_file, tag);
+	TMTag *tm_tag = tm_tag_new();
+
+	init_tag(tm_tag, current_source_file, tag);
 
 	if (tm_tag->lang == TM_PARSER_PYTHON)
 		update_python_arglist(tm_tag, current_source_file);
@@ -405,38 +990,3 @@ TMParserType tm_source_file_get_named_lang(const gchar *name)
 {
 	return getNamedLanguage(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
9 lines changed, 4 insertions(+), 5 deletions(-)
===================================================================
@@ -16,10 +16,6 @@
 
 #include "tm_parser.h"
 
-#ifndef LIBCTAGS_DEFINED
-typedef void tagEntryInfo;
-#endif
-
 G_BEGIN_DECLS
 
 /* Casts a pointer to a pointer to a TMSourceFile structure */
@@ -50,7 +46,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);
@@ -60,6 +55,10 @@ 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 */
 
 G_END_DECLS


Modified: tagmanager/src/tm_tag.c
527 lines changed, 2 insertions(+), 525 deletions(-)
===================================================================
@@ -11,13 +11,7 @@
 #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"
 
 
 #define TAG_NEW(T)	((T) = g_slice_new0(TMTag))
@@ -79,32 +73,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 +81,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 +93,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()


Modified: tagmanager/src/tm_tag.h
23 lines changed, 1 insertions(+), 22 deletions(-)
===================================================================
@@ -110,13 +110,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 */
@@ -140,26 +133,12 @@ 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);
 


Modified: tagmanager/src/tm_workspace.c
69 lines changed, 10 insertions(+), 59 deletions(-)
===================================================================
@@ -60,6 +60,10 @@ static TMTagType TM_TYPE_WITH_MEMBERS =
 	tm_tag_class_t | tm_tag_struct_t | tm_tag_union_t |
 	tm_tag_enum_t | tm_tag_interface_t;
 
+static 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;
+
 static TMWorkspace *theWorkspace = NULL;
 
 
@@ -342,54 +346,12 @@ void tm_workspace_remove_source_files(GPtrArray *source_files)
 */
 gboolean tm_workspace_load_global_tags(const char *tags_file, TMParserType mode)
 {
-	guchar buf[BUFSIZ];
-	FILE *fp;
 	GPtrArray *file_tags, *new_tags;
-	TMTag *tag;
-	TMFileFormat format = TM_FILE_FORMAT_TAGMANAGER;
 
-	if (NULL == (fp = g_fopen(tags_file, "r")))
+	file_tags = tm_source_file_read_tags_file(tags_file, mode);
+	if (!file_tags)
 		return FALSE;
-	if ((NULL == fgets((gchar*) buf, BUFSIZ, fp)) || ('\0' == *buf))
-	{
-		fclose(fp);
-		return FALSE; /* 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 = tm_tag_new_from_file(NULL, fp, mode, format)))
-		g_ptr_array_add(file_tags, tag);
-	fclose(fp);
-	
+
 	tm_tags_sort(file_tags, global_tags_sort_attrs, TRUE, TRUE);
 
 	/* reorder the whole array, because tm_tags_find expects a sorted array */
@@ -521,6 +483,7 @@ gboolean tm_workspace_create_global_tags(const char *pre_process, const char **i
 	GList *includes_files = NULL;
 	gchar *temp_file = create_temp_file("tmp_XXXXXX.cpp");
 	gchar *temp_file2 = create_temp_file("tmp_XXXXXX.cpp");
+	gboolean ret;
 
 	if (NULL == temp_file || NULL == temp_file2 ||
 		NULL == (fp = g_fopen(temp_file, "w")))
@@ -669,22 +632,10 @@ gboolean tm_workspace_create_global_tags(const char *pre_process, const char **i
 		tm_source_file_free(source_file);
 		return FALSE;
 	}
-	if (NULL == (fp = g_fopen(tags_file, "w")))
-	{
-		tm_source_file_free(source_file);
-		return FALSE;
-	}
-	fprintf(fp, "# format=tagmanager\n");
-	for (i = 0; i < tags_array->len; ++i)
-	{
-		tm_tag_write(TM_TAG(tags_array->pdata[i]), 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);
-	}
-	fclose(fp);
+	ret = tm_source_file_write_tags_file(tags_file, tags_array);
 	tm_source_file_free(source_file);
 	g_ptr_array_free(tags_array, TRUE);
-	return TRUE;
+	return ret;
 }
 
 



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