Currently I keep all the defined names in one doubly-linked list. If this proves to be a bottleneck it can be replaced with something more fancy without upsetting the rest of the program.
#include <ctype.h> #include <stdio.h> #include <string.h> #include "iofns.h" #include "memfns.h" #include "syms.h" /* symbol table entry */ typedef struct Symbol { char *name; long value; struct Symbol *next; struct Symbol *prev; } Symbol; static Symbol *base, *last; static Symbol *find_entry (char *name) { Symbol *p; for (p = base; p; p = p -> next) if (strcmp (p -> name, name) == 0) break; return (p); } int IsDefined (char *name) { return (!! find_entry (name)); } long GetValue (char *name) { Symbol *p = find_entry (name); if (! p) FatalPrintf (1, "uninitialised variable (%.100s) used", name); return (p -> value); } void Unset (char *name) { Symbol *p = find_entry (name); if (p) { my_free (p -> name); p -> name = NULL; if (p -> next) p -> next -> prev = p -> prev; else last = p -> prev; if (p -> prev) p -> prev -> next = p -> next; else base = p -> next; } } void SetValue (char *name, long value) { Symbol *p = find_entry (name); if (! p) { p = my_malloc (sizeof (Symbol)); p -> name = my_malloc (1 + strlen (name)); strcpy (p -> name, name); p -> next = base; if (base) base -> prev = p; p -> prev = NULL; base = p; } p -> value = value; } void ListSymbols (void) { Symbol *p; for (p = base; p; p = p -> next) fprintf (stderr, "%s: %ld\n", p -> name, p -> value); }