SF.net SVN: geany: [1411] trunk

ntrel at users.sourceforge.net ntrel at xxxxx
Wed Mar 21 13:26:17 UTC 2007


Revision: 1411
          http://svn.sourceforge.net/geany/?rev=1411&view=rev
Author:   ntrel
Date:     2007-03-21 06:26:16 -0700 (Wed, 21 Mar 2007)

Log Message:
-----------
Add option --generate-tags (-g) to generate a global tags file from
a list of source files. Currently this is only likely to work
correctly for C-like source files. Run 'geany -g' for syntax info.
Remove short option for hidden option --generate-data-files.
Update tm_workspace_create_global_tags() from Anjuta 1.2.4a.

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

Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2007-03-21 13:21:03 UTC (rev 1410)
+++ trunk/ChangeLog	2007-03-21 13:26:16 UTC (rev 1411)
@@ -2,6 +2,12 @@
 
  * src/project.c:
    Made all project dialogs modal.
+ * src/main.c, src/symbols.c, src/symbols.h, tagmanager/tm_workspace.c:
+   Add option --generate-tags (-g) to generate a global tags file from
+   a list of source files. Currently this is only likely to work
+   correctly for C-like source files. Run 'geany -g' for syntax info.
+   Remove short option for hidden option --generate-data-files.
+   Update tm_workspace_create_global_tags() from Anjuta 1.2.4a.
 
 
 2007-03-20  Enrico Tröger  <enrico.troeger at uvena.de>

Modified: trunk/src/main.c
===================================================================
--- trunk/src/main.c	2007-03-21 13:21:03 UTC (rev 1410)
+++ trunk/src/main.c	2007-03-21 13:26:16 UTC (rev 1411)
@@ -87,13 +87,15 @@
 static gboolean ignore_socket = FALSE;
 #endif
 static gboolean generate_datafiles = FALSE;
+static gboolean generate_tags = FALSE;
 
 static GOptionEntry entries[] =
 {
 	{ "column", 0, 0, G_OPTION_ARG_INT, &cl_options.goto_column, N_("set initial column number for the first opened file (useful in conjunction with --line)"), NULL },
 	{ "config", 'c', 0, G_OPTION_ARG_FILENAME, &alternate_config, N_("use an alternate configuration directory"), NULL },
 	{ "debug", 'd', 0, G_OPTION_ARG_NONE, &debug_mode, N_("runs in debug mode (means being verbose)"), NULL },
-	{ "generate-data-files", 'g', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &generate_datafiles, "", NULL },
+	{ "generate-tags", 'g', 0, G_OPTION_ARG_NONE, &generate_tags, N_("generate global tags file (see documentation)"), NULL },
+	{ "generate-data-files", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &generate_datafiles, "", NULL },
 #ifdef HAVE_SOCKET
 	{ "new-instance", 'i', 0, G_OPTION_ARG_NONE, &ignore_socket, N_("don't open files in a running instance, force opening a new instance"), NULL },
 #endif
@@ -433,7 +435,13 @@
 
 		exit(0);
 	}
+	if (generate_tags)
+	{
+		gboolean ret = symbols_generate_global_tags(*argc, *argv);
 
+		exit(ret);
+	}
+
 	app->debug_mode = debug_mode;
 #ifdef GEANY_DEBUG
 	geany_debug("debug mode built in (can't be disabled)");

Modified: trunk/src/symbols.c
===================================================================
--- trunk/src/symbols.c	2007-03-21 13:21:03 UTC (rev 1410)
+++ trunk/src/symbols.c	2007-03-21 13:26:16 UTC (rev 1411)
@@ -32,6 +32,7 @@
 
 #include <ctype.h>
 #include <string.h>
+#include <stdlib.h>
 
 #include "symbols.h"
 #include "utils.h"
@@ -688,3 +689,41 @@
 }
 
 
+/* Adapted from anjuta-2.0.2/global-tags/tm_global_tags.c, thanks.
+ * Needs full path and \" quoting characters around filenames.
+ * Example:
+ * geany -g tagsfile \"/home/nmt/svn/geany/src/d*.h\" */
+int symbols_generate_global_tags(int argc, char **argv)
+{
+	/* -E pre-process, -dD output user macros, -p prof info (?),
+	 * -undef remove builtin macros (seems to be needed with FC5 gcc 4.1.1 */
+	const char pre_process[] = "gcc -E -dD -p -undef";
+
+	if (argc > 2)
+	{
+		/* Create global taglist */
+		int status;
+		char *command;
+		command = g_strdup_printf("%s %s", pre_process,
+								  NVL(getenv("CFLAGS"), ""));
+		//printf(">%s<\n", command);
+		status = tm_workspace_create_global_tags(command,
+												 (const char **) (argv + 2),
+												 argc - 2, argv[1]);
+		g_free(command);
+		if (!status)
+			return 1;
+	}
+	else
+	{
+		fprintf(stderr, "Usage: %s -g <Tag File> <File list>\n\n", argv[0]);
+		fprintf(stderr, "Each file in <File list> must be enclosed in double quotes.\n");
+		fprintf(stderr, "Example:\n"
+			"CFLAGS=`pkg-config gtk+-2.0 --cflags` %s -g gtk2.c.tags"
+			" \\\"/usr/include/gtk-2.0/gtk/gtk.h\\\"\n", argv[0]);
+		return 1;
+	}
+	return 0;
+}
+
+

Modified: trunk/src/symbols.h
===================================================================
--- trunk/src/symbols.h	2007-03-21 13:21:03 UTC (rev 1410)
+++ trunk/src/symbols.h	2007-03-21 13:26:16 UTC (rev 1411)
@@ -48,4 +48,6 @@
 
 gboolean symbols_recreate_tag_list(gint idx);
 
+int symbols_generate_global_tags(int argc, char **argv);
+
 #endif

Modified: trunk/tagmanager/tm_workspace.c
===================================================================
--- trunk/tagmanager/tm_workspace.c	2007-03-21 13:21:03 UTC (rev 1410)
+++ trunk/tagmanager/tm_workspace.c	2007-03-21 13:26:16 UTC (rev 1411)
@@ -33,6 +33,7 @@
 #include "tm_workspace.h"
 #include "tm_project.h"
 
+
 static TMWorkspace *theWorkspace = NULL;
 guint workspace_class_id = 0;
 
@@ -156,6 +157,31 @@
 	return TRUE;
 }
 
+static guint tm_file_inode_hash(gconstpointer key)
+{
+	struct stat file_stat;
+	const char *filename = (const char*)key;
+	if (stat(filename, &file_stat) == 0)
+	{
+#ifdef TM_DEBUG
+		g_message ("Hash for '%s' is '%d'\n", filename, file_stat.st_ino);
+#endif
+		return g_direct_hash (GUINT_TO_POINTER (file_stat.st_ino));
+	} else {
+		return 0;
+	}
+}
+
+static void tm_move_entries_to_g_list(gpointer key, gpointer value, gpointer user_data)
+{
+	GList **pp_list = (GList**)user_data;
+
+	if (user_data == NULL)
+		return;
+
+	*pp_list = g_list_prepend(*pp_list, value);
+}
+
 gboolean tm_workspace_create_global_tags(const char *pre_process, const char **includes
   , int includes_count, const char *tags_file)
 {
@@ -169,11 +195,9 @@
 	FILE *fp;
 	TMWorkObject *source_file;
 	GPtrArray *tags_array;
+	GHashTable *includes_files_hash;
 	GList *includes_files = NULL;
-	guint list_len;
-	guint idx_main;
-	guint idx_sub;
-	int remove_count = 0;
+	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));
@@ -181,11 +205,18 @@
 	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));
 #endif
-	TMTagAttrType sort_attrs[] = { tm_tag_attr_name_t, tm_tag_attr_scope_t
-		, tm_tag_attr_type_t, 0};
+	TMTagAttrType sort_attrs[] = {
+		tm_tag_attr_name_t, tm_tag_attr_scope_t,
+		tm_tag_attr_type_t, 0
+	};
+
 	if (NULL == (fp = fopen(temp_file, "w")))
 		return FALSE;
 
+	includes_files_hash = g_hash_table_new_full (tm_file_inode_hash,
+												 g_direct_equal,
+												 NULL, g_free);
+
 #ifdef HAVE_GLOB_H
 	globbuf.gl_offs = 0;
 	for(idx_inc = 0; idx_inc < includes_count; idx_inc++)
@@ -195,91 +226,87 @@
 		strncpy(clean_path, includes[idx_inc] + 1, dirty_len - 1);
 		clean_path[dirty_len - 2] = 0;
 
-		//printf("[o][%s]\n", clean_path);
+#ifdef TM_DEBUG
+		g_message ("[o][%s]\n", clean_path);
+#endif
 		glob(clean_path, 0, NULL, &globbuf);
-		//printf("matches: %d\n", globbuf.gl_pathc);
+
+#ifdef TM_DEBUG
+		g_message ("matches: %d\n", globbuf.gl_pathc);
+#endif
+
 		for(idx_glob = 0; idx_glob < globbuf.gl_pathc; idx_glob++)
 		{
-			includes_files = g_list_append(includes_files, strdup(globbuf.gl_pathv[idx_glob]));
-			//printf(">>> %s\n", globbuf.gl_pathv[idx_glob]);
+#ifdef TM_DEBUG
+			g_message (">>> %s\n", globbuf.gl_pathv[idx_glob]);
+#endif
+			if (!g_hash_table_lookup(includes_files_hash,
+									globbuf.gl_pathv[idx_glob]))
+			{
+				char* file_name_copy = strdup(globbuf.gl_pathv[idx_glob]);
+				g_hash_table_insert(includes_files_hash, file_name_copy,
+									file_name_copy);
+#ifdef TM_DEBUG
+				g_message ("Added ...\n");
+#endif
+			}
 		}
 		globfree(&globbuf);
 		free(clean_path);
   	}
-#else
+#else	// no glob support
 	for(idx_inc = 0; idx_inc < includes_count; idx_inc++)
 	{
- 		includes_files = g_list_append(includes_files, strdup(includes[idx_inc]));
+		if (!g_hash_table_lookup(includes_files_hash,
+									includes[idx_inc]))
+		{
+			char* file_name_copy = strdup(includes[idx_inc]);
+			g_hash_table_insert(includes_files_hash, file_name_copy,
+								file_name_copy);
+		}
   	}
 #endif
 
 
 	/* Checks for duplicate file entries which would case trouble */
-	{
-		struct stat main_stat;
-		struct stat sub_stat;
+	g_hash_table_foreach(includes_files_hash, tm_move_entries_to_g_list,
+						 &includes_files);
 
-		remove_count = 0;
+	includes_files = g_list_reverse (includes_files);
 
-		list_len = g_list_length(includes_files);
-
-		/* We look for files with the same inode */
-		for(idx_main = 0; idx_main < list_len; idx_main++)
-		{
-//			printf("%d / %d\n", idx_main, list_len - 1);
-			stat(g_list_nth_data(includes_files, idx_main), &main_stat);
-			for(idx_sub = idx_main + 1; idx_sub < list_len; idx_sub++)
-			{
-				GList *element = NULL;
-
-				stat(g_list_nth_data(includes_files, idx_sub), &sub_stat);
-
-
-				if(main_stat.st_ino != sub_stat.st_ino)
-					continue;
-
-				/* Inodes match */
-
-				element = g_list_nth(includes_files, idx_sub);
-
-/*				printf("%s == %s\n", g_list_nth_data(includes_files, idx_main),
-										 g_list_nth_data(includes_files, idx_sub)); */
-
-				/* We delete the duplicate entry from the list */
-				includes_files = g_list_remove_link(includes_files, element);
-				remove_count++;
-
-				/* Don't forget to free the mallocs (we duplicated every string earlier!) */
-				free(element->data);
-
-				idx_sub--; /* Cause the inner loop not to move; good since we removed
-							   an element at the current position; we don't have to worry
-							   about the outer loop because the inner loop always starts
-							   after the outer loop's index */
-
-				list_len = g_list_length(includes_files);
-			}
-		}
-	}
-
-
-	printf("writing out files to %s\n", temp_file);
-	for(idx_main = 0; idx_main < g_list_length(includes_files); idx_main++)
+#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*)g_list_nth_data(includes_files,
-														   idx_main));
+		char *str = g_strdup_printf("#include \"%s\"\n", (char*)node->data);
 		int str_len = strlen(str);
 
 		fwrite(str, str_len, 1, fp);
-
 		free(str);
-		free(g_list_nth(includes_files, idx_main) -> data);
+		node = g_list_next (node);
 	}
 
+	g_list_free (includes_files);
+	g_hash_table_destroy(includes_files_hash);
+	includes_files_hash = NULL;
+	includes_files = NULL;
 	fclose(fp);
 
-	command = g_strdup_printf("%s %s >%s", pre_process, temp_file, temp_file2);
+	/* FIXME: The following grep command it be remove the lines 
+	 * G_BEGIN_DECLS and G_END_DECLS from the header files. The reason is
+	 * that in tagmanager, the files are not correctly parsed and the typedefs
+	 * 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",
+							  pre_process, temp_file, temp_file2);
+
+#ifdef TM_DEBUG
+	g_message("Executing: %s", command);
+#endif
+
 	system(command);
 	g_free(command);
 	unlink(temp_file);


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