scc

A fork of https://git.simple-cc.org/scc/ for Qute

git clone https://git.8pit.net/scc.git

  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 */
 18struct symtab {
 19	Symbol sym;
 20	Obj *where;
 21	struct symtab *hash;
 22	struct symtab *next, *prev;
 23};
 24
 25static struct symtab *symtab[NR_SYMBOL];
 26static struct symtab undef = {.next = &undef, .prev = &undef};
 27static struct symtab def = {.next = &def, .prev = &def};
 28static struct symtab common = {.next = &common, .prev = &common};
 29
 30static Symbol *
 31unlinksym(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
 41static Symbol *
 42linksym(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
 54int
 55hasref(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
 68Symbol *
 69lookupsym(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
105int
106moreundef(void)
107{
108	return undef.next != &undef;
109}
110
111void
112listundef(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
120Symbol *
121define(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
156void
157debugsym(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