diff options
Diffstat (limited to 'src/output.c')
-rw-r--r-- | src/output.c | 117 |
1 files changed, 64 insertions, 53 deletions
diff --git a/src/output.c b/src/output.c index f33d0ae..a617816 100644 --- a/src/output.c +++ b/src/output.c @@ -188,12 +188,18 @@ is_var(Symbol *symp) else return 1; } return 0; } +int +symbol_is_function(Symbol *symp) +{ + return symp->type == SymIdentifier && symp->arity >= 0; +} + static void clear_active(Symbol *sym) { sym->active = 0; } @@ -238,15 +244,15 @@ print_type(Symbol *symp) } void xref_output() { Symbol **symbols, *symp; - int i, num; + size_t i, num; - num = collect_symbols(&symbols, is_var); + num = collect_symbols(&symbols, is_var, 0); qsort(symbols, num, sizeof(*symbols), compare); /* produce xref output */ for (i = 0; i < num; i++) { symp = symbols[i]; switch (symp->type) { @@ -264,32 +270,12 @@ xref_output() } /* Tree output */ -/* Scan call tree. Mark the recursive calls - */ -static void -scan_tree(int lev, Symbol *sym) -{ - struct linked_list_entry *p; - - if (sym->type == SymUndefined) - return; - if (sym->active) { - sym->recursive = 1; - return; - } - sym->active = 1; - for (p = linked_list_head(sym->callee); p; p = p->next) { - scan_tree(lev+1, (Symbol*)p->data); - } - sym->active = 0; -} - static void set_active(Symbol *sym) { sym->active = out_line; } @@ -358,49 +344,74 @@ inverted_tree(int lev, int last, Symbol *sym) } static void tree_output() { Symbol **symbols, *main_sym; - int i, num; + size_t i, num; + cflow_depmap_t depmap; - /* Collect and sort symbols */ - num = collect_symbols(&symbols, is_var); - qsort(symbols, num, sizeof(*symbols), compare); - /* Scan and mark the recursive ones */ + /* Collect functions and assign them ordinal numbers */ + num = collect_functions(&symbols); + for (i = 0; i < num; i++) + symbols[i]->ord = i; + + /* Create a dependency matrix */ + depmap = depmap_alloc(num); for (i = 0; i < num; i++) { - if (symbols[i]->callee) - scan_tree(0, symbols[i]); + if (symbols[i]->callee) { + struct linked_list_entry *p; + + for (p = linked_list_head(symbols[i]->callee); p; + p = p->next) { + Symbol *s = (Symbol*) p->data; + if (symbol_is_function(s)) + depmap_set(depmap, i, ((Symbol*)p->data)->ord); + } + } } + depmap_tc(depmap); + + /* Mark recursive calls */ + for (i = 0; i < num; i++) + if (depmap_isset(depmap, i, i)) + symbols[i]->recursive = 1; + free(depmap); + free(symbols); + + /* Collect and sort all symbols */ + num = collect_symbols(&symbols, is_var, 0); + qsort(symbols, num, sizeof(*symbols), compare); + /* Produce output */ - begin(); - - if (reverse_tree) { - for (i = 0; i < num; i++) { - inverted_tree(0, 0, symbols[i]); - separator(); - } - } else { - main_sym = lookup(start_name); - if (main_sym) { - direct_tree(0, 0, main_sym); - separator(); - } else { - for (i = 0; i < num; i++) { - if (symbols[i]->callee == NULL) - continue; - direct_tree(0, 0, symbols[i]); - separator(); - } - } - } + begin(); - end(); - - free(symbols); + if (reverse_tree) { + for (i = 0; i < num; i++) { + inverted_tree(0, 0, symbols[i]); + separator(); + } + } else { + main_sym = lookup(start_name); + if (main_sym) { + direct_tree(0, 0, main_sym); + separator(); + } else { + for (i = 0; i < num; i++) { + if (symbols[i]->callee == NULL) + continue; + direct_tree(0, 0, symbols[i]); + separator(); + } + } + } + + end(); + + free(symbols); } void output() { if (strcmp(outname, "-") == 0) { |