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) { #ifdef TM_DEBUG g_message("Updating workspace from source file"); #endif tm_workspace_merge_tags(&theWorkspace->tags_array, source_file->tags_array); merge_extracted_tags(&(theWorkspace->typename_array), source_file->tags_array, TM_GLOBAL_TYPE_MASK); } #ifdef TM_DEBUG else g_message("Skipping workspace update because update_workspace is %s", update_workspace?"TRUE":"FALSE"); #endif }
/* adapted from tm_workspace_find, Anjuta 2.02 */ const GPtrArray * tm_workspace_find_scoped (const char *name, const char *scope, gint type, TMTagAttrType *attrs, gboolean partial, langType lang, gboolean global_search) { static GPtrArray *tags = NULL; if ((!theWorkspace)) return NULL; if (tags) g_ptr_array_set_size (tags, 0); else tags = g_ptr_array_new (); fill_find_tags_array (tags, theWorkspace->work_object.tags_array, name, scope, type, partial, lang, FALSE); if (global_search) { /* for a scoped tag, I think we always want the same language */ fill_find_tags_array (tags, theWorkspace->global_tags, name, scope, type, partial, lang, FALSE); } if (attrs) tm_tags_sort (tags, attrs, TRUE); return tags; }
gboolean tm_source_file_buffer_update(TMWorkObject *source_file, guchar* text_buf, gint buf_size, gboolean update_parent) { #ifdef TM_DEBUG g_message("Buffer updating based on source file %s", source_file->file_name); #endif tm_source_file_buffer_parse (TM_SOURCE_FILE(source_file), text_buf, buf_size); tm_tags_sort(source_file->tags_array, NULL, FALSE); /* source_file->analyze_time = time(NULL); */ if ((source_file->parent) && update_parent) { #ifdef TM_DEBUG g_message("Updating parent [project] from buffer.."); #endif tm_work_object_update(source_file->parent, TRUE, FALSE, TRUE); } #ifdef TM_DEBUG else g_message("Skipping parent update because parent is %s and update_parent is %s" , source_file->parent?"NOT NULL":"NULL", update_parent?"TRUE":"FALSE"); #endif 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) { 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; }
/* Returns all matching tags found in the workspace. @param name The name of the tag to find. @param scope The scope name of the tag to find, or NULL. @param type The tag types to return (TMTagType). Can be a bitmask. @param attrs The attributes to sort and dedup on (0 terminated integer array). @param lang Specifies the language(see the table in parsers.h) of the tags to be found, -1 for all @return Array of matching tags. */ GPtrArray *tm_workspace_find(const char *name, const char *scope, TMTagType type, TMTagAttrType *attrs, TMParserType lang) { GPtrArray *tags = g_ptr_array_new(); fill_find_tags_array(tags, theWorkspace->tags_array, name, scope, type, lang); fill_find_tags_array(tags, theWorkspace->global_tags, name, scope, type, lang); if (attrs) tm_tags_sort(tags, attrs, TRUE, FALSE); return tags; }
/* Returns tags with the specified prefix sorted by name. If there are several tags with the same name, only one of them appears in the resulting array. @param prefix The prefix of the tag to find. @param lang Specifies the language(see the table in parsers.h) of the tags to be found, -1 for all. @param max_num The maximum number of tags to return. @return Array of matching tags sorted by their name. */ GPtrArray *tm_workspace_find_prefix(const char *prefix, TMParserType lang, guint max_num) { TMTagAttrType attrs[] = { tm_tag_attr_name_t, 0 }; GPtrArray *tags = g_ptr_array_new(); fill_find_tags_array_prefix(tags, theWorkspace->tags_array, prefix, lang, max_num); fill_find_tags_array_prefix(tags, theWorkspace->global_tags, prefix, lang, max_num); tm_tags_sort(tags, attrs, TRUE, FALSE); if (tags->len > max_num) tags->len = max_num; return tags; }
gboolean tm_workspace_load_global_tags(const char *tags_file, gint mode) { guchar buf[BUFSIZ]; FILE *fp; TMTag *tag; gboolean format_pipe = FALSE; if (NULL == theWorkspace) return FALSE; if (NULL == (fp = g_fopen(tags_file, "r"))) return FALSE; if (NULL == theWorkspace->global_tags) theWorkspace->global_tags = g_ptr_array_new(); 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_pipe = TRUE; else if (buf[0] == '#' && strstr((gchar*) buf, "format=tagmanager") != NULL) format_pipe = FALSE; 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; for (i = 0; i < BUFSIZ && buf[i] != '\0' && pipe_cnt < 2; i++) { if (buf[i] == '|') pipe_cnt++; } format_pipe = (pipe_cnt > 1); } rewind(fp); /* reset the file pointer, to start reading again from the beginning */ } while (NULL != (tag = tm_tag_new_from_file(NULL, fp, mode, format_pipe))) g_ptr_array_add(theWorkspace->global_tags, tag); fclose(fp); /* resort the whole array, because tm_tags_find expects a sorted array and it is not sorted * when c99.tags, php.tags and latex.tags are loaded at the same time */ tm_tags_sort(theWorkspace->global_tags, global_tags_sort_attrs, TRUE); return TRUE; }
void tm_workspace_recreate_tags_array(void) { guint i, j; TMWorkObject *w; TMTagAttrType sort_attrs[] = { tm_tag_attr_name_t, tm_tag_attr_file_t , tm_tag_attr_scope_t, tm_tag_attr_type_t, tm_tag_attr_arglist_t, 0}; #ifdef TM_DEBUG g_message("Recreating workspace tags array"); #endif if ((NULL == theWorkspace) || (NULL == theWorkspace->work_objects)) return; if (NULL != theWorkspace->work_object.tags_array) g_ptr_array_set_size(theWorkspace->work_object.tags_array, 0); else theWorkspace->work_object.tags_array = g_ptr_array_new(); #ifdef TM_DEBUG g_message("Total %d objects", theWorkspace->work_objects->len); #endif for (i=0; i < theWorkspace->work_objects->len; ++i) { w = TM_WORK_OBJECT(theWorkspace->work_objects->pdata[i]); #ifdef TM_DEBUG g_message("Adding tags of %s", w->file_name); #endif if ((NULL != w) && (NULL != w->tags_array) && (w->tags_array->len > 0)) { for (j = 0; j < w->tags_array->len; ++j) { g_ptr_array_add(theWorkspace->work_object.tags_array, w->tags_array->pdata[j]); } } } #ifdef TM_DEBUG g_message("Total: %d tags", theWorkspace->work_object.tags_array->len); #endif tm_tags_sort(theWorkspace->work_object.tags_array, sort_attrs, TRUE); }
gboolean tm_source_file_update(TMWorkObject *source_file, gboolean force , gboolean UNUSED recurse, gboolean update_parent) { if (force) { tm_source_file_parse(TM_SOURCE_FILE(source_file)); tm_tags_sort(source_file->tags_array, NULL, FALSE); /* source_file->analyze_time = tm_get_file_timestamp(source_file->file_name); */ if ((source_file->parent) && update_parent) { tm_work_object_update(source_file->parent, TRUE, FALSE, TRUE); } return TRUE; } else { #ifdef TM_DEBUG g_message ("no parsing of %s has been done", source_file->file_name); #endif return FALSE; } }
/* 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); }
/* 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(const char *name, int type, TMTagAttrType *attrs , gboolean partial, langType lang) { static GPtrArray *tags = NULL; TMTag **matches[2]; int len, tagCount[2]={0,0}, tagIter; gint tags_lang; if ((!theWorkspace) || (!name)) return NULL; len = strlen(name); if (!len) return NULL; if (tags) g_ptr_array_set_size(tags, 0); else tags = g_ptr_array_new(); matches[0] = tm_tags_find(theWorkspace->work_object.tags_array, name, partial, &tagCount[0]); matches[1] = tm_tags_find(theWorkspace->global_tags, name, partial, &tagCount[1]); /* file tags */ if (matches[0] && *matches[0]) { /* tag->atts.file.lang contains the line of the tag and * tags->atts.entry.file->lang contains the language */ tags_lang = (*matches[0])->atts.entry.file->lang; for (tagIter=0;tagIter<tagCount[0];++tagIter) { if ((type & (*matches[0])->type) && (lang == -1 || tags_lang == lang)) g_ptr_array_add(tags, *matches[0]); if (partial) { if (0 != strncmp((*matches[0])->name, name, len)) break; } else { if (0 != strcmp((*matches[0])->name, name)) break; } ++ matches[0]; } } /* global tags */ if (matches[1] && *matches[1]) { int tags_lang_alt = 0; /* tag->atts.file.lang contains the language and * tags->atts.entry.file is NULL */ tags_lang = (*matches[1])->atts.file.lang; /* tags_lang_alt is used to load C global tags only once for C and C++ * lang = 1 is C++, lang = 0 is C * if we have lang 0, than accept also lang 1 for C++ */ if (tags_lang == 0) /* C or C++ */ tags_lang_alt = 1; else tags_lang_alt = tags_lang; /* otherwise just ignore it */ for (tagIter=0;tagIter<tagCount[1];++tagIter) { if ((type & (*matches[1])->type) && (lang == -1 || tags_lang == lang || tags_lang_alt == lang)) g_ptr_array_add(tags, *matches[1]); if (partial) { if (0 != strncmp((*matches[1])->name, name, len)) break; } else { if (0 != strcmp((*matches[1])->name, name)) break; } ++ matches[1]; } } if (attrs) tm_tags_sort(tags, attrs, TRUE); 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; }