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 (1627B)
---
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
12 Symbol *locals;
13 static Symbol *tail;
14
15 static Symbol *symtab[NR_SYMHASH];
16 static int infunction;
17
18
19 void
20 freesym(Symbol *sym)
21 {
22 free(sym->name);
23 free(sym);
24 }
25
26 void
27 pushctx(void)
28 {
29 infunction = 1;
30 }
31
32 void
33 popctx(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
58 Symbol *
59 getsym(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 }