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