aboutsummaryrefslogtreecommitdiff
path: root/src/symbol.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/symbol.c')
-rw-r--r--src/symbol.c187
1 files changed, 64 insertions, 123 deletions
diff --git a/src/symbol.c b/src/symbol.c
index 4fe5f85..e3ccd7c 100644
--- a/src/symbol.c
+++ b/src/symbol.c
@@ -1,5 +1,5 @@
1/* This file is part of GNU cflow 1/* This file is part of GNU cflow
2 Copyright (C) 1997, 2005, 2006, 2007 Sergey Poznyakoff 2 Copyright (C) 1997, 2005, 2006, 2007, 2009 Sergey Poznyakoff
3 3
4 GNU cflow is free software; you can redistribute it and/or modify 4 GNU cflow is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 5 it under the terms of the GNU General Public License as published by
@@ -110,18 +110,19 @@ delete_symbol(struct table_entry *tp)
110 Symbol *s = unlink_symbol(tp); 110 Symbol *s = unlink_symbol(tp);
111 /* The symbol could have been referenced even if it is static 111 /* The symbol could have been referenced even if it is static
112 in -i^s mode. See tests/static.at for details. */ 112 in -i^s mode. See tests/static.at for details. */
113 if (s->ref_line == NULL) 113 if (s->ref_line == NULL) {
114 linked_list_destroy(&s->ref_line);
115 linked_list_destroy(&s->caller);
116 linked_list_destroy(&s->callee);
114 free(s); 117 free(s);
118 }
115} 119}
116 120
117static void cleanup_symbol_refs(Symbol *sym);
118
119/* Delete from the symbol table all static symbols defined in the current 121/* Delete from the symbol table all static symbols defined in the current
120 source. 122 source.
121 If the user requested static symbols in the listing, the symbol is 123 If the user requested static symbols in the listing, the symbol is
122 not deleted, as it may have been referenced by other symbols. Instead, 124 not deleted, as it may have been referenced by other symbols. Instead,
123 it is unlinked from its table entry and cleanup_symbol_refs() is 125 it is unlinked from its table entry.
124 called, so that its reference tables become usable.
125 NOTE: This takes advantage of the fact that install() uses LIFO strategy, 126 NOTE: This takes advantage of the fact that install() uses LIFO strategy,
126 so we don't have to check the name of the source where the symbol was 127 so we don't have to check the name of the source where the symbol was
127 defined. */ 128 defined. */
@@ -137,7 +138,7 @@ static_processor(void *data, void *proc_data)
137 if (globals_only()) 138 if (globals_only())
138 delete_symbol(t); 139 delete_symbol(t);
139 else 140 else
140 cleanup_symbol_refs(unlink_symbol(t)); 141 unlink_symbol(t);
141 } 142 }
142 return true; 143 return true;
143} 144}
@@ -174,7 +175,7 @@ auto_processor(void *data, void *proc_data)
174 break; 175 break;
175 176
176 case StaticStorage: 177 case StaticStorage:
177 cleanup_symbol_refs(unlink_symbol(t)); 178 unlink_symbol(t);
178 break; 179 break;
179 180
180 default: 181 default:
@@ -193,48 +194,6 @@ delete_autos(int level)
193 hash_do_for_each (symbol_table, auto_processor, &level); 194 hash_do_for_each (symbol_table, auto_processor, &level);
194} 195}
195 196
196
197/* Make all list pointers of the SYM ready for final processing.
198 * This means for each list replace its entry point with its CAR
199 * and throw away the first cons. The first cons holds pointers
200 * to the head and tail of the list and is used to speed up appends.
201 *
202 * TODO: The memory is not reclaimed
203 */
204static void
205cleanup_symbol_refs(Symbol *sym)
206{
207 if (sym && sym->type == SymIdentifier) {
208 if (sym->ref_line)
209 sym->ref_line = CAR(sym->ref_line);
210 if (sym->caller)
211 sym->caller = CAR(sym->caller);
212 if (sym->callee)
213 sym->callee = CAR(sym->callee);
214 }
215}
216
217static bool
218cleanup_processor(void *data, void *proc_data)
219{
220 struct table_entry *t = data;
221 Symbol *sym;
222 for (sym = t->sym; sym; sym = sym->next) {
223 cleanup_symbol_refs(sym);
224 }
225 return true;
226}
227
228
229/* Clean up all symbols from the auxiliary information.
230 * See the comment for cleanup_symbol() above
231 */
232void
233cleanup()
234{
235 hash_do_for_each (symbol_table, cleanup_processor, NULL);
236}
237
238struct collect_data { 197struct collect_data {
239 Symbol **sym; 198 Symbol **sym;
240 int (*sel)(Symbol *p); 199 int (*sel)(Symbol *p);
@@ -324,97 +283,79 @@ move_parms(int level)
324} 283}
325 284
326 285
327typedef struct bucket Bucket;
328struct bucket {
329 Bucket *next; /* Next bucket */
330 int free;
331 Cons cons[1];
332};
333
334static int bucket_nodes = 512;
335static Bucket *root_bucket, *last_bucket;
336 286
337void 287static struct linked_list *
338alloc_new_bucket() 288deref_linked_list (struct linked_list **plist)
339{ 289{
340 Bucket *bp; 290 if (!*plist) {
341 291 struct linked_list *list = xmalloc(sizeof(*list));
342 bp = malloc(sizeof(*bp) + sizeof(Cons)*(bucket_nodes-1)); 292 list->free_data = NULL;
343 if (!bp) 293 list->head = list->tail = NULL;
344 return; 294 *plist = list;
345 bp->next = NULL;
346 bp->free = 0;
347 if (!root_bucket)
348 root_bucket = last_bucket = bp;
349 else {
350 last_bucket->next = bp;
351 last_bucket = bp;
352 } 295 }
296 return *plist;
353} 297}
354 298
355Consptr 299
356alloc_cons_from_bucket() 300struct linked_list *
301linked_list_create(linked_list_free_data_fp fun)
357{ 302{
358 if (!last_bucket || last_bucket->free == bucket_nodes) 303 struct linked_list *list = xmalloc(sizeof(*list));
359 return NULL; 304 list->free_data = fun;
360 return &last_bucket->cons[last_bucket->free++]; 305 list->head = list->tail = NULL;
306 return list;
361} 307}
362 308
363Consptr 309void
364alloc_cons() 310linked_list_append(struct linked_list **plist, void *data)
365{ 311{
366 Consptr cp; 312 struct linked_list *list = deref_linked_list (plist);
367 313 struct linked_list_entry *entry = xmalloc(sizeof(*entry));
368 cp = alloc_cons_from_bucket(); 314 entry->next = NULL;
369 if (!cp) { 315 entry->data = data;
370 alloc_new_bucket(); 316 if (list->tail)
371 if ((cp = alloc_cons_from_bucket()) == NULL) { 317 list->tail->next = entry;
372 error(2, 0, _("not enough core")); 318 else
373 } 319 list->head = entry;
374 } 320 list->tail = entry;
375 CAR(cp) = CDR(cp) = NULL;
376 return cp;
377} 321}
378 322
379/* Append a new cons to the tail of the list 323void
380 * ROOT_PTR points to a `root cons'. 324linked_list_prepend(struct linked_list **plist, void *data)
381 * CAR is the car value of the cons to be created.
382 *
383 * Note: Car of the root cons points to the head of the list,
384 * cdr of root cons points to the tail of the list.
385 */
386Consptr
387append_to_list(Consptr *root_ptr, void *car)
388{ 325{
389 Consptr root, cons; 326 struct linked_list *list = deref_linked_list (plist);
390 327 struct linked_list_entry *entry = xmalloc(sizeof(*entry));
391 if (!*root_ptr) { 328 entry->next = list->head;
392 *root_ptr = alloc_cons(); 329 entry->data = data;
393 /* both car and cdr are guaranteed to be NULL */ 330 list->head = entry;
331 if (!list->tail)
332 list->tail = entry;
333}
334
335void
336linked_list_destroy(struct linked_list **plist)
337{
338 if (plist && *plist) {
339 struct linked_list *list = *plist;
340 struct linked_list_entry *p;
341
342 for (p = list->head; p; p = p->next) {
343 if (list->free_data)
344 list->free_data(p->data);
345 free(p);
346 }
347 free(list);
348 *plist = NULL;
394 } 349 }
395 root = *root_ptr;
396
397 cons = alloc_cons();
398 if (!CAR(root))
399 CAR(root) = cons;
400
401 /* Maintain linked list */
402 if (CDR(root))
403 CDR(CDR(root)) = cons;
404 CDR(root) = cons;
405 CAR(cons) = car;
406 return cons;
407} 350}
408 351
409int 352int
410symbol_in_list(Symbol *sym, Consptr list) 353symbol_in_list(Symbol *sym, struct linked_list *list)