symbol.c - scc - simple c99 compiler
(HTM) git clone git://git.simple-cc.org/scc
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) Submodules
(DIR) README
(DIR) LICENSE
---
symbol.c (3023B)
---
1 #include <assert.h>
2 #include <errno.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6
7 #include <scc/mach.h>
8 #include <scc/scc.h>
9
10 #include "ld.h"
11
12 #define NR_SYMBOL 128
13
14 /*
15 * struct symtab has a Symbol as first field because
16 * the code is going to cast from the symbols to the tab.
17 */
18 struct symtab {
19 Symbol sym;
20 Obj *where;
21 struct symtab *hash;
22 struct symtab *next, *prev;
23 };
24
25 static struct symtab *symtab[NR_SYMBOL];
26 static struct symtab undef = {.next = &undef, .prev = &undef};
27 static struct symtab def = {.next = &def, .prev = &def};
28 static struct symtab common = {.next = &common, .prev = &common};
29
30 static Symbol *
31 unlinksym(Symbol *sym)
32 {
33 struct symtab *sp = (struct symtab *) sym;
34
35 sp->next->prev = sp->prev;
36 sp->prev->next = sp->next;
37
38 return sym;
39 }
40
41 static Symbol *
42 linksym(struct symtab *lst, Symbol *sym)
43 {
44 struct symtab *sp = (struct symtab *) sym;
45
46 sp->next = lst;
47 sp->prev = lst->prev;
48 lst->prev->next = sp;
49 lst->prev = sp;
50
51 return sym;
52 }
53
54 int
55 hasref(char *name)
56 {
57 unsigned h;
58 struct symtab *sp;
59
60 h = genhash(name) % NR_SYMBOL;
61 for (sp = symtab[h]; sp; sp = sp->hash) {
62 if (!strcmp(name, sp->sym.name))
63 return sp->sym.type == 'U';
64 }
65 return 0;
66 }
67
68 Symbol *
69 lookupsym(char *name)
70 {
71 unsigned h;
72 size_t len;
73 char *s;
74 Symbol *sym;
75 struct symtab *sp;
76
77 h = genhash(name) % NR_SYMBOL;
78 for (sp = symtab[h]; sp; sp = sp->hash) {
79 if (!strcmp(name, sp->sym.name))
80 return &sp->sym;
81 }
82
83 len = strlen(name) + 1;
84 s = malloc(len);
85 sp = malloc(sizeof(*sp));
86 if (!s || !sp) {
87 error(strerror(errno));
88 exit(EXIT_FAILURE);
89 }
90
91 sym = &sp->sym;
92 sym->name = memcpy(s, name, len);
93 sym->value = 0;
94 sym->size = 0;
95 sym->index = 0;
96 sym->type = 'U';
97 sp->where = NULL;
98 sp->hash = symtab[h];
99 symtab[h] = sp;
100
101 return linksym(&undef, sym);
102 }
103
104
105 int
106 moreundef(void)
107 {
108 return undef.next != &undef;
109 }
110
111 void
112 listundef(void)
113 {
114 struct symtab *sp;
115
116 for (sp = undef.next; sp != &undef; sp = sp->next)
117 error("ld: symbol '%s' not defined", sp->sym.name);
118 }
119
120 Symbol *
121 define(Symbol *osym, Obj *obj)
122 {
123 struct symtab *lst;
124 Symbol *sym = lookupsym(osym->name);
125 struct symtab *sp = (struct symtab *) sym;
126
127 assert(osym->type != 'U');
128 sp->where = obj;
129
130 switch (sym->type) {
131 case 'U':
132 sym->value = osym->value;
133 sym->size = osym->size;
134 lst = (osym->type == 'C') ? &common : &def;
135 linksym(lst, unlinksym(sym));
136 break;
137 case 'C':
138 if (osym->type != 'C') {
139 sym->size = osym->size;
140 sym->value = osym->size;
141 linksym(&def, unlinksym(sym));
142 } else if (sym->size < osym->size) {
143 sym->value = osym->value;
144 sym->size = osym->size;
145 }
146 break;
147 defaul:
148 error("%s: symbol redefined", sym->name);
149 break;
150 }
151
152 return sym;
153 }
154
155 #ifndef NDEBUG
156 void
157 debugsym(void)
158 {
159 struct symtab **spp, *sp;
160 Symbol*sym;
161
162 fputs("Symbols:\n", stderr);
163 for (spp = symtab; spp < &symtab[NR_SYMBOL]; spp++) {
164 for (sp = *spp; sp; sp = sp->hash) {
165 sym = &sp->sym;
166 fprintf(stderr,
167 "sym: %s (%#llx)\n",
168 sym->name,
169 sym->value);
170 }
171 }
172 }
173 #endif