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);
}