SF.net SVN: geany: [1480] trunk

ntrel at users.sourceforge.net ntrel at xxxxx
Fri Apr 27 11:00:30 UTC 2007


Revision: 1480
          http://svn.sourceforge.net/geany/?rev=1480&view=rev
Author:   ntrel
Date:     2007-04-27 04:00:29 -0700 (Fri, 27 Apr 2007)

Log Message:
-----------
Add support for generating global tags files for non-C-like
filetypes.

Modified Paths:
--------------
    trunk/ChangeLog
    trunk/src/main.c
    trunk/src/symbols.c
    trunk/tagmanager/include/tm_workspace.h
    trunk/tagmanager/tm_workspace.c

Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2007-04-27 10:58:41 UTC (rev 1479)
+++ trunk/ChangeLog	2007-04-27 11:00:29 UTC (rev 1480)
@@ -1,3 +1,14 @@
+2007-04-26  Nick Treleaven  <nick.treleaven at btinternet.com>
+
+ * tagmanager/tm_source_file.c, tagmanager/include/tm_source_file.h:
+   Add tm_source_file_get_lang_name() as a wrapper for getLanguageName()
+   in parse.c.
+ * src/main.c, src/symbols.c, tagmanager/tm_workspace.c,
+   tagmanager/include/tm_workspace.h:
+   Add support for generating global tags files for non-C-like
+   filetypes.
+
+
 2007-04-25  Nick Treleaven  <nick.treleaven at btinternet.com>
 
  * src/filetypes.c, src/filetypes.h, src/main.c:

Modified: trunk/src/main.c
===================================================================
--- trunk/src/main.c	2007-04-27 10:58:41 UTC (rev 1479)
+++ trunk/src/main.c	2007-04-27 11:00:29 UTC (rev 1480)
@@ -467,6 +467,8 @@
 	{
 		gboolean ret;
 
+		filetypes_init_types();
+		configuration_read_filetype_extensions();	// needed for *.lang.tags filetype matching
 		ret = symbols_generate_global_tags(*argc, *argv);
 		exit(ret);
 	}

Modified: trunk/src/symbols.c
===================================================================
--- trunk/src/symbols.c	2007-04-27 10:58:41 UTC (rev 1479)
+++ trunk/src/symbols.c	2007-04-27 11:00:29 UTC (rev 1480)
@@ -704,10 +704,33 @@
 }
 
 
+/* Detects a global tags filetype from the *.lang.* language extension.
+ * Returns NULL if there was no matching TM language. */
+static filetype *detect_global_tags_filetype(const gchar *utf8_filename)
+{
+	gchar *tags_ext;
+	gchar *shortname = g_strdup(utf8_filename);
+	filetype *ft = NULL;
+
+	tags_ext = strstr(shortname, ".tags");
+	if (tags_ext)
+	{
+		*tags_ext = '\0';	// remove .tags extension
+		ft = filetypes_detect_from_filename(shortname);
+	}
+	g_free(shortname);
+
+	if (filetypes[FILETYPE_ID(ft)]->lang < 0)
+		return NULL;
+	return ft;
+}
+
+
 /* Adapted from anjuta-2.0.2/global-tags/tm_global_tags.c, thanks.
- * Needs full path and \" quoting characters around filenames.
+ * Needs full paths for filenames, except for C/C++ tag files, when CFLAGS includes
+ * the relevant path.
  * Example:
- * geany -g tagsfile \"/home/nmt/svn/geany/src/d*.h\" */
+ * CFLAGS=-I/home/user/libname-1.x geany -g libname.d.tags libname.h */
 int symbols_generate_global_tags(int argc, char **argv)
 {
 	/* -E pre-process, -dD output user macros, -p prof info (?),
@@ -719,15 +742,34 @@
 		/* Create global taglist */
 		int status;
 		char *command;
-		command = g_strdup_printf("%s %s", pre_process,
-								  NVL(getenv("CFLAGS"), ""));
-		//printf(">%s<\n", command);
+		const char *tags_file = argv[1];
+		char *utf8_fname;
+		filetype *ft;
+
+		utf8_fname = utils_get_utf8_from_locale(tags_file);
+		ft = detect_global_tags_filetype(utf8_fname);
+		g_free(utf8_fname);
+
+		if (ft == NULL)
+		{
+			fprintf(stderr, "Unknown filetype extension for \"%s\".\n", tags_file);
+			return 1;
+		}
+		if (ft->lang == 0 || ft->lang == 1)	/* C/C++ */
+			command = g_strdup_printf("%s %s", pre_process, NVL(getenv("CFLAGS"), ""));
+		else
+			command = NULL;	// don't preprocess
+
+		geany_debug("Generating %s tags file.", ft->name);
 		status = tm_workspace_create_global_tags(command,
 												 (const char **) (argv + 2),
-												 argc - 2, argv[1]);
+												 argc - 2, tags_file, ft->lang);
 		g_free(command);
-		if (!status)
+		if (! status)
+		{
+			fprintf(stderr, "Failed to create tags file.\n");
 			return 1;
+		}
 	}
 	else
 	{
@@ -741,34 +783,6 @@
 }
 
 
-// fname should be in locale encoding
-static gboolean load_tags_filename(const gchar *fname)
-{
-	gchar *tags_ext;
-	gchar *shortname = g_strdup(fname);
-	gboolean ret = FALSE;
-
-	tags_ext = strstr(shortname, ".tags");
-	if (tags_ext)
-	{
-		gchar *utf8_shortname;
-		filetype *ft;
-
-		*tags_ext = '\0';	// remove .tags extension
-		utf8_shortname = utils_get_utf8_from_locale(shortname);
-		ft = filetypes_detect_from_filename(utf8_shortname);
-		g_free(utf8_shortname);
-
-		if (ft)
-		{
-			ret = tm_workspace_load_global_tags(fname, ft->lang);
-		}
-	}
-	g_free(shortname);
-	return ret;
-}
-
-
 void symbols_show_load_tags_dialog()
 {
 	GtkWidget *dialog;
@@ -793,13 +807,16 @@
 		{
 			gchar *fname = item->data;
 			gchar *utf8_fname;
-			gboolean ok;
+			filetype *ft;
 
-			ok = load_tags_filename(fname);
+			utf8_fname = utils_get_utf8_from_locale(fname);
+			ft = detect_global_tags_filetype(utf8_fname);
 
-			utf8_fname = utils_get_utf8_from_locale(fname);
-			msgwin_status_add(ok ? _("Loaded tags file '%s'.") :
-				_("Could not load tags file '%s'."), utf8_fname);
+			if (ft != NULL && tm_workspace_load_global_tags(fname, ft->lang))
+				msgwin_status_add(_("Loaded %s tags file '%s'."), ft->name, utf8_fname);
+			else
+				msgwin_status_add(_("Could not load tags file '%s'."), utf8_fname);
+
 			g_free(utf8_fname);
 			g_free(fname);
 		}

Modified: trunk/tagmanager/include/tm_workspace.h
===================================================================
--- trunk/tagmanager/include/tm_workspace.h	2007-04-27 10:58:41 UTC (rev 1479)
+++ trunk/tagmanager/include/tm_workspace.h	2007-04-27 11:00:29 UTC (rev 1480)
@@ -100,10 +100,11 @@
  \param includes Include files to process. Wildcards such as '/usr/include/a*.h'
  are allowed.
  \param tags_file The file where the tags will be stored.
+ \param lang The language to use for the tags file.
  \return TRUE on success, FALSE on failure.
 */
 gboolean tm_workspace_create_global_tags(const char *pre_process, const char **includes
-  , int includes_count, const char *tags_file);
+  , int includes_count, const char *tags_file, int lang);
 
 /*! Recreates the tag array of the workspace by collecting the tags of
  all member work objects. You shouldn't have to call this directly since

Modified: trunk/tagmanager/tm_workspace.c
===================================================================
--- trunk/tagmanager/tm_workspace.c	2007-04-27 10:58:41 UTC (rev 1479)
+++ trunk/tagmanager/tm_workspace.c	2007-04-27 11:00:29 UTC (rev 1480)
@@ -187,8 +187,68 @@
 	*pp_list = g_list_prepend(*pp_list, value);
 }
 
+static void write_includes_file(FILE *fp, GList *includes_files)
+{
+	GList *node;
+
+	node = includes_files;
+	while (node)
+	{
+		char *str = g_strdup_printf("#include \"%s\"\n", (char*)node->data);
+		int str_len = strlen(str);
+
+		fwrite(str, str_len, 1, fp);
+		free(str);
+		node = g_list_next (node);
+	}
+}
+
+
+static void append_to_temp_file(FILE *fp, GList *file_list)
+{
+	GList *node;
+
+	node = file_list;
+	while (node)
+	{
+		const char *fname = node->data;
+		char *contents;
+		size_t length;
+		GError *err = NULL;
+
+		if (! g_file_get_contents(fname, &contents, &length, &err))
+		{
+			fprintf(stderr, "Unable to read file: %s\n", err->message);
+			g_error_free(err);
+		}
+		else
+		{
+			fwrite(contents, length, 1, fp);
+			fwrite("\n", 1, 1, fp);	// in case file doesn't end in newline (e.g. windows).
+			g_free(contents);
+		}
+		node = g_list_next (node);
+	}
+}
+
+static gint get_global_tag_type_mask(gint lang)
+{
+	switch (lang)
+	{
+		case 0:
+		case 1:
+			// C/C++
+			return tm_tag_class_t | tm_tag_typedef_t | tm_tag_enum_t | tm_tag_enumerator_t |
+				tm_tag_prototype_t |
+				tm_tag_function_t | tm_tag_method_t |	// for inline functions
+				tm_tag_macro_t | tm_tag_macro_with_arg_t;
+		default:
+			return tm_tag_max_t;
+	}
+}
+
 gboolean tm_workspace_create_global_tags(const char *pre_process, const char **includes
-  , int includes_count, const char *tags_file)
+  , int includes_count, const char *tags_file, int lang)
 {
 #ifdef HAVE_GLOB_H
 	glob_t globbuf;
@@ -202,7 +262,6 @@
 	GPtrArray *tags_array;
 	GHashTable *includes_files_hash;
 	GList *includes_files = NULL;
-	GList *node;
 #ifdef G_OS_WIN32
 	char *temp_file = g_strdup_printf("%s_%d_%ld_1.cpp", P_tmpdir, getpid(), time(NULL));
 	char *temp_file2 = g_strdup_printf("%s_%d_%ld_2.cpp", P_tmpdir, getpid(), time(NULL));
@@ -259,6 +318,7 @@
   	}
   	else
 #endif
+	// no glob support or globbing not wanted
 	for(idx_inc = 0; idx_inc < includes_count; idx_inc++)
 	{
 		if (!g_hash_table_lookup(includes_files_hash,
@@ -279,17 +339,11 @@
 #ifdef TM_DEBUG
 	g_message ("writing out files to %s\n", temp_file);
 #endif
-	node = includes_files;
-	while (node)
-	{
-		char *str = g_strdup_printf("#include \"%s\"\n", (char*)node->data);
-		int str_len = strlen(str);
+	if (pre_process != NULL)
+		write_includes_file(fp, includes_files);
+	else
+		append_to_temp_file(fp, includes_files);
 
-		fwrite(str, str_len, 1, fp);
-		free(str);
-		node = g_list_next (node);
-	}
-
 	g_list_free (includes_files);
 	g_hash_table_destroy(includes_files_hash);
 	includes_files_hash = NULL;
@@ -302,18 +356,26 @@
 	 * following these lines are incorrectly parsed. The real fix should,
 	 * of course be in tagmanager (c) parser. This is just a temporary fix.
 	 */
-	command = g_strdup_printf("%s %s | grep -v -E '^\\s*(G_BEGIN_DECLS|G_END_DECLS)\\s*$' > %s",
+	if (pre_process != NULL)
+	{
+		command = g_strdup_printf("%s %s | grep -v -E '^\\s*(G_BEGIN_DECLS|G_END_DECLS)\\s*$' > %s",
 							  pre_process, temp_file, temp_file2);
-
 #ifdef TM_DEBUG
-	g_message("Executing: %s", command);
+		g_message("Executing: %s", command);
 #endif
-
-	system(command);
-	g_free(command);
-	unlink(temp_file);
-	g_free(temp_file);
-	source_file = tm_source_file_new(temp_file2, TRUE, NULL);
+		system(command);
+		g_free(command);
+		unlink(temp_file);
+		g_free(temp_file);
+	}
+	else
+	{
+		// no pre-processing needed, so temp_file2 = temp_file
+		g_free(temp_file2);
+		temp_file2 = temp_file;
+		temp_file = NULL;
+	}
+	source_file = tm_source_file_new(temp_file2, TRUE, tm_source_file_get_lang_name(lang));
 	if (NULL == source_file)
 	{
 		unlink(temp_file2);
@@ -326,10 +388,7 @@
 		tm_source_file_free(source_file);
 		return FALSE;
 	}
-	tags_array = tm_tags_extract(source_file->tags_array, tm_tag_class_t |
-	  tm_tag_typedef_t | tm_tag_enum_t | tm_tag_enumerator_t |
-	  tm_tag_prototype_t | tm_tag_function_t | tm_tag_method_t |	// for inline functions
-	  tm_tag_macro_t | tm_tag_macro_with_arg_t);
+	tags_array = tm_tags_extract(source_file->tags_array, get_global_tag_type_mask(lang));
 	if ((NULL == tags_array) || (0 == tags_array->len))
 	{
 		if (tags_array)


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.



More information about the Commits mailing list