/* Creates a list of global tags. Ideally, this should be created once during installations so that all users can use the same file. This is because a full scale global tag list can occupy several megabytes of disk space. @param pre_process The pre-processing command. This is executed via system(), so you can pass stuff like 'gcc -E -dD -P `gnome-config --cflags gnome`'. @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, TMParserType lang) { gboolean ret = FALSE; TMSourceFile *source_file; GList *includes_files; gchar *temp_file = create_temp_file("tmp_XXXXXX.cpp"); if (!temp_file) return FALSE; includes_files = lookup_includes(includes, includes_count); #ifdef TM_DEBUG g_message ("writing out files to %s\n", temp_file); #endif if (pre_process) ret = write_includes_file(temp_file, includes_files); else ret = combine_include_files(temp_file, includes_files); g_list_free_full(includes_files, g_free); if (!ret) goto cleanup; ret = FALSE; if (pre_process) { gchar *temp_file2 = pre_process_file(pre_process, temp_file); if (temp_file2) { g_unlink(temp_file); g_free(temp_file); temp_file = temp_file2; } else goto cleanup; } source_file = tm_source_file_new(temp_file, tm_source_file_get_lang_name(lang)); if (!source_file) goto cleanup; update_source_file(source_file, NULL, 0, FALSE, FALSE); if (source_file->tags_array->len == 0) { tm_source_file_free(source_file); goto cleanup; } tm_tags_sort(source_file->tags_array, global_tags_sort_attrs, TRUE, FALSE); ret = tm_source_file_write_tags_file(tags_file, source_file->tags_array); tm_source_file_free(source_file); cleanup: g_unlink(temp_file); g_free(temp_file); return ret; }
static void workspace_add_tag(gchar *filename, TagObject *obj, gpointer foo) { TMWorkObject *tm_obj = NULL; if (!document_find_by_filename(filename)) { gchar *locale_filename; locale_filename = utils_get_locale_from_utf8(filename); tm_obj = tm_source_file_new(locale_filename, FALSE, filetypes_detect_from_file(filename)->name); g_free(locale_filename); if (tm_obj) { tm_workspace_add_object(tm_obj); tm_source_file_update(tm_obj, TRUE, FALSE, TRUE); } } if (obj->tag) tm_workspace_remove_object(obj->tag, TRUE, TRUE); obj->tag = tm_obj; }
/* Creates a list of global tags. Ideally, this should be created once during installations so that all users can use the same file. This is because a full scale global tag list can occupy several megabytes of disk space. @param pre_process The pre-processing command. This is executed via system(), so you can pass stuff like 'gcc -E -dD -P `gnome-config --cflags gnome`'. @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, TMParserType lang) { #ifdef HAVE_GLOB_H glob_t globbuf; size_t idx_glob; #endif int idx_inc; char *command; guint i; FILE *fp; TMSourceFile *source_file; GPtrArray *tags_array; GHashTable *includes_files_hash; GList *includes_files = NULL; gchar *temp_file = create_temp_file("tmp_XXXXXX.cpp"); gchar *temp_file2 = create_temp_file("tmp_XXXXXX.cpp"); if (NULL == temp_file || NULL == temp_file2 || NULL == (fp = g_fopen(temp_file, "w"))) { g_free(temp_file); g_free(temp_file2); 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; if (includes[0][0] == '"') /* leading \" char for glob matching */ for(idx_inc = 0; idx_inc < includes_count; idx_inc++) { size_t dirty_len = strlen(includes[idx_inc]); char *clean_path = g_malloc(dirty_len - 1); strncpy(clean_path, includes[idx_inc] + 1, dirty_len - 1); clean_path[dirty_len - 2] = 0; #ifdef TM_DEBUG g_message ("[o][%s]\n", clean_path); #endif glob(clean_path, 0, NULL, &globbuf); #ifdef TM_DEBUG g_message ("matches: %d\n", globbuf.gl_pathc); #endif for(idx_glob = 0; idx_glob < globbuf.gl_pathc; 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); g_free(clean_path); } 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, includes[idx_inc])) { char* file_name_copy = strdup(includes[idx_inc]); g_hash_table_insert(includes_files_hash, file_name_copy, file_name_copy); } } /* Checks for duplicate file entries which would case trouble */ g_hash_table_foreach(includes_files_hash, tm_move_entries_to_g_list, &includes_files); includes_files = g_list_reverse (includes_files); #ifdef TM_DEBUG g_message ("writing out files to %s\n", temp_file); #endif if (pre_process != NULL) write_includes_file(fp, includes_files); else append_to_temp_file(fp, includes_files); g_list_free (includes_files); g_hash_table_destroy(includes_files_hash); includes_files_hash = NULL; includes_files = NULL; fclose(fp); if (pre_process != NULL) { gint ret; gchar *tmp_errfile = create_temp_file("tmp_XXXXXX"); gchar *errors = NULL; command = g_strdup_printf("%s %s >%s 2>%s", pre_process, temp_file, temp_file2, tmp_errfile); #ifdef TM_DEBUG g_message("Executing: %s", command); #endif ret = system(command); g_free(command); g_unlink(temp_file); g_free(temp_file); g_file_get_contents(tmp_errfile, &errors, NULL, NULL); if (errors && *errors) g_printerr("%s", errors); g_free(errors); g_unlink(tmp_errfile); g_free(tmp_errfile); if (ret == -1) { g_unlink(temp_file2); return FALSE; } } else { /* no pre-processing needed, so temp_file2 = temp_file */ g_unlink(temp_file2); g_free(temp_file2); temp_file2 = temp_file; temp_file = NULL; } source_file = tm_source_file_new(temp_file2, tm_source_file_get_lang_name(lang)); update_source_file(source_file, NULL, 0, FALSE, FALSE); if (NULL == source_file) { g_unlink(temp_file2); return FALSE; } g_unlink(temp_file2); g_free(temp_file2); if (0 == source_file->tags_array->len) { tm_source_file_free(source_file); return FALSE; } tags_array = tm_tags_extract(source_file->tags_array, tm_tag_max_t); if ((NULL == tags_array) || (0 == tags_array->len)) { if (tags_array) g_ptr_array_free(tags_array, TRUE); tm_source_file_free(source_file); return FALSE; } if (FALSE == tm_tags_sort(tags_array, global_tags_sort_attrs, TRUE, FALSE)) { 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); tm_source_file_free(source_file); g_ptr_array_free(tags_array, TRUE); return TRUE; }
gboolean tm_workspace_create_global_tags(const char *pre_process, const char **includes, int includes_count, const char *tags_file, int lang) { #ifdef HAVE_GLOB_H glob_t globbuf; size_t idx_glob; #endif int idx_inc; char *command; guint i; FILE *fp; TMWorkObject *source_file; GPtrArray *tags_array; GHashTable *includes_files_hash; GList *includes_files = NULL; gchar *temp_file = create_temp_file("tmp_XXXXXX.cpp"); gchar *temp_file2 = create_temp_file("tmp_XXXXXX.cpp"); if (NULL == temp_file || NULL == temp_file2 || NULL == theWorkspace || NULL == (fp = g_fopen(temp_file, "w"))) { g_free(temp_file); g_free(temp_file2); 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; if (includes[0][0] == '"') /* leading \" char for glob matching */ for(idx_inc = 0; idx_inc < includes_count; idx_inc++) { int dirty_len = strlen(includes[idx_inc]); char *clean_path = g_malloc(dirty_len - 1); strncpy(clean_path, includes[idx_inc] + 1, dirty_len - 1); clean_path[dirty_len - 2] = 0; #ifdef TM_DEBUG g_message ("[o][%s]\n", clean_path); #endif glob(clean_path, 0, NULL, &globbuf); #ifdef TM_DEBUG g_message ("matches: %d\n", globbuf.gl_pathc); #endif for(idx_glob = 0; idx_glob < globbuf.gl_pathc; 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); g_free(clean_path); } 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, includes[idx_inc])) { char* file_name_copy = strdup(includes[idx_inc]); g_hash_table_insert(includes_files_hash, file_name_copy, file_name_copy); } } /* Checks for duplicate file entries which would case trouble */ g_hash_table_foreach(includes_files_hash, tm_move_entries_to_g_list, &includes_files); includes_files = g_list_reverse (includes_files); #ifdef TM_DEBUG g_message ("writing out files to %s\n", temp_file); #endif if (pre_process != NULL) write_includes_file(fp, includes_files); else append_to_temp_file(fp, includes_files); g_list_free (includes_files); g_hash_table_destroy(includes_files_hash); includes_files_hash = NULL; includes_files = NULL; fclose(fp); /* FIXME: The following grep command removes 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. */ 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); #endif system(command); g_free(command); g_unlink(temp_file); g_free(temp_file); } else { /* no pre-processing needed, so temp_file2 = temp_file */ g_unlink(temp_file2); 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) { g_unlink(temp_file2); return FALSE; } g_unlink(temp_file2); g_free(temp_file2); if ((NULL == source_file->tags_array) || (0 == source_file->tags_array->len)) { tm_source_file_free(source_file); return FALSE; } tags_array = tm_tags_extract(source_file->tags_array, tm_tag_max_t); if ((NULL == tags_array) || (0 == tags_array->len)) { if (tags_array) g_ptr_array_free(tags_array, TRUE); tm_source_file_free(source_file); return FALSE; } if (FALSE == tm_tags_sort(tags_array, global_tags_sort_attrs, TRUE)) { 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); tm_source_file_free(source_file); g_ptr_array_free(tags_array, TRUE); return TRUE; }