static int find_namespace_members_tags (const GPtrArray * all, GPtrArray * tags, const langType langJava, const char *name, const char *filename) { GPtrArray *local = g_ptr_array_new (); unsigned int i; TMTag *tag; size_t len = strlen (name); g_return_val_if_fail (all != NULL, 0); for (i = 0; (i < all->len); ++i) { tag = TM_TAG (all->pdata[i]); if (filename && tag->atts.entry.file && 0 != strcmp (filename, tag->atts.entry.file->work_object.short_name)) { continue; } if (tag && tag->atts.entry.scope && tag->atts.entry.scope[0] != '\0') { if (0 == strncmp (name, tag->atts.entry.scope, len)) { g_ptr_array_add (local, tag); } } } if (local->len > 0) { char *scope; for (i = 0; (i < local->len); ++i) { tag = TM_TAG (local->pdata[i]); scope = tag->atts.entry.scope; /* if we wanna complete something like * namespace1:: * we'll just return the tags that have "namespace1" * as their scope. So we won't return classes/members/namespaces * under, for example, namespace2, where namespace1::namespace2 */ if (scope && 0 == strcmp (name, scope)) { g_ptr_array_add (tags, tag); } } } g_ptr_array_free (local, TRUE); return (int) tags->len; }
const TMTag * tm_get_current_function (GPtrArray * file_tags, const gulong line) { GPtrArray *const local = tm_tags_extract (file_tags, tm_tag_function_t); if (local && local->len) { guint i; TMTag *tag, *function_tag = NULL; gulong function_line = 0; glong delta; for (i = 0; (i < local->len); ++i) { tag = TM_TAG (local->pdata[i]); delta = line - tag->atts.entry.line; if (delta >= 0 && (gulong)delta < line - function_line) { function_tag = tag; function_line = tag->atts.entry.line; } } g_ptr_array_free (local, TRUE); return function_tag; } return NULL; }
const TMTag * tm_get_current_tag (GPtrArray * file_tags, const gulong line, const guint tag_types) { GPtrArray *const local = tm_tags_extract (file_tags, tag_types); TMTag *matching_tag = NULL; if (local && local->len) { guint i; gulong matching_line = 0; glong delta; for (i = 0; (i < local->len); ++i) { TMTag *tag = TM_TAG (local->pdata[i]); delta = line - tag->atts.entry.line; if (delta >= 0 && (gulong)delta < line - matching_line) { matching_tag = tag; matching_line = tag->atts.entry.line; } } } if (local) g_ptr_array_free (local, TRUE); return matching_tag; }
const GPtrArray *tm_workspace_get_parents(const gchar *name) { static TMTagAttrType type[] = { tm_tag_attr_name_t, tm_tag_attr_none_t }; static GPtrArray *parents = NULL; const GPtrArray *matches; guint i = 0; guint j; gchar **klasses; gchar **klass; TMTag *tag; g_return_val_if_fail(name && isalpha(*name),NULL); if (NULL == parents) parents = g_ptr_array_new(); else g_ptr_array_set_size(parents, 0); matches = tm_workspace_find(name, tm_tag_class_t, type, FALSE, -1); if ((NULL == matches) || (0 == matches->len)) return NULL; g_ptr_array_add(parents, matches->pdata[0]); while (i < parents->len) { tag = TM_TAG(parents->pdata[i]); if ((NULL != tag->atts.entry.inheritance) && (isalpha(tag->atts.entry.inheritance[0]))) { klasses = g_strsplit(tag->atts.entry.inheritance, ",", 10); for (klass = klasses; (NULL != *klass); ++ klass) { for (j=0; j < parents->len; ++j) { if (0 == strcmp(*klass, TM_TAG(parents->pdata[j])->name)) break; } if (parents->len == j) { matches = tm_workspace_find(*klass, tm_tag_class_t, type, FALSE, -1); if ((NULL != matches) && (0 < matches->len)) g_ptr_array_add(parents, matches->pdata[0]); } } g_strfreev(klasses); } ++ i; } return parents; }
/* Prints info about all tags in the array to the given file pointer. */ void tm_tags_array_print(GPtrArray *tags, FILE *fp) { guint i; TMTag *tag; if (!(tags && (tags->len > 0) && fp)) return; for (i = 0; i < tags->len; ++i) { tag = TM_TAG(tags->pdata[i]); tm_tag_print(tag, fp); } }
/* Returns TMTag which "own" given line @param line Current line in edited file. @param file_tags A GPtrArray of edited file TMTag pointers. @param tag_types the tag types to include in the match @return TMTag pointers to owner tag. */ const TMTag * tm_get_current_tag (GPtrArray * file_tags, const gulong line, const TMTagType tag_types) { TMTag *matching_tag = NULL; if (file_tags && file_tags->len) { guint i; gulong matching_line = 0; for (i = 0; (i < file_tags->len); ++i) { TMTag *tag = TM_TAG (file_tags->pdata[i]); if (tag && tag->type & tag_types && tag->line <= line && tag->line > matching_line) { matching_tag = tag; matching_line = tag->line; } } } return matching_tag; }
gboolean tm_source_file_write(TMWorkObject *source_file, FILE *fp, guint attrs) { TMTag *tag; guint i; if (NULL != source_file) { if (NULL != (tag = tm_tag_new(TM_SOURCE_FILE(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; }
/* 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; }
const GPtrArray * tm_workspace_find_namespace_members (const GPtrArray * file_tags, const char *name, gboolean search_global) { static GPtrArray *tags = NULL; GPtrArray *local = NULL; char *new_name = (char *) name; char *filename = NULL; int found = 0, del = 0; static langType langJava = -1; TMTag *tag = NULL; g_return_val_if_fail ((theWorkspace && name && name[0] != '\0'), NULL); if (!tags) tags = g_ptr_array_new (); while (1) { const GPtrArray *tags2; int got = 0, types = (tm_tag_class_t | tm_tag_namespace_t | tm_tag_struct_t | tm_tag_typedef_t | tm_tag_union_t | tm_tag_enum_t); if (file_tags) { g_ptr_array_set_size (tags, 0); got = fill_find_tags_array (tags, file_tags, new_name, NULL, types, FALSE, -1, FALSE); } if (got) { tags2 = tags; } else { TMTagAttrType attrs[] = { tm_tag_attr_name_t, tm_tag_attr_type_t, tm_tag_attr_none_t }; tags2 = tm_workspace_find (new_name, types, attrs, FALSE, -1); } if ((tags2) && (tags2->len == 1) && (tag = TM_TAG (tags2->pdata[0]))) { if (tag->type == tm_tag_typedef_t && tag->atts.entry.var_type && tag->atts.entry.var_type[0] != '\0') { new_name = tag->atts.entry.var_type; continue; } filename = (tag->atts.entry.file ? tag->atts.entry.file->work_object.short_name : NULL); if (tag->atts.entry.scope && tag->atts.entry.scope[0] != '\0') { del = 1; if (tag->atts.entry.file && tag->atts.entry.file->lang == langJava) { new_name = g_strdup_printf ("%s.%s", tag->atts.entry.scope, new_name); } else { new_name = g_strdup_printf ("%s::%s", tag->atts.entry.scope, new_name); } } break; } else { return NULL; } } g_ptr_array_set_size (tags, 0); if (tag && tag->atts.entry.file) { local = tm_tags_extract (tag->atts.entry.file->work_object.tags_array, (tm_tag_function_t | tm_tag_field_t | tm_tag_enumerator_t | tm_tag_namespace_t | tm_tag_class_t )); } else { local = tm_tags_extract (theWorkspace->work_object.tags_array, (tm_tag_function_t | tm_tag_prototype_t | tm_tag_member_t | tm_tag_field_t | tm_tag_enumerator_t | tm_tag_namespace_t | tm_tag_class_t )); } if (local) { found = find_namespace_members_tags (local, tags, langJava, new_name, filename); g_ptr_array_free (local, TRUE); } if (!found && search_global) { GPtrArray *global = tm_tags_extract (theWorkspace->global_tags, (tm_tag_member_t | tm_tag_prototype_t | tm_tag_field_t | tm_tag_method_t | tm_tag_function_t | tm_tag_enumerator_t | tm_tag_namespace_t | tm_tag_class_t )); if (global) { find_namespace_members_tags (global, tags, langJava, new_name, filename); /*/ DEBUG_PRINT ("returning these"); gint i; for (i=0; i < tags->len; i++) { TMTag *cur_tag; cur_tag = (TMTag*)g_ptr_array_index (tags, i); tm_tag_print (cur_tag, stdout ); } /*/ g_ptr_array_free (global, TRUE); } } if (del) { g_free (new_name); } return tags; }
static int find_scope_members_tags (const GPtrArray * all, GPtrArray * tags, const langType langJava, const char *name, const char *filename, gboolean no_definitions) { GPtrArray *local = g_ptr_array_new (); unsigned int i; TMTag *tag; size_t len = strlen (name); for (i = 0; (i < all->len); ++i) { tag = TM_TAG (all->pdata[i]); if (no_definitions && filename && tag->atts.entry.file && 0 != strcmp (filename, tag->atts.entry.file->work_object.short_name)) { continue; } if (tag && tag->atts.entry.scope && tag->atts.entry.scope[0] != '\0') { if (0 == strncmp (name, tag->atts.entry.scope, len)) { g_ptr_array_add (local, tag); } } } if (local->len > 0) { unsigned int j; TMTag *tag2; char backup = 0; char *s_backup = NULL; char *var_type = NULL; char *scope; for (i = 0; (i < local->len); ++i) { tag = TM_TAG (local->pdata[i]); scope = tag->atts.entry.scope; if (scope && 0 == strcmp (name, scope)) { g_ptr_array_add (tags, tag); continue; } s_backup = NULL; j = 0; /* someone could write better code :P */ while (scope) { if (s_backup) { backup = s_backup[0]; s_backup[0] = '\0'; if (0 == strcmp (name, tag->atts.entry.scope)) { j = local->len; s_backup[0] = backup; break; } } if (tag->atts.entry.file && tag->atts.entry.file->lang == langJava) { scope = strrchr (tag->atts.entry.scope, '.'); if (scope) var_type = scope + 1; } else { scope = strrchr (tag->atts.entry.scope, ':'); if (scope) { var_type = scope + 1; scope--; } } if (s_backup) { s_backup[0] = backup; } if (scope) { if (s_backup) { backup = s_backup[0]; s_backup[0] = '\0'; } for (j = 0; (j < local->len); ++j) { if (i == j) continue; tag2 = TM_TAG (local->pdata[j]); if (tag2->atts.entry.var_type && 0 == strcmp (var_type, tag2->atts.entry.var_type)) { break; } } if (s_backup) s_backup[0] = backup; } if (j < local->len) { break; } s_backup = scope; } if (j == local->len) { g_ptr_array_add (tags, tag); } } } g_ptr_array_free (local, TRUE); return (int) tags->len; }
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; }
TMSymbol *tm_symbol_tree_new(GPtrArray *tags_array) { TMSymbol *root = NULL; GPtrArray *tags; #ifdef TM_DEBUG g_message("Building symbol tree.."); #endif if ((!tags_array) || (tags_array->len <= 0)) return NULL; #ifdef TM_DEBUG fprintf(stderr, "Dumping all tags..\n"); tm_tags_array_print(tags_array, stderr); #endif tags = tm_tags_extract(tags_array, tm_tag_max_t); #ifdef TM_DEBUG fprintf(stderr, "Dumping unordered tags..\n"); tm_tags_array_print(tags, stderr); #endif if (tags && (tags->len > 0)) { guint i; int j; int max_parents = -1; TMTag *tag; TMSymbol *sym = NULL, *sym1; char *parent_name; char *scope_end; gboolean matched; int str_match; SYM_NEW(root); tm_tags_custom_sort(tags, (TMTagCompareFunc) tm_symbol_tag_compare , FALSE); #ifdef TM_DEBUG fprintf(stderr, "Dumping ordered tags.."); tm_tags_array_print(tags, stderr); fprintf(stderr, "Rebuilding symbol table..\n"); #endif for (i=0; i < tags->len; ++i) { tag = TM_TAG(tags->pdata[i]); if (tm_tag_prototype_t == tag->type) { if (sym && (tm_tag_function_t == sym->tag->type) && (!sym->info.equiv) && (0 == strcmp(NVL(tag->atts.entry.scope, "") , NVL(sym->tag->atts.entry.scope, "")))) { sym->info.equiv = tag; continue; } } if (max_parents < 0) { if (SYM_ORDER(tag) > 2) { max_parents = i; if (max_parents > 0) qsort(root->info.children->pdata, max_parents , sizeof(gpointer), tm_symbol_compare); } } SYM_NEW(sym); sym->tag = tag; if ((max_parents <= 0) || (!tag->atts.entry.scope)) { sym->parent = root; if (!root->info.children) root->info.children = g_ptr_array_new(); g_ptr_array_add(root->info.children, sym); } else { parent_name = tag->atts.entry.scope; scope_end = strstr(tag->atts.entry.scope, "::"); if (scope_end) *scope_end = '\0'; matched = FALSE; if (('\0' != parent_name[0]) && (0 != strcmp(parent_name, "<anonymous>"))) { for (j=0; j < max_parents; ++j) { sym1 = TM_SYMBOL(root->info.children->pdata[j]); str_match = strcmp(sym1->tag->name, parent_name); if (str_match == 0) { matched = TRUE; sym->parent = sym1; if (!sym1->info.children) sym1->info.children = g_ptr_array_new(); g_ptr_array_add(sym1->info.children, sym); break; } else if (str_match > 0) break; } } if (!matched) { sym->parent = root; if (!root->info.children) root->info.children = g_ptr_array_new(); g_ptr_array_add(root->info.children, sym); } if (scope_end) *scope_end = ':'; } } #ifdef TM_DEBUG fprintf(stderr, "Done.Dumping symbol tree.."); tm_symbol_print(root, 0); #endif } if (tags) g_ptr_array_free(tags, TRUE); return root; }
/* Returns all matching members tags found in given struct/union/class name. @param name Name of the struct/union/class. @param file_tags A GPtrArray of edited file TMTag pointers (for search speedup, can be NULL). @return A GPtrArray of TMTag pointers to struct/union/class members */ const GPtrArray * tm_workspace_find_scope_members (const GPtrArray * file_tags, const char *name, gboolean search_global, gboolean no_definitions) { static GPtrArray *tags = NULL; GPtrArray *local = NULL; char *new_name = (char *) name; char *filename = NULL; int found = 0, del = 0; static langType langJava = -1; TMTag *tag = NULL; /* FIXME */ /* langJava = getNamedLanguage ("Java"); */ g_return_val_if_fail ((theWorkspace && name && name[0] != '\0'), NULL); if (!tags) tags = g_ptr_array_new (); while (1) { const GPtrArray *tags2; guint got = 0; TMTagType types = (tm_tag_class_t | tm_tag_namespace_t | tm_tag_struct_t | tm_tag_typedef_t | tm_tag_union_t | tm_tag_enum_t); if (file_tags) { g_ptr_array_set_size (tags, 0); got = fill_find_tags_array (tags, file_tags, new_name, NULL, types, FALSE, -1, FALSE); } if (got) { tags2 = tags; } else { TMTagAttrType attrs[] = { tm_tag_attr_name_t, tm_tag_attr_type_t, tm_tag_attr_none_t }; tags2 = tm_workspace_find (new_name, types, attrs, FALSE, -1); } if ((tags2) && (tags2->len == 1) && (tag = TM_TAG (tags2->pdata[0]))) { if (tag->type == tm_tag_typedef_t && tag->var_type && tag->var_type[0] != '\0') { char *tmp_name; tmp_name = tag->var_type; if (strcmp(tmp_name, new_name) == 0) { new_name = NULL; } else { new_name = tmp_name; } continue; } filename = (tag->file ? tag->file->short_name : NULL); if (tag->scope && tag->scope[0] != '\0') { del = 1; if (tag->file && tag->file->lang == langJava) { new_name = g_strdup_printf ("%s.%s", tag->scope, new_name); } else { new_name = g_strdup_printf ("%s::%s", tag->scope, new_name); } } break; } else { return NULL; } } g_ptr_array_set_size (tags, 0); if (no_definitions && tag && tag->file) { local = tm_tags_extract (tag->file->tags_array, (tm_tag_function_t | tm_tag_prototype_t | tm_tag_member_t | tm_tag_field_t | tm_tag_method_t | tm_tag_enumerator_t)); } else { local = tm_tags_extract (theWorkspace->tags_array, (tm_tag_function_t | tm_tag_prototype_t | tm_tag_member_t | tm_tag_field_t | tm_tag_method_t | tm_tag_enumerator_t)); } if (local) { found = find_scope_members_tags (local, tags, langJava, new_name, filename, no_definitions); g_ptr_array_free (local, TRUE); } if (!found && search_global) { GPtrArray *global = tm_tags_extract (theWorkspace->global_tags, (tm_tag_member_t | tm_tag_prototype_t | tm_tag_field_t | tm_tag_method_t | tm_tag_function_t | tm_tag_enumerator_t |tm_tag_struct_t | tm_tag_typedef_t | tm_tag_union_t | tm_tag_enum_t)); if (global) { find_scope_members_tags (global, tags, langJava, new_name, filename, no_definitions); g_ptr_array_free (global, TRUE); } } if (del) { g_free (new_name); } return tags; }