diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2006-03-15 19:33:01 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2006-03-15 19:33:01 +0000 |
commit | 79d36e31afc3d1a7d8f6246b7b2407f5fc22dbb8 (patch) | |
tree | a7ca8cfaa55fd03ea1ff1d66ef36298ee5d46d63 /src | |
parent | d554d1c146acc8cce076669a1e42abd4b2352a4a (diff) | |
download | cflow-79d36e31afc3d1a7d8f6246b7b2407f5fc22dbb8.tar.gz cflow-79d36e31afc3d1a7d8f6246b7b2407f5fc22dbb8.tar.bz2 |
Change organization of the symbol table: the
table entry contains struct table_entry, which contains a pointer
to the head of the symbol list associated with the entry. Thus,
deletions from the table can be handled in a more natural manner.
All functions changed to reflect the change.
(unlink_symbol): New function.
(delete_symbol): Rewritten using unlink_symbol
(delete_statics): always call static_processor
Diffstat (limited to 'src')
-rw-r--r-- | src/symbol.c | 187 |
1 files changed, 119 insertions, 68 deletions
diff --git a/src/symbol.c b/src/symbol.c index dab0d29..c31a323 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -1,5 +1,5 @@ /* This file is part of GNU cflow - Copyright (C) 1997,2005 Sergey Poznyakoff + Copyright (C) 1997, 2005, 2006 Sergey Poznyakoff GNU cflow is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,45 +20,59 @@ #include <parser.h> #include <hash.h> -Hash_table *symbol_table; +static Hash_table *symbol_table; + +struct table_entry { + Symbol *sym; +}; /* Calculate the hash of a string. */ -static unsigned +static size_t hash_symbol_hasher(void const *data, unsigned n_buckets) { - Symbol const *sym = data; - return hash_string(sym->name, n_buckets); + struct table_entry const *t = data; + if (!t->sym) + return ((size_t) data) % n_buckets; + return hash_string(t->sym->name, n_buckets); } /* Compare two strings for equality. */ static bool hash_symbol_compare(void const *data1, void const *data2) { - Symbol const *s1 = data1; - Symbol const *s2 = data2; - return strcmp(s1->name, s2->name) == 0; + struct table_entry const *t1 = data1; + struct table_entry const *t2 = data2; + return t1->sym && t2->sym && strcmp(t1->sym->name, t2->sym->name) == 0; } Symbol * lookup(char *name) { Symbol s; + struct table_entry t, *tp; + if (!symbol_table) return NULL; s.name = name; - return hash_lookup(symbol_table, &s); + t.sym = &s; + tp = hash_lookup(symbol_table, &t); + return tp ? tp->sym : NULL; } Symbol * install(char *name) { - Symbol *sym, *s; - + Symbol *sym; + struct table_entry *tp, *ret; + sym = xmalloc(sizeof(*sym)); memset(sym, 0, sizeof(*sym)); sym->type = SymUndefined; sym->name = name; + tp = xmalloc(sizeof(*tp)); + tp->sym = sym; + if (canonical_filename && strcmp(filename, canonical_filename)) sym->flag = symbol_temp; else @@ -68,37 +82,42 @@ install(char *name) || (symbol_table = hash_initialize (0, 0, hash_symbol_hasher, hash_symbol_compare, 0))) - && (s = hash_insert (symbol_table, sym)))) + && (ret = hash_insert (symbol_table, tp)))) xalloc_die (); - if (s != sym) { - if (s->type == SymUndefined) { - *s = *sym; - free(sym); - } else { - Symbol tmp = *s; - *s = *sym; - *sym = tmp; - s->next = sym; - } + if (ret != tp) { + if (ret->sym->type != SymUndefined) + sym->next = ret->sym; + ret->sym = sym; } - return s; + return sym; } +/* Unlink the first symbol from the table entry */ +static Symbol * +unlink_symbol(struct table_entry *tp) +{ + Symbol *s = tp->sym; + if (s) + tp->sym = s->next; + return s; +} + +/* Unlink and free the first symbol from the table entry */ static void -delete_symbol(Symbol *s) +delete_symbol(struct table_entry *tp) { - Symbol *next = s->next; - if (next) { - *s = *next; - free(next); - } else { - s->type = SymUndefined; - } + free(unlink_symbol(tp)); } +static void cleanup_symbol_refs(Symbol *sym); + /* Delete from the symbol table all static symbols defined in the current source. + If the user requested static symbols in the listing, the symbol is + not deleted, as it may have been referenced by other symbols. Instead, + it is unlinked from its table entry and cleanup_symbol_refs() is + called, so that its reference tables become usable. NOTE: This takes advantage of the fact that install() uses LIFO strategy, so we don't have to check the name of the source where the symbol was defined. */ @@ -106,28 +125,33 @@ delete_symbol(Symbol *s) static bool static_processor(void *data, void *proc_data) { - Symbol *s = data; - - if (s->type == SymIdentifier && s->storage == StaticStorage) - delete_symbol(s); + struct table_entry *t = data; + + if (t->sym + && t->sym->type == SymIdentifier + && t->sym->storage == StaticStorage) { + if (globals_only()) + delete_symbol(t); + else + cleanup_symbol_refs(unlink_symbol(t)); + } return true; } static bool temp_processor(void *data, void *proc_data) { - Symbol *s = data; + struct table_entry *t = data; - if (s->flag == symbol_temp) - delete_symbol(s); + if (t->sym && t->sym->flag == symbol_temp) + delete_symbol(t); return true; } void delete_statics() { - if (globals_only()) - hash_do_for_each (symbol_table, static_processor, NULL); + hash_do_for_each (symbol_table, static_processor, NULL); hash_do_for_each (symbol_table, temp_processor, NULL); } @@ -135,11 +159,25 @@ delete_statics() bool auto_processor(void *data, void *proc_data) { - Symbol *s = data; - int *level = proc_data; - if (s->type == SymIdentifier && s->storage == AutoStorage - && s->level == *level) - delete_symbol(s); + struct table_entry *t = data; + Symbol *s = t->sym; + if (s) { + int *level = proc_data; + if (s->type == SymIdentifier && s->level == *level) { + switch (s->storage) { + case AutoStorage: + delete_symbol(t); + break; + + case StaticStorage: + cleanup_symbol_refs(unlink_symbol(t)); + break; + + default: + break; + } + } + } return true; } @@ -159,20 +197,26 @@ delete_autos(int level) * * TODO: The memory is not reclaimed */ +static void +cleanup_symbol_refs(Symbol *sym) +{ + if (sym && sym->type == SymIdentifier) { + if (sym->ref_line) + sym->ref_line = CAR(sym->ref_line); + if (sym->caller) + sym->caller = CAR(sym->caller); + if (sym->callee) + sym->callee = CAR(sym->callee); + } +} + static bool cleanup_processor(void *data, void *proc_data) { + struct table_entry *t = data; Symbol *sym; - - for (sym = data; sym; sym = sym->next) { - if (sym->type == SymIdentifier) { - if (sym->ref_line) - sym->ref_line = CAR(sym->ref_line); - if (sym->caller) - sym->caller = CAR(sym->caller); - if (sym->callee) - sym->callee = CAR(sym->callee); - } + for (sym = t->sym; sym; sym = sym->next) { + cleanup_symbol_refs(sym); } return true; } @@ -196,9 +240,10 @@ struct collect_data { static bool collect_processor(void *data, void *proc_data) { - Symbol *s; + struct table_entry *t = data; struct collect_data *cd = proc_data; - for (s = data; s; s = s->next) { + Symbol *s; + for (s = t->sym; s; s = s->next) { if (cd->sel(s)) { if (cd->sym) cd->sym[cd->index] = s; @@ -232,11 +277,14 @@ collect_symbols(Symbol ***return_sym, int (*sel)(Symbol *p)) static bool delete_parm_processor(void *data, void *proc_data) { - Symbol *s = data; - int *level = proc_data; - if (s->type == SymIdentifier && s->storage == AutoStorage - && s->flag == symbol_parm && s->level > *level) - delete_symbol(s); + struct table_entry *t = data; + Symbol *s = t->sym; + if (s) { + int *level = proc_data; + if (s->type == SymIdentifier && s->storage == AutoStorage + && s->flag == symbol_parm && s->level > *level) + delete_symbol(t); + } return true; } @@ -250,12 +298,15 @@ delete_parms(int level) static bool move_parm_processor(void *data, void *proc_data) { - Symbol *s = data; - int level = *(int*)proc_data; - if (s->type == SymIdentifier && s->storage == AutoStorage - && s->flag == symbol_parm) { - s->level = level; - s->flag = symbol_none; + struct table_entry *t = data; + Symbol *s = t->sym; + if (s) { + int level = *(int*)proc_data; + if (s->type == SymIdentifier && s->storage == AutoStorage + && s->flag == symbol_parm) { + s->level = level; + s->flag = symbol_none; + } } return true; } |