summaryrefslogtreecommitdiffabout
Side-by-side diff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--src/cflow.h34
-rw-r--r--src/main.c18
-rw-r--r--src/output.c43
-rw-r--r--src/parser.c14
-rw-r--r--src/symbol.c187
5 files changed, 123 insertions, 173 deletions
diff --git a/src/cflow.h b/src/cflow.h
index 7a38682..c6712c9 100644
--- a/src/cflow.h
+++ b/src/cflow.h
@@ -1,5 +1,5 @@
/* This file is part of GNU cflow
- Copyright (C) 1997,2005,2007 Sergey Poznyakoff
+ Copyright (C) 1997,2005,2007,2009 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
@@ -45,15 +45,19 @@
#define NUMITEMS(a) sizeof(a)/sizeof((a)[0])
-typedef struct cons *Consptr;
-typedef struct cons Cons;
-struct cons {
- Consptr car;
- Consptr cdr;
+struct linked_list_entry {
+ struct linked_list_entry *next;
+ void *data;
};
-#define CAR(a) (a)->car
-#define CDR(a) (a)->cdr
+typedef void (*linked_list_free_data_fp) (void*);
+
+struct linked_list {
+ linked_list_free_data_fp free_data;
+ struct linked_list_entry *head, *tail;
+};
+
+#define linked_list_head(list) ((list) ? (list)->head : NULL)
enum symtype {
SymUndefined, /* Undefined or deleted symbol */
@@ -97,7 +101,7 @@ struct symbol {
int token_type; /* Type of the token */
char *source; /* Source file */
int def_line; /* Source line */
- Consptr ref_line; /* Referenced in */
+ struct linked_list *ref_line; /* Referenced in */
int level; /* Block nesting level (for local vars),
Parameter nesting level (for params) */
@@ -109,8 +113,8 @@ struct symbol {
variables */
int recursive; /* Is the function recursive */
- Consptr caller; /* List of callers */
- Consptr callee; /* List of callees */
+ struct linked_list *caller; /* List of callers */
+ struct linked_list *callee; /* List of callees */
};
/* Output flags */
@@ -162,10 +166,12 @@ void delete_autos(int level);
void delete_statics(void);
void delete_parms(int level);
void move_parms(int level);
-void cleanup(void);
int collect_symbols(Symbol ***, int (*sel)());
-Consptr append_to_list(Consptr *, void *);
-int symbol_in_list(Symbol *sym, Consptr list);
+struct linked_list *linked_list_create(linked_list_free_data_fp fun);
+void linked_list_destroy(struct linked_list **plist);
+void linked_list_append(struct linked_list **plist, void *data);
+void linked_list_prepend(struct linked_list **plist, void *data);
+int symbol_in_list(Symbol *sym, struct linked_list *list);
int get_token(void);
int source(char *name);
diff --git a/src/main.c b/src/main.c
index cbb472e..b08ccdd 100644
--- a/src/main.c
+++ b/src/main.c
@@ -218,7 +218,7 @@ int preprocess_option = 0; /* Do they want to preprocess sources? */
char *start_name = "main"; /* Name of start symbol */
-Consptr arglist; /* List of command line arguments */
+struct linked_list *arglist; /* List of command line arguments */
/* Given the option_type array and (possibly abbreviated) option argument
* find the type corresponding to that argument.
@@ -487,7 +487,7 @@ set_level_indent(const char *str)
static void
add_name(const char *name)
{
- append_to_list(&arglist, (void*) name);
+ linked_list_append(&arglist, (void*) name);
}
static void
@@ -769,16 +769,18 @@ main(int argc, char **argv)
init();
- if (arglist)
- /* See comment to cleanup_processor */
- for (arglist = CAR(arglist); arglist; arglist = CDR(arglist)) {
- char *s = (char*)CAR(arglist);
+ if (arglist) {
+ struct linked_list_entry *p;
+
+ for (p = arglist->head; p; p = p->next) {
+ char *s = (char*)p->data;
if (s[0] == '-')
pp_option(s);
else if (source(s) == 0)
yyparse();
}
-
+ }
+
argc -= index;
argv += index;
@@ -790,8 +792,6 @@ main(int argc, char **argv)
if (input_file_count == 0)
error(1, 0, _("no input files"));
- cleanup();
-
output();
return 0;
}
diff --git a/src/output.c b/src/output.c
index 7e604f4..f33d0ae 100644
--- a/src/output.c
+++ b/src/output.c
@@ -1,5 +1,5 @@
/* This file is part of GNU cflow
- Copyright (C) 1997,2005,2007 Sergey Poznyakoff
+ Copyright (C) 1997,2005,2007,2009 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
@@ -200,12 +200,13 @@ clear_active(Symbol *sym)
/* Cross-reference output */
void
-print_refs(char *name, Consptr cons)
+print_refs(char *name, struct linked_list *reflist)
{
Ref *refptr;
-
- for ( ; cons; cons = CDR(cons)) {
- refptr = (Ref*)CAR(cons);
+ struct linked_list_entry *p;
+
+ for (p = linked_list_head(reflist); p; p = p->next) {
+ refptr = (Ref*)p->data;
fprintf(outfile, "%s %s:%d\n",
name,
refptr->source,
@@ -271,7 +272,7 @@ xref_output()
static void
scan_tree(int lev, Symbol *sym)
{
- Consptr cons;
+ struct linked_list_entry *p;
if (sym->type == SymUndefined)
return;
@@ -280,8 +281,8 @@ scan_tree(int lev, Symbol *sym)
return;
}
sym->active = 1;
- for (cons = sym->callee; cons; cons = CDR(cons)) {
- scan_tree(lev+1, (Symbol*)CAR(cons));
+ for (p = linked_list_head(sym->callee); p; p = p->next) {
+ scan_tree(lev+1, (Symbol*)p->data);
}
sym->active = 0;
}
@@ -293,16 +294,16 @@ set_active(Symbol *sym)
}
static int
-is_printable(Consptr cons)
+is_printable(struct linked_list_entry *p)
{
- return cons != NULL && include_symbol((Symbol*)CAR(cons));
+ return p != NULL && include_symbol((Symbol*)p->data);
}
static int
-is_last(Consptr cons)
+is_last(struct linked_list_entry *p)
{
- while (cons = CDR(cons))
- if (is_printable(cons))
+ while (p = p->next)
+ if (is_printable(p))
return 0;
return 1;
}
@@ -312,7 +313,7 @@ is_last(Consptr cons)
static void
direct_tree(int lev, int last, Symbol *sym)
{
- Consptr cons;
+ struct linked_list_entry *p;
int rc;
if (sym->type == SymUndefined
@@ -325,9 +326,9 @@ direct_tree(int lev, int last, Symbol *sym)
if (rc || sym->active)
return;
set_active(sym);
- for (cons = sym->callee; cons; cons = CDR(cons)) {
- set_level_mark(lev+1, is_printable(CDR(cons)));
- direct_tree(lev+1, is_last(cons), (Symbol*)CAR(cons));
+ for (p = linked_list_head(sym->callee); p; p = p->next) {
+ set_level_mark(lev+1, is_printable(p->next));
+ direct_tree(lev+1, is_last(p), (Symbol*)p->data);
}
clear_active(sym);
}
@@ -337,7 +338,7 @@ direct_tree(int lev, int last, Symbol *sym)
static void
inverted_tree(int lev, int last, Symbol *sym)
{
- Consptr cons;
+ struct linked_list_entry *p;
int rc;
if (sym->type == SymUndefined
@@ -349,9 +350,9 @@ inverted_tree(int lev, int last, Symbol *sym)
if (rc || sym->active)
return;
set_active(sym);
- for (cons = sym->caller; cons; cons = CDR(cons)) {
- set_level_mark(lev+1, is_printable(CDR(cons)));
- inverted_tree(lev+1, is_last(cons), (Symbol*)CAR(cons));
+ for (p = linked_list_head(sym->caller); p; p = p->next) {
+ set_level_mark(lev+1, is_printable(p->next));
+ inverted_tree(lev+1, is_last(p), (Symbol*)p->data);
}
clear_active(sym);
}
diff --git a/src/parser.c b/src/parser.c
index 911bf58..26ac25d 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -1,5 +1,5 @@
/* This file is part of GNU cflow
- Copyright (C) 1997, 2005, 2006, 2007 Sergey Poznyakoff
+ Copyright (C) 1997, 2005, 2006, 2007, 2009 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
@@ -1077,7 +1077,9 @@ add_reference(char *name, int line)
refptr = xmalloc(sizeof(*refptr));
refptr->source = filename;
refptr->line = line;
- append_to_list(&sp->ref_line, refptr);
+ if (!sp->ref_line)
+ sp->ref_line = linked_list_create(free);
+ linked_list_append(&sp->ref_line, refptr);
return sp;
}
@@ -1094,9 +1096,9 @@ call(char *name, int line)
sp->arity = 0;
if (caller) {
if (!symbol_in_list(caller, sp->caller))
- append_to_list(&sp->caller, caller);
+ linked_list_append(&sp->caller, caller);
if (!symbol_in_list(sp, caller->callee))
- append_to_list(&caller->callee, sp);
+ linked_list_append(&caller->callee, sp);
}
}
@@ -1108,9 +1110,9 @@ reference(char *name, int line)
return;
if (caller) {
if (!symbol_in_list(caller, sp->caller))
- append_to_list(&sp->caller, caller);
+ linked_list_append(&sp->caller, caller);
if (!symbol_in_list(sp, caller->callee))
- append_to_list(&caller->callee, sp);
+ linked_list_append(&caller->callee, sp);
}
}
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 @@
/* This file is part of GNU cflow
- Copyright (C) 1997, 2005, 2006, 2007 Sergey Poznyakoff
+ Copyright (C) 1997, 2005, 2006, 2007, 2009 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
@@ -110,18 +110,19 @@ delete_symbol(struct table_entry *tp)
Symbol *s = unlink_symbol(tp);
/* The symbol could have been referenced even if it is static
in -i^s mode. See tests/static.at for details. */
- if (s->ref_line == NULL)
+ if (s->ref_line == NULL) {
+ linked_list_destroy(&s->ref_line);
+ linked_list_destroy(&s->caller);
+ linked_list_destroy(&s->callee);
free(s);
+ }
}
-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.
+ it is unlinked from its table entry.
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. */
@@ -137,7 +138,7 @@ static_processor(void *data, void *proc_data)
if (globals_only())
delete_symbol(t);
else
- cleanup_symbol_refs(unlink_symbol(t));
+ unlink_symbol(t);
}
return true;
}
@@ -174,7 +175,7 @@ auto_processor(void *data, void *proc_data)
break;
case StaticStorage:
- cleanup_symbol_refs(unlink_symbol(t));
+ unlink_symbol(t);
break;
default:
@@ -193,48 +194,6 @@ delete_autos(int level)
hash_do_for_each (symbol_table, auto_processor, &level);
}
-
-/* Make all list pointers of the SYM ready for final processing.
- * This means for each list replace its entry point with its CAR
- * and throw away the first cons. The first cons holds pointers
- * to the head and tail of the list and is used to speed up appends.
- *
- * 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 = t->sym; sym; sym = sym->next) {
- cleanup_symbol_refs(sym);
- }
- return true;
-}
-
-
-/* Clean up all symbols from the auxiliary information.
- * See the comment for cleanup_symbol() above
- */
-void
-cleanup()
-{
- hash_do_for_each (symbol_table, cleanup_processor, NULL);
-}
-
struct collect_data {
Symbol **sym;
int (*sel)(Symbol *p);
@@ -324,97 +283,79 @@ move_parms(int level)
}
-typedef struct bucket Bucket;
-struct bucket {
- Bucket *next; /* Next bucket */
- int free;
- Cons cons[1];
-};
-
-static int bucket_nodes = 512;
-static Bucket *root_bucket, *last_bucket;
-void
-alloc_new_bucket()
+static struct linked_list *
+deref_linked_list (struct linked_list **plist)
{
- Bucket *bp;
-
- bp = malloc(sizeof(*bp) + sizeof(Cons)*(bucket_nodes-1));
- if (!bp)
- return;
- bp->next = NULL;
- bp->free = 0;
- if (!root_bucket)
- root_bucket = last_bucket = bp;
- else {
- last_bucket->next = bp;
- last_bucket = bp;
+ if (!*plist) {
+ struct linked_list *list = xmalloc(sizeof(*list));
+ list->free_data = NULL;
+ list->head = list->tail = NULL;
+ *plist = list;
}
+ return *plist;
}
-Consptr
-alloc_cons_from_bucket()
+
+struct linked_list *
+linked_list_create(linked_list_free_data_fp fun)
{
- if (!last_bucket || last_bucket->free == bucket_nodes)
- return NULL;
- return &last_bucket->cons[last_bucket->free++];
+ struct linked_list *list = xmalloc(sizeof(*list));
+ list->free_data = fun;
+ list->head = list->tail = NULL;
+ return list;
}
-Consptr
-alloc_cons()
+void
+linked_list_append(struct linked_list **plist, void *data)
{
- Consptr cp;
-
- cp = alloc_cons_from_bucket();
- if (!cp) {
- alloc_new_bucket();
- if ((cp = alloc_cons_from_bucket()) == NULL) {
- error(2, 0, _("not enough core"));
- }
- }
- CAR(cp) = CDR(cp) = NULL;
- return cp;
+ struct linked_list *list = deref_linked_list (plist);
+ struct linked_list_entry *entry = xmalloc(sizeof(*entry));
+ entry->next = NULL;
+ entry->data = data;
+ if (list->tail)
+ list->tail->next = entry;
+ else
+ list->head = entry;
+ list->tail = entry;
}
-/* Append a new cons to the tail of the list
- * ROOT_PTR points to a `root cons'.
- * CAR is the car value of the cons to be created.
- *
- * Note: Car of the root cons points to the head of the list,
- * cdr of root cons points to the tail of the list.
- */
-Consptr
-append_to_list(Consptr *root_ptr, void *car)
+void
+linked_list_prepend(struct linked_list **plist, void *data)
{
- Consptr root, cons;
-
- if (!*root_ptr) {
- *root_ptr = alloc_cons();
- /* both car and cdr are guaranteed to be NULL */
+ struct linked_list *list = deref_linked_list (plist);
+ struct linked_list_entry *entry = xmalloc(sizeof(*entry));
+ entry->next = list->head;
+ entry->data = data;
+ list->head = entry;
+ if (!list->tail)
+ list->tail = entry;
+}
+
+void
+linked_list_destroy(struct linked_list **plist)
+{
+ if (plist && *plist) {
+ struct linked_list *list = *plist;
+ struct linked_list_entry *p;
+
+ for (p = list->head; p; p = p->next) {
+ if (list->free_data)
+ list->free_data(p->data);
+ free(p);
+ }
+ free(list);
+ *plist = NULL;
}
- root = *root_ptr;
-
- cons = alloc_cons();
- if (!CAR(root))
- CAR(root) = cons;
-
- /* Maintain linked list */
- if (CDR(root))
- CDR(CDR(root)) = cons;
- CDR(root) = cons;
- CAR(cons) = car;
- return cons;
}
int
-symbol_in_list(Symbol *sym, Consptr list)
+symbol_in_list(Symbol *sym, struct linked_list *list)
{
- Consptr cons;
+ struct linked_list_entry *p;
- if (!list)
- return 0;
- for (cons = CAR(list); cons; cons = CDR(cons))
- if ((Symbol*)CAR(cons) == sym)
+ for (p = linked_list_head(list); p; p = p->next)
+ if ((Symbol*)p->data == sym)
return 1;
return 0;
}

Return to:

Send suggestions and report system problems to the System administrator.