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 #if GLIB_CHECK_VERSION (2, 10, 0)
17 /* Use GSlices if present */
19 #define SYM_NEW(T) ((T) = g_slice_new0(TMSymbol))
20 #define SYM_FREE(T) g_slice_free(TMSymbol, (T))
22 #else /* GLib < 2.10 */
24 static GMemChunk
*sym_mem_chunk
= NULL
;
28 sym_mem_chunk = g_mem_chunk_new("TMSymbol MemChunk", sizeof(TMSymbol), 1024 \
29 , G_ALLOC_AND_FREE); \
30 (T) = g_chunk_new0(TMSymbol, sym_mem_chunk);}
32 #define SYM_FREE(T) g_mem_chunk_free(sym_mem_chunk, (T))
34 #endif /* GLib version check */
37 void tm_symbol_print(TMSymbol
*sym
, guint level
)
41 g_return_if_fail (sym
!= NULL
);
42 for (i
=0; i
< level
; ++i
)
44 fprintf(stderr
, "%s\n", (sym
->tag
)?sym
->tag
->name
:"Root");
45 if (sym
->info
.children
)
47 if (sym
->tag
&& tm_tag_function_t
== sym
->tag
->type
)
48 tm_tag_print(sym
->info
.equiv
, stderr
);
51 for (i
=0; i
< sym
->info
.children
->len
; ++i
)
52 tm_symbol_print(TM_SYMBOL(sym
->info
.children
->pdata
[i
])
58 #define SYM_ORDER(T) (((tm_tag_class_t == (T)->type) || (tm_tag_struct_t ==\
59 (T)->type))?1:(((tm_tag_enum_t == (T)->type) || (tm_tag_interface_t ==\
62 /* Comparison function for sorting symbols alphabetically */
63 int tm_symbol_compare(const void *p1
, const void *p2
)
73 s1
= *(TMSymbol
**) p1
;
74 s2
= *(TMSymbol
**) p2
;
81 if (!s1
->tag
&& !s2
->tag
)
87 return strcmp(s1
->tag
->name
, s2
->tag
->name
);
91 * Compares function argument lists.
92 * FIXME: Compare based on types, not an exact string match.
94 int tm_arglist_compare(const TMTag
* t1
, const TMTag
* t2
)
96 return strcmp(NVL(t1
->atts
.entry
.arglist
, ""),
97 NVL(t2
->atts
.entry
.arglist
, ""));
100 /* Need this custom compare function to generate a symbol tree
101 in a simgle pass from tag list */
102 int tm_symbol_tag_compare(const TMTag
**t1
, const TMTag
**t2
)
106 if ((!t1
&& !t2
) || (!*t1
&& !*t2
))
108 else if (!t1
|| !*t1
)
110 else if (!t2
|| !*t2
)
112 if ((tm_tag_file_t
== (*t1
)->type
) && (tm_tag_file_t
== (*t2
)->type
))
114 else if (tm_tag_file_t
== (*t1
)->type
)
116 else if (tm_tag_file_t
== (*t2
)->type
)
119 /* Compare on depth of scope - less depth gets higher priortity */
120 s1
= tm_tag_scope_depth(*t1
);
121 s2
= tm_tag_scope_depth(*t2
);
125 /* Compare of tag type using a symbol ordering routine */
131 /* Compare names alphabetically */
132 s1
= strcmp((*t1
)->name
, (*t2
)->name
);
136 /* Compare scope alphabetically */
137 s1
= strcmp(NVL((*t1
)->atts
.entry
.scope
, ""),
138 NVL((*t2
)->atts
.entry
.scope
, ""));
142 /* If none of them are function/prototype, they are effectively equal */
143 if ((tm_tag_function_t
!= (*t1
)->type
) &&
144 (tm_tag_prototype_t
!= (*t1
)->type
)&&
145 (tm_tag_function_t
!= (*t2
)->type
) &&
146 (tm_tag_prototype_t
!= (*t2
)->type
))
149 /* Whichever is not a function/prototype goes first */
150 if ((tm_tag_function_t
!= (*t1
)->type
) &&
151 (tm_tag_prototype_t
!= (*t1
)->type
))
153 if ((tm_tag_function_t
!= (*t2
)->type
) &&
154 (tm_tag_prototype_t
!= (*t2
)->type
))
157 /* Compare the argument list */
158 s1
= tm_arglist_compare(*t1
, *t2
);
162 /* Functions go before prototypes */
163 if ((tm_tag_function_t
== (*t1
)->type
) &&
164 (tm_tag_function_t
!= (*t2
)->type
))
166 if ((tm_tag_function_t
!= (*t1
)->type
) &&
167 (tm_tag_function_t
== (*t2
)->type
))
174 TMSymbol
*tm_symbol_tree_new(GPtrArray
*tags_array
)
176 TMSymbol
*root
= NULL
;
180 g_message("Building symbol tree..");
183 if ((!tags_array
) || (tags_array
->len
<= 0))
187 fprintf(stderr
, "Dumping all tags..\n");
188 tm_tags_array_print(tags_array
, stderr
);
191 tags
= tm_tags_extract(tags_array
, tm_tag_max_t
);
193 fprintf(stderr
, "Dumping unordered tags..\n");
194 tm_tags_array_print(tags
, stderr
);
197 if (tags
&& (tags
->len
> 0))
201 int max_parents
= -1;
203 TMSymbol
*sym
= NULL
, *sym1
;
210 tm_tags_custom_sort(tags
, (TMTagCompareFunc
) tm_symbol_tag_compare
214 fprintf(stderr
, "Dumping ordered tags..");
215 tm_tags_array_print(tags
, stderr
);
216 fprintf(stderr
, "Rebuilding symbol table..\n");
218 for (i
=0; i
< tags
->len
; ++i
)
220 tag
= TM_TAG(tags
->pdata
[i
]);
222 if (tm_tag_prototype_t
== tag
->type
)
224 if (sym
&& (tm_tag_function_t
== sym
->tag
->type
) &&
225 (!sym
->info
.equiv
) &&
226 (0 == strcmp(NVL(tag
->atts
.entry
.scope
, "")
227 , NVL(sym
->tag
->atts
.entry
.scope
, ""))))
229 sym
->info
.equiv
= tag
;
235 if (SYM_ORDER(tag
) > 2)
239 qsort(root
->info
.children
->pdata
, max_parents
240 , sizeof(gpointer
), tm_symbol_compare
);
245 if ((max_parents
<= 0) || (!tag
->atts
.entry
.scope
))
248 if (!root
->info
.children
)
249 root
->info
.children
= g_ptr_array_new();
250 g_ptr_array_add(root
->info
.children
, sym
);
254 parent_name
= tag
->atts
.entry
.scope
;
255 scope_end
= strstr(tag
->atts
.entry
.scope
, "::");
259 if (('\0' != parent_name
[0]) &&
260 (0 != strcmp(parent_name
, "<anonymous>")))
262 for (j
=0; j
< max_parents
; ++j
)
264 sym1
= TM_SYMBOL(root
->info
.children
->pdata
[j
]);
265 str_match
= strcmp(sym1
->tag
->name
, parent_name
);
270 if (!sym1
->info
.children
)
271 sym1
->info
.children
= g_ptr_array_new();
272 g_ptr_array_add(sym1
->info
.children
, sym
);
275 else if (str_match
> 0)
282 if (!root
->info
.children
)
283 root
->info
.children
= g_ptr_array_new();
284 g_ptr_array_add(root
->info
.children
, sym
);
291 fprintf(stderr
, "Done.Dumping symbol tree..");
292 tm_symbol_print(root
, 0);
296 g_ptr_array_free(tags
, TRUE
);
301 static void tm_symbol_free(TMSymbol
*sym
)
305 if ((!sym
->tag
) || ((tm_tag_function_t
!= sym
->tag
->type
) &&
306 (tm_tag_prototype_t
!= sym
->tag
->type
)))
308 if (sym
->info
.children
)
311 for (i
=0; i
< sym
->info
.children
->len
; ++i
)
312 tm_symbol_free(TM_SYMBOL(sym
->info
.children
->pdata
[i
]));
313 g_ptr_array_free(sym
->info
.children
, TRUE
);
314 sym
->info
.children
= NULL
;
320 void tm_symbol_tree_free(gpointer root
)
323 tm_symbol_free(TM_SYMBOL(root
));
326 TMSymbol
*tm_symbol_tree_update(TMSymbol
*root
, GPtrArray
*tags
)
329 tm_symbol_free(root
);
330 if ((tags
) && (tags
->len
> 0))
331 return tm_symbol_tree_new(tags
);