scc

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

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

 1#include <limits.h>
 2#include <stdio.h>
 3#include <stdlib.h>
 4#include <string.h>
 5
 6#include <scc/scc.h>
 7
 8#include "cc2.h"
 9
10#define NR_SYMHASH  64
11
12Symbol *locals;
13static Symbol *tail;
14
15static Symbol *symtab[NR_SYMHASH];
16static int infunction;
17
18
19void
20freesym(Symbol *sym)
21{
22	free(sym->name);
23	free(sym);
24}
25
26void
27pushctx(void)
28{
29	infunction = 1;
30}
31
32void
33popctx(void)
34{
35	Symbol *sym, *prev;
36
37	infunction = 0;
38	for (sym = tail; sym; sym = prev) {
39		prev = sym->prev;
40		/*
41		 * Symbols are inserted in the hash in the inverted
42		 * order they are found in locals and it is impossible
43		 * to have a global over a local, because a local is
44		 * any symbol defined in the body of a function,
45		 * even if it has extern linkage.
46		 * For this reason when we reach a symbol in the
47		 * locals list we know that it is the head of it
48		 * collision list and we can remove it assigning
49		 * it h_next to the hash table position
50		 */
51		if (sym->id != TMPSYM)
52			symtab[sym->id & NR_SYMHASH-1] = sym->h_next;
53		freesym(sym);
54	}
55	locals = tail = NULL;
56}
57
58Symbol *
59getsym(unsigned id)
60{
61	Symbol **htab, *sym;
62	static unsigned short num;
63
64	if (id >= USHRT_MAX)
65		error(EBADID);
66
67	if (id != TMPSYM) {
68		htab = &symtab[id & NR_SYMHASH-1];
69		for (sym = *htab; sym; sym = sym->h_next) {
70			if (sym->id == id)
71				return sym;
72		}
73	}
74
75	sym = xcalloc(1, sizeof(*sym));
76	sym->id = id;
77	if (infunction) {
78		sym->next = NULL;
79		sym->prev = tail;
80		if (tail)
81			tail->next = sym;
82		tail = sym;
83		if (!locals)
84			locals = sym;
85	}
86	if (id != TMPSYM) {
87		sym->h_next = *htab;
88		*htab = sym;
89	}
90	if ((sym->numid = ++num) == 0)
91		error(EIDOVER);
92
93	return sym;
94}