-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsymbol.c
111 lines (99 loc) · 2.36 KB
/
symbol.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/* $Id: symbol.c,v 4.9 2011/01/02 19:17:15 tom Exp $
*
* Implements a symbol table abstract data type.
*/
#include <symbol.h>
/* Create a symbol table.
* Return a pointer to the symbol table or NULL if an error occurs.
*/
SymbolTable *
new_symbol_table(void)
{
SymbolTable *symtab;
int i;
if ((symtab = NEW(SymbolTable)) != NULL) {
for (i = 0; i < SYM_MAX_HASH; ++i)
symtab->bucket[i] = NULL;
}
return symtab;
}
/* Free the memory allocated to the symbol table.
*/
void
free_symbol_table(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;
if (sym->name != 0)
free(sym->name);
if (sym->value != 0)
free(sym->value);
free(sym);
sym = next;
}
}
free(symtab);
}
/* This is a simple hash function mapping a symbol name to a hash bucket. */
static unsigned
hash(const char *name)
{
const char *s;
unsigned h;
h = 0;
s = name;
while (*s != '\0')
h = (h << 1) ^ (unsigned char) (*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(Symbol * list, const 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(SymbolTable * symtab, const 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.
*/
Symbol *
new_symbol(
SymbolTable * symtab, /* symbol table */
const char *name, /* symbol name */
const char *value, /* symbol value */
int flags) /* symbol attributes */
{
Symbol *sym;
unsigned i;
if ((sym = find_symbol(symtab, name)) == NULL) {
sym = NEW(Symbol);
sym->name = xstrdup(name);
i = hash(name);
sym->next = symtab->bucket[i];
symtab->bucket[i] = sym;
} else {
free(sym->value);
}
sym->value = (value != NULL) ? xstrdup(value) : NULL;
sym->flags = (short) flags;
return sym;
}