shithub: scc

ref: ff9a7ec77a798f1555fa184a1516f3f721943560
dir: /cc1/symbol.c/

View raw version

#include <stdint.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

#include <cc.h>
#include "cc1.h"

#define NR_SYM_HASH 32

uint8_t curctx;
short symid;

static struct symtab {
	Symbol *head;
	Symbol *htab[NR_SYM_HASH];
} symtab [NR_NAMESPACES];

static inline uint8_t
hash(register const char *s)
{
	register uint8_t h, ch;

	for (h = 0; ch = *s++; h += ch)
		/* nothing */;
	return h & NR_SYM_HASH - 1;
}

static void
freesyms(uint8_t ns)
{
	static struct symtab *tbl;
	register Symbol *sym, *next;

	tbl = &symtab[ns];
	for (sym = tbl->head; sym; sym = next) {
		if (sym->ctx <= curctx)
			break;
		if (ns == NS_LABEL && !sym->s.isdefined)
			error("label '%s' is not defined", sym->name);
		tbl->htab[hash(sym->name)] = sym->hash;
		next = tbl->head = sym->next;
		free(sym->name);
		free(sym);
	}
}

Type *
aggregate(Type * (*fun)(void))
{
	Type *tp;

	++curctx;
	tp = (*fun)();
	--curctx;
	freesyms(NS_IDEN);
	return tp;
}

void
context(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
{
	++curctx;
	compound(lbreak, lcont, lswitch);
	--curctx;
	freesyms(NS_IDEN);
	freesyms(NS_TAG);
	if (curctx == 0)
		freesyms(NS_LABEL);
}

Symbol *
lookup(register char *s, uint8_t ns)
{
	struct symtab *tbl;
	register Symbol *sym;

	tbl = &symtab[ns];
	for (sym = tbl->htab[hash(s)]; sym; sym = sym->hash) {
		if (!strcmp(sym->name, s))
			return sym;
	}

	return NULL;
}

Symbol *
install(char *s, uint8_t ns)
{
	register Symbol *sym, **t;
	struct symtab *tbl;

	sym = xcalloc(1, sizeof(*sym));
	sym->name = xstrdup(s);
	sym->ctx = curctx;
	sym->token = IDEN;
	sym->id = symid++;
	sym->s.isdefined = 1;
	tbl = &symtab[ns];
	sym->next = tbl->head;
	tbl->head = sym;

	t = &tbl->htab[hash(s)];
	sym->hash = *t;
	return *t = sym;
}