3
* Copyright (c) 2001-2002, Biswapesh Chattopadhyay
5
* This source code is released for free distribution under the terms of the
6
* GNU General Public License.
13
#include "tm_symbol.h"
16
#define SYM_NEW(T) ((T) = g_slice_new0(TMSymbol))
17
#define SYM_FREE(T) g_slice_free(TMSymbol, (T))
20
void tm_symbol_print(TMSymbol *sym, guint level)
24
g_return_if_fail (sym != NULL);
25
for (i=0; i < level; ++i)
27
fprintf(stderr, "%s\n", (sym->tag)?sym->tag->name:"Root");
28
if (sym->info.children)
30
if (sym->tag && tm_tag_function_t == sym->tag->type)
31
tm_tag_print(sym->info.equiv, stderr);
34
for (i=0; i < sym->info.children->len; ++i)
35
tm_symbol_print(TM_SYMBOL(sym->info.children->pdata[i])
41
#define SYM_ORDER(T) (((tm_tag_class_t == (T)->type) || (tm_tag_struct_t ==\
42
(T)->type))?1:(((tm_tag_enum_t == (T)->type) || (tm_tag_interface_t ==\
45
/* Comparison function for sorting symbols alphabetically */
46
int tm_symbol_compare(const void *p1, const void *p2)
56
s1 = *(TMSymbol **) p1;
57
s2 = *(TMSymbol **) p2;
64
if (!s1->tag && !s2->tag)
70
return strcmp(s1->tag->name, s2->tag->name);
74
* Compares function argument lists.
75
* FIXME: Compare based on types, not an exact string match.
77
int tm_arglist_compare(const TMTag* t1, const TMTag* t2)
79
return strcmp(NVL(t1->atts.entry.arglist, ""),
80
NVL(t2->atts.entry.arglist, ""));
83
/* Need this custom compare function to generate a symbol tree
84
in a simgle pass from tag list */
85
int tm_symbol_tag_compare(const TMTag **t1, const TMTag **t2)
91
if (t1 && t2 && !*t1 && !*t2)
97
if ((tm_tag_file_t == (*t1)->type) && (tm_tag_file_t == (*t2)->type))
99
else if (tm_tag_file_t == (*t1)->type)
101
else if (tm_tag_file_t == (*t2)->type)
104
/* Compare on depth of scope - less depth gets higher priortity */
105
s1 = tm_tag_scope_depth(*t1);
106
s2 = tm_tag_scope_depth(*t2);
110
/* Compare of tag type using a symbol ordering routine */
116
/* Compare names alphabetically */
117
s1 = strcmp((*t1)->name, (*t2)->name);
121
/* Compare scope alphabetically */
122
s1 = strcmp(NVL((*t1)->atts.entry.scope, ""),
123
NVL((*t2)->atts.entry.scope, ""));
127
/* If none of them are function/prototype, they are effectively equal */
128
if ((tm_tag_function_t != (*t1)->type) &&
129
(tm_tag_prototype_t != (*t1)->type)&&
130
(tm_tag_function_t != (*t2)->type) &&
131
(tm_tag_prototype_t != (*t2)->type))
134
/* Whichever is not a function/prototype goes first */
135
if ((tm_tag_function_t != (*t1)->type) &&
136
(tm_tag_prototype_t != (*t1)->type))
138
if ((tm_tag_function_t != (*t2)->type) &&
139
(tm_tag_prototype_t != (*t2)->type))
142
/* Compare the argument list */
143
s1 = tm_arglist_compare(*t1, *t2);
147
/* Functions go before prototypes */
148
if ((tm_tag_function_t == (*t1)->type) &&
149
(tm_tag_function_t != (*t2)->type))
151
if ((tm_tag_function_t != (*t1)->type) &&
152
(tm_tag_function_t == (*t2)->type))
159
TMSymbol *tm_symbol_tree_new(GPtrArray *tags_array)
161
TMSymbol *root = NULL;
165
g_message("Building symbol tree..");
168
if ((!tags_array) || (tags_array->len <= 0))
172
fprintf(stderr, "Dumping all tags..\n");
173
tm_tags_array_print(tags_array, stderr);
176
tags = tm_tags_extract(tags_array, tm_tag_max_t);
178
fprintf(stderr, "Dumping unordered tags..\n");
179
tm_tags_array_print(tags, stderr);
182
if (tags && (tags->len > 0))
186
int max_parents = -1;
188
TMSymbol *sym = NULL, *sym1;
195
tm_tags_custom_sort(tags, (TMTagCompareFunc) tm_symbol_tag_compare
199
fprintf(stderr, "Dumping ordered tags..");
200
tm_tags_array_print(tags, stderr);
201
fprintf(stderr, "Rebuilding symbol table..\n");
203
for (i=0; i < tags->len; ++i)
205
tag = TM_TAG(tags->pdata[i]);
207
if (tm_tag_prototype_t == tag->type)
209
if (sym && (tm_tag_function_t == sym->tag->type) &&
210
(!sym->info.equiv) &&
211
(0 == strcmp(NVL(tag->atts.entry.scope, "")
212
, NVL(sym->tag->atts.entry.scope, ""))))
214
sym->info.equiv = tag;
220
if (SYM_ORDER(tag) > 2)
224
qsort(root->info.children->pdata, max_parents
225
, sizeof(gpointer), tm_symbol_compare);
230
if ((max_parents <= 0) || (!tag->atts.entry.scope))
233
if (!root->info.children)
234
root->info.children = g_ptr_array_new();
235
g_ptr_array_add(root->info.children, sym);
239
parent_name = tag->atts.entry.scope;
240
scope_end = strstr(tag->atts.entry.scope, "::");
244
if (('\0' != parent_name[0]) &&
245
(0 != strcmp(parent_name, "<anonymous>")))
247
for (j=0; j < max_parents; ++j)
249
sym1 = TM_SYMBOL(root->info.children->pdata[j]);
250
str_match = strcmp(sym1->tag->name, parent_name);
255
if (!sym1->info.children)
256
sym1->info.children = g_ptr_array_new();
257
g_ptr_array_add(sym1->info.children, sym);
260
else if (str_match > 0)
267
if (!root->info.children)
268
root->info.children = g_ptr_array_new();
269
g_ptr_array_add(root->info.children, sym);
276
fprintf(stderr, "Done.Dumping symbol tree..");
277
tm_symbol_print(root, 0);
281
g_ptr_array_free(tags, TRUE);
286
static void tm_symbol_free(TMSymbol *sym)
290
if ((!sym->tag) || ((tm_tag_function_t != sym->tag->type) &&
291
(tm_tag_prototype_t != sym->tag->type)))
293
if (sym->info.children)
296
for (i=0; i < sym->info.children->len; ++i)
297
tm_symbol_free(TM_SYMBOL(sym->info.children->pdata[i]));
298
g_ptr_array_free(sym->info.children, TRUE);
299
sym->info.children = NULL;
305
void tm_symbol_tree_free(gpointer root)
308
tm_symbol_free(TM_SYMBOL(root));
311
TMSymbol *tm_symbol_tree_update(TMSymbol *root, GPtrArray *tags)
314
tm_symbol_free(root);
315
if ((tags) && (tags->len > 0))
316
return tm_symbol_tree_new(tags);