summaryrefslogtreecommitdiff
path: root/symbol.c
diff options
context:
space:
mode:
Diffstat (limited to 'symbol.c')
-rw-r--r--symbol.c119
1 files changed, 119 insertions, 0 deletions
diff --git a/symbol.c b/symbol.c
new file mode 100644
index 0000000..85be039
--- /dev/null
+++ b/symbol.c
@@ -0,0 +1,119 @@
+/* $Id: symbol.c,v 1.1 2004-05-03 05:17:48 behdad Exp $
+ *
+ * Symbol table maintenance. Implements an abstract data type called
+ * the symbol table.
+ */
+#include "c2man.h"
+#include "symbol.h"
+
+/* Create a symbol table.
+ * Return a pointer to the symbol table or NULL if an error occurs.
+ */
+SymbolTable *
+create_symbol_table ()
+{
+ SymbolTable *symtab;
+ int i;
+
+ symtab = (SymbolTable *)safe_malloc(sizeof(SymbolTable));
+
+ for (i = 0; i < SYM_MAX_HASH; ++i)
+ symtab->bucket[i] = NULL;
+
+ return symtab;
+}
+
+
+/* Free the memory allocated to the symbol table.
+ */
+void
+destroy_symbol_table (symtab)
+SymbolTable *symtab;
+{
+ int i;
+ Symbol *sym, *next;
+
+ for (i = 0; i < SYM_MAX_HASH; ++i) {
+ sym = symtab->bucket[i];
+ while (sym != NULL) {
+ next = sym->next;
+ free(sym->name);
+ free(sym);
+ sym = next;
+ }
+ }
+ free(symtab);
+}
+
+
+/* This is a simple hash function mapping a symbol name to a hash bucket. */
+
+static unsigned int
+hash (name)
+char *name;
+{
+ char *s;
+ unsigned int h;
+
+ h = 0;
+ s = name;
+ while (*s != '\0')
+ h = (h << 1) ^ *s++;
+ return h % SYM_MAX_HASH;
+}
+
+
+/* Search the list of symbols <list> for the symbol <name>.
+ * Return a pointer to the symbol or NULL if not found.
+ */
+static Symbol *
+search_symbol_list (list, name)
+Symbol *list;
+char *name;
+{
+ Symbol *sym;
+
+ for (sym = list; sym != NULL; sym = sym->next) {
+ if (strcmp(sym->name, name) == 0)
+ return sym;
+ }
+ return NULL;
+}
+
+
+/* Look for symbol <name> in symbol table <symtab>.
+ * Return a pointer to the symbol or NULL if not found.
+ */
+Symbol *
+find_symbol (symtab, name)
+SymbolTable *symtab;
+char *name;
+{
+ return search_symbol_list(symtab->bucket[hash(name)], name);
+}
+
+
+/* If the symbol <name> does not already exist in symbol table <symtab>,
+ * then add the symbol to the symbol table.
+ * Return a pointer to the symbol or NULL on an error.
+ */
+Symbol *
+new_symbol (symtab, name, flags)
+SymbolTable *symtab; /* symbol table */
+char *name; /* symbol name */
+int flags; /* symbol attributes */
+{
+ Symbol *sym;
+ int i;
+
+ if ((sym = find_symbol(symtab, name)) == NULL) {
+ sym = (Symbol *)safe_malloc(sizeof(Symbol));
+ sym->name = strduplicate(name);
+ sym->flags = flags;
+ sym->valtype = SYMVAL_NONE;
+ i = hash(name);
+ sym->next = symtab->bucket[i];
+ symtab->bucket[i] = sym;
+ }
+ return sym;
+}