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"
14 #include "tm_workspace.h"
16 static GMemChunk
*sym_mem_chunk
= NULL
;
20 sym_mem_chunk = g_mem_chunk_new("TMSymbol MemChunk", sizeof(TMSymbol), 1024 \
21 , G_ALLOC_AND_FREE); \
22 (T) = g_chunk_new0(TMSymbol, sym_mem_chunk);}
24 #define SYM_FREE(T) g_mem_chunk_free(sym_mem_chunk, (T))
26 void tm_symbol_print(TMSymbol
*sym
, guint level
)
30 g_return_if_fail (sym
!= NULL
);
31 for (i
=0; i
< level
; ++i
)
33 fprintf(stderr
, "%s\n", (sym
->tag
)?sym
->tag
->name
:"Root");
34 if (sym
->info
.children
)
38 if (tm_tag_function_t
== sym
->tag
->type
||
39 tm_tag_prototype_t
== sym
->tag
->type
)
41 tm_tag_print(sym
->info
.equiv
, stderr
);
46 for (i
=0; i
< sym
->info
.children
->len
; ++i
)
47 tm_symbol_print(TM_SYMBOL(sym
->info
.children
->pdata
[i
])
53 #define SYM_ORDER(T) (((tm_tag_class_t == (T)->type) || (tm_tag_struct_t ==\
54 (T)->type))?1:(((tm_tag_enum_t == (T)->type) || (tm_tag_interface_t ==\
57 /* Comparison function for sorting symbols alphabetically */
58 int tm_symbol_compare(const void *p1
, const void *p2
)
68 s1
= *(TMSymbol
**) p1
;
69 s2
= *(TMSymbol
**) p2
;
76 if (!s1
->tag
&& !s2
->tag
)
82 return strcmp(s1
->tag
->name
, s2
->tag
->name
);
86 * Compares function argument lists.
87 * FIXME: Compare based on types, not an exact string match.
89 int tm_arglist_compare(const TMTag
* t1
, const TMTag
* t2
)
91 return strcmp(NVL(t1
->atts
.entry
.arglist
, "()"),
92 NVL(t2
->atts
.entry
.arglist
, "()"));
95 /* Need this custom compare function to generate a symbol tree
96 in a simgle pass from tag list */
97 int tm_symbol_tag_compare(const TMTag
**t1
, const TMTag
**t2
)
101 if ((!t1
&& !t2
) || (!*t1
&& !*t2
))
103 else if (!t1
|| !*t1
)
105 else if (!t2
|| !*t2
)
107 if ((tm_tag_file_t
== (*t1
)->type
) && (tm_tag_file_t
== (*t2
)->type
))
109 else if (tm_tag_file_t
== (*t1
)->type
)
111 else if (tm_tag_file_t
== (*t2
)->type
)
114 /* Compare on depth of scope - less depth gets higher priortity */
115 s1
= tm_tag_scope_depth(*t1
);
116 s2
= tm_tag_scope_depth(*t2
);
120 /* Compare of tag type using a symbol ordering routine */
126 /* Compare names alphabetically */
127 s1
= strcmp((*t1
)->name
, (*t2
)->name
);
131 /* Compare scope alphabetically */
132 s1
= strcmp(NVL((*t1
)->atts
.entry
.scope
, ""),
133 NVL((*t2
)->atts
.entry
.scope
, ""));
137 /* If none of them are function/prototype, they are effectively equal */
138 if ((tm_tag_function_t
!= (*t1
)->type
) &&
139 (tm_tag_prototype_t
!= (*t1
)->type
)&&
140 (tm_tag_function_t
!= (*t2
)->type
) &&
141 (tm_tag_prototype_t
!= (*t2
)->type
))
144 /* Whichever is not a function/prototype goes first */
145 if ((tm_tag_function_t
!= (*t1
)->type
) &&
146 (tm_tag_prototype_t
!= (*t1
)->type
))
148 if ((tm_tag_function_t
!= (*t2
)->type
) &&
149 (tm_tag_prototype_t
!= (*t2
)->type
))
152 /* Compare the argument list */
153 s1
= tm_arglist_compare(*t1
, *t2
);
157 /* Functions go before prototypes */
158 if ((tm_tag_function_t
== (*t1
)->type
) &&
159 (tm_tag_function_t
!= (*t2
)->type
))
161 if ((tm_tag_function_t
!= (*t1
)->type
) &&
162 (tm_tag_function_t
== (*t2
)->type
))
170 check_children_symbols(TMSymbol
*sym
, const char *name
, gint level
)
173 g_warning ("Infinite recursion detected (symbol name = %s) !!", name
);
178 GPtrArray
*scope_tags
;
180 TMSymbol
*sym1
= sym
->parent
;
182 while(sym1
&& (tag
= sym1
->tag
) && tag
->name
)
184 if(0 == strcmp(tag
->name
, name
))
191 scope_tags
= tm_tags_extract (tm_workspace_find_scope_members (NULL
, name
, FALSE
, FALSE
), tm_tag_max_t
);
192 if(scope_tags
&& scope_tags
->len
> 0)
197 tm_tags_custom_sort (scope_tags
,
198 (TMTagCompareFunc
) tm_symbol_tag_compare
,
200 sym
->info
.children
= g_ptr_array_sized_new(scope_tags
->len
);
201 for (j
=0; j
< scope_tags
->len
; ++j
)
203 tag
= TM_TAG(scope_tags
->pdata
[j
]);
204 if (tm_tag_prototype_t
== tag
->type
)
206 /* Since the tags are sorted, we can now expect to find
207 * identical definitions/declarations in the previous element.
208 * Functions will come before their prototypes.
210 if (sym1
&& (tm_tag_function_t
== sym1
->tag
->type
) &&
211 (!sym1
->info
.equiv
) &&
212 (0 == strcmp(NVL(tag
->atts
.entry
.scope
, ""),
213 NVL(sym1
->tag
->atts
.entry
.scope
, ""))) &&
214 (0 == strcmp(tag
->name
, sym1
->tag
->name
)) &&
215 (0 == tm_arglist_compare(tag
, sym1
->tag
)))
217 sym1
->info
.equiv
= tag
;
221 if (strcmp(tag
->name
, sym
->tag
->name
) == 0)
223 continue; /* Avoid recursive definition */
228 g_ptr_array_add(sym
->info
.children
, sym1
);
231 for (j
=0; j
< sym
->info
.children
->len
; ++j
)
233 sym1
= TM_SYMBOL(sym
->info
.children
->pdata
[j
]);
234 if ((tm_tag_member_t
& sym1
->tag
->type
) == tm_tag_member_t
&&
235 sym1
->tag
->atts
.entry
.pointerOrder
== 0)
236 check_children_symbols(sym1
, sym1
->tag
->atts
.entry
.type_ref
[1],
241 g_ptr_array_free (scope_tags
, TRUE
);
247 tm_symbol_get_root_index (TMSymbol
* sym
)
252 access
= sym
->tag
->atts
.entry
.access
;
253 switch (sym
->tag
->type
)
258 case tm_tag_struct_t
:
264 case tm_tag_function_t
:
267 case TAG_ACCESS_PRIVATE
:
268 case TAG_ACCESS_PROTECTED
:
269 case TAG_ACCESS_PUBLIC
:
277 case tm_tag_prototype_t
:
278 if ((sym
->info
.equiv
) && (TAG_ACCESS_UNKNOWN
== access
))
279 access
= sym
->info
.equiv
->atts
.entry
.access
;
282 case TAG_ACCESS_PRIVATE
:
283 case TAG_ACCESS_PROTECTED
:
284 case TAG_ACCESS_PUBLIC
:
292 case tm_tag_member_t
:
295 case TAG_ACCESS_PRIVATE
:
296 case TAG_ACCESS_PROTECTED
:
297 case TAG_ACCESS_PUBLIC
:
305 case tm_tag_variable_t
:
306 case tm_tag_externvar_t
:
310 case tm_tag_macro_with_arg_t
:
313 case tm_tag_typedef_t
:
316 case tm_tag_enumerator_t
:
326 TMSymbol
*tm_symbol_tree_new(GPtrArray
*tags_array
)
329 TMSymbol
*grand_root
= NULL
;
330 static int subroot_types
[] = {
331 tm_tag_class_t
, tm_tag_struct_t
, tm_tag_union_t
,
332 tm_tag_prototype_t
, tm_tag_variable_t
, tm_tag_macro_t
,
333 tm_tag_typedef_t
, tm_tag_enumerator_t
, tm_tag_other_t
,
336 static TMTag subroot_tags
[sizeof(subroot_types
)] = {
337 {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}
339 static char* subroot_labels
[sizeof(subroot_types
)] = {
340 "Classes", "Structs", "Unions", "Functions", "Variables",
341 "Macros", "Typedefs", "Enumerators", "Others", NULL
343 TMSymbol
*subroot
[sizeof(subroot_types
)] = {NULL
, NULL
, NULL
,
344 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
347 g_message("Building symbol tree..");
350 if ((!tags_array
) || (tags_array
->len
<= 0))
354 fprintf(stderr
, "Dumping all tags..\n");
355 tm_tags_array_print(tags_array
, stderr
);
358 tags
= tm_tags_extract(tags_array
, tm_tag_max_t
);
360 fprintf(stderr
, "Dumping unordered tags..\n");
361 tm_tags_array_print(tags
, stderr
);
364 if (tags
&& (tags
->len
> 0))
369 TMSymbol
*sym
= NULL
;
371 /* Creating top-level symbols */
373 if (!grand_root
->info
.children
)
374 grand_root
->info
.children
= g_ptr_array_new();
376 for (i
= 0; subroot_types
[i
] != tm_tag_undef_t
; i
++)
379 subroot_tags
[i
].name
= subroot_labels
[i
];
380 subroot_tags
[i
].type
= subroot_types
[i
];
381 sym
->tag
= &subroot_tags
[i
];
382 sym
->parent
= grand_root
;
383 g_ptr_array_add(grand_root
->info
.children
, sym
);
387 tm_tags_custom_sort(tags
, (TMTagCompareFunc
) tm_symbol_tag_compare
391 fprintf(stderr
, "Dumping ordered tags..");
392 tm_tags_array_print(tags
, stderr
);
393 fprintf(stderr
, "Rebuilding symbol table..\n");
396 for (i
=0; i
< tags
->len
; ++i
)
398 tag
= TM_TAG(tags
->pdata
[i
]);
400 if (tm_tag_prototype_t
== tag
->type
)
402 /* Since the tags are sorted, we can now expect to find
403 * identical definitions/declarations in the previous element.
404 * Functions will come before their prototypes.
406 if (sym
&& (tm_tag_function_t
== sym
->tag
->type
) &&
407 (!sym
->info
.equiv
) &&
408 (0 == strcmp(NVL(tag
->atts
.entry
.scope
, ""),
409 NVL(sym
->tag
->atts
.entry
.scope
, ""))) &&
410 (0 == strcmp(tag
->name
, sym
->tag
->name
)) &&
411 (0 == tm_arglist_compare(tag
, sym
->tag
)))
413 sym
->info
.equiv
= tag
;
418 if(tag
->atts
.entry
.scope
)
420 if ((tm_tag_class_t
| tm_tag_enum_t
|
421 tm_tag_struct_t
| tm_tag_union_t
) & tag
->type
)
423 /* this is Hack an shold be fixed by adding this info in tag struct */
424 if(NULL
!= strstr(tag
->name
, "_fake_"))
436 if(!(tag
->type
& tm_tag_enum_t
)
437 && NULL
!= strstr(tag
->name
, "_fake_"))
439 /* This is Hack an should be fixed by adding this info in tag struct */
445 sym
->parent
= subroot
[tm_symbol_get_root_index (sym
)];
446 if (!sym
->parent
->info
.children
)
447 sym
->parent
->info
.children
= g_ptr_array_new();
448 g_ptr_array_add(sym
->parent
->info
.children
, sym
);
450 if ((tm_tag_undef_t
| tm_tag_function_t
| tm_tag_prototype_t
|
451 tm_tag_macro_t
| tm_tag_macro_with_arg_t
| tm_tag_file_t
)
455 check_children_symbols(sym
, tag
->name
, 0);
458 fprintf(stderr
, "Done.Dumping symbol tree..");
459 tm_symbol_print(grand_root
, 0);
463 g_ptr_array_free(tags
, TRUE
);
468 static void tm_symbol_free(TMSymbol
*sym
)
472 if (sym
->info
.children
)
475 for (i
=0; i
< sym
->info
.children
->len
; ++i
)
476 tm_symbol_free(TM_SYMBOL(sym
->info
.children
->pdata
[i
]));
477 g_ptr_array_free(sym
->info
.children
, TRUE
);
478 sym
->info
.children
= NULL
;
483 void tm_symbol_tree_free(gpointer root
)
486 tm_symbol_free(TM_SYMBOL(root
));
489 TMSymbol
*tm_symbol_tree_update(TMSymbol
*root
, GPtrArray
*tags
)
492 tm_symbol_free(root
);
493 if ((tags
) && (tags
->len
> 0))
494 return tm_symbol_tree_new(tags
);