[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