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; }
static void merge_extracted_tags(GPtrArray **dest, GPtrArray *src, TMTagType tag_types) { GPtrArray *arr; arr = tm_tags_extract(src, tag_types); tm_workspace_merge_tags(dest, arr); g_ptr_array_free(arr, TRUE); }
/* Loads the global tag list from the specified file. The global tag list should have been first created using tm_workspace_create_global_tags(). @param tags_file The file containing global tags. @return TRUE on success, FALSE on failure. @see tm_workspace_create_global_tags() */ gboolean tm_workspace_load_global_tags(const char *tags_file, TMParserType mode) { GPtrArray *file_tags, *new_tags; file_tags = tm_source_file_read_tags_file(tags_file, mode); if (!file_tags) return FALSE; tm_tags_sort(file_tags, global_tags_sort_attrs, TRUE, TRUE); /* reorder the whole array, because tm_tags_find expects a sorted array */ new_tags = tm_tags_merge(theWorkspace->global_tags, file_tags, global_tags_sort_attrs, TRUE); g_ptr_array_free(theWorkspace->global_tags, TRUE); g_ptr_array_free(file_tags, TRUE); theWorkspace->global_tags = new_tags; g_ptr_array_free(theWorkspace->global_typename_array, TRUE); theWorkspace->global_typename_array = tm_tags_extract(new_tags, TM_GLOBAL_TYPE_MASK); return TRUE; }
/* Recreates workspace tag array from all member TMSourceFile objects. Use if you want to globally refresh the workspace. This function does not call tm_source_file_update() which should be called before this function on source files which need to be reparsed. */ static void tm_workspace_update(void) { guint i, j; TMSourceFile *source_file; #ifdef TM_DEBUG g_message("Recreating workspace tags array"); #endif g_ptr_array_set_size(theWorkspace->tags_array, 0); #ifdef TM_DEBUG g_message("Total %d objects", theWorkspace->source_files->len); #endif for (i=0; i < theWorkspace->source_files->len; ++i) { source_file = theWorkspace->source_files->pdata[i]; #ifdef TM_DEBUG g_message("Adding tags of %s", source_file->file_name); #endif if (source_file->tags_array->len > 0) { for (j = 0; j < source_file->tags_array->len; ++j) { g_ptr_array_add(theWorkspace->tags_array, source_file->tags_array->pdata[j]); } } } #ifdef TM_DEBUG g_message("Total: %d tags", theWorkspace->tags_array->len); #endif tm_tags_sort(theWorkspace->tags_array, workspace_tags_sort_attrs, TRUE, FALSE); g_ptr_array_free(theWorkspace->typename_array, TRUE); theWorkspace->typename_array = tm_tags_extract(theWorkspace->tags_array, TM_GLOBAL_TYPE_MASK); }
static void update_source_file(TMSourceFile *source_file, guchar* text_buf, gsize buf_size, gboolean use_buffer, gboolean update_workspace) { #ifdef TM_DEBUG g_message("Source file updating based on source file %s", source_file->file_name); #endif if (update_workspace) { /* tm_source_file_parse() deletes the tag objects - remove the tags from * workspace while they exist and can be scanned */ tm_tags_remove_file_tags(source_file, theWorkspace->tags_array); tm_tags_remove_file_tags(source_file, theWorkspace->typename_array); } tm_source_file_parse(source_file, text_buf, buf_size, use_buffer); tm_tags_sort(source_file->tags_array, file_tags_sort_attrs, FALSE, TRUE); if (update_workspace) { GPtrArray *sf_typedefs; #ifdef TM_DEBUG g_message("Updating workspace from source file"); #endif tm_workspace_merge_tags(&theWorkspace->tags_array, source_file->tags_array); sf_typedefs = tm_tags_extract(source_file->tags_array, TM_GLOBAL_TYPE_MASK); tm_workspace_merge_tags(&theWorkspace->typename_array, sf_typedefs); g_ptr_array_free(sf_typedefs, TRUE); } #ifdef TM_DEBUG else g_message("Skipping workspace update because update_workspace is %s", update_workspace?"TRUE":"FALSE"); #endif }
/* 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; }
/* Loads the global tag list from the specified file. The global tag list should have been first created using tm_workspace_create_global_tags(). @param tags_file The file containing global tags. @return TRUE on success, FALSE on failure. @see tm_workspace_create_global_tags() */ gboolean tm_workspace_load_global_tags(const char *tags_file, TMParserType mode) { guchar buf[BUFSIZ]; FILE *fp; GPtrArray *file_tags, *new_tags; TMTag *tag; TMFileFormat format = TM_FILE_FORMAT_TAGMANAGER; if (NULL == (fp = g_fopen(tags_file, "r"))) return FALSE; if ((NULL == fgets((gchar*) buf, BUFSIZ, fp)) || ('\0' == *buf)) { fclose(fp); return FALSE; /* early out on error */ } else { /* We read the first line for the format specification. */ if (buf[0] == '#' && strstr((gchar*) buf, "format=pipe") != NULL) format = TM_FILE_FORMAT_PIPE; else if (buf[0] == '#' && strstr((gchar*) buf, "format=tagmanager") != NULL) format = TM_FILE_FORMAT_TAGMANAGER; else if (buf[0] == '#' && strstr((gchar*) buf, "format=ctags") != NULL) format = TM_FILE_FORMAT_CTAGS; else if (strncmp((gchar*) buf, "!_TAG_", 6) == 0) format = TM_FILE_FORMAT_CTAGS; else { /* We didn't find a valid format specification, so we try to auto-detect the format * by counting the pipe characters on the first line and asumme pipe format when * we find more than one pipe on the line. */ guint i, pipe_cnt = 0, tab_cnt = 0; for (i = 0; i < BUFSIZ && buf[i] != '\0' && pipe_cnt < 2; i++) { if (buf[i] == '|') pipe_cnt++; else if (buf[i] == '\t') tab_cnt++; } if (pipe_cnt > 1) format = TM_FILE_FORMAT_PIPE; else if (tab_cnt > 1) format = TM_FILE_FORMAT_CTAGS; } rewind(fp); /* reset the file pointer, to start reading again from the beginning */ } file_tags = g_ptr_array_new(); while (NULL != (tag = tm_tag_new_from_file(NULL, fp, mode, format))) g_ptr_array_add(file_tags, tag); fclose(fp); tm_tags_sort(file_tags, global_tags_sort_attrs, TRUE, TRUE); /* reorder the whole array, because tm_tags_find expects a sorted array */ new_tags = tm_tags_merge(theWorkspace->global_tags, file_tags, global_tags_sort_attrs, TRUE); g_ptr_array_free(theWorkspace->global_tags, TRUE); g_ptr_array_free(file_tags, TRUE); theWorkspace->global_tags = new_tags; g_ptr_array_free(theWorkspace->global_typename_array, TRUE); theWorkspace->global_typename_array = tm_tags_extract(new_tags, TM_GLOBAL_TYPE_MASK); 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; }
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; }