scc

Simple C99 Compiler
Log | Files | Refs | README | LICENSE

symbol.c (6051B)


      1 /* See LICENSE file for copyright and license details. */
      2 #include <limits.h>
      3 #include <stdio.h>
      4 #include <stdlib.h>
      5 #include <string.h>
      6 
      7 #include "../inc/cc.h"
      8 #include "../inc/sizes.h"
      9 #include "arch.h"
     10 #include "cc1.h"
     11 
     12 #define NR_SYM_HASH 64
     13 
     14 unsigned curctx;
     15 static unsigned short counterid;
     16 
     17 static Symbol *head, *labels;
     18 static Symbol *htab[NR_SYM_HASH];
     19 
     20 #ifndef NDEBUG
     21 void
     22 dumpstab(char *msg)
     23 {
     24 	Symbol **bp, *sym;
     25 
     26 	fprintf(stderr, "Symbol Table dump at ctx=%u\n%s\n", curctx, msg);
     27 	for (bp = htab; bp < &htab[NR_SYM_HASH]; ++bp) {
     28 		if (*bp == NULL)
     29 			continue;
     30 		fprintf(stderr, "%d", (int) (bp - htab));
     31 		for (sym = *bp; sym; sym = sym->hash)
     32 			fprintf(stderr, "->[%d,%d:'%s'=%p]",
     33 			        sym->ns, sym->ctx, sym->name, (void *) sym);
     34 		putc('\n', stderr);
     35 	}
     36 	fputs("head:", stderr);
     37 	for (sym = head; sym; sym = sym->next) {
     38 		fprintf(stderr, "->[%d,%d:'%s'=%p]",
     39 		        sym->ns, sym->ctx,
     40 		        (sym->name) ? sym->name : "", (void *) sym);
     41 	}
     42 	putc('\n', stderr);
     43 }
     44 #endif
     45 
     46 static unsigned
     47 hash(const char *s)
     48 {
     49 	unsigned c, h;
     50 
     51 	for (h = 0; c = *s; ++s)
     52 		h ^= 33 * c;
     53 	return h & NR_SYM_HASH-1;
     54 }
     55 
     56 static void
     57 unlinkhash(Symbol *sym)
     58 {
     59 	Symbol **h, *p, *prev;
     60 
     61 	if ((sym->flags & SDECLARED) == 0)
     62 		return;
     63 	h = &htab[hash(sym->name)];
     64 	for (prev = p = *h; p != sym; prev = p, p = p->hash)
     65 		/* nothing */;
     66 	if (prev == p)
     67 		*h = sym->hash;
     68 	else
     69 		prev->hash = sym->hash;
     70 }
     71 
     72 void
     73 pushctx(void)
     74 {
     75 	if (++curctx == NR_BLOCK+1)
     76 		error("too many nested blocks");
     77 }
     78 
     79 void
     80 killsym(Symbol *sym)
     81 {
     82 	short f;
     83 	char *name;
     84 
     85 	f = sym->flags;
     86 	if (f & SSTRING)
     87 		free(sym->u.s);
     88 	if (sym->ns == NS_TAG)
     89 		sym->type->prop &= ~TDEFINED;
     90 	unlinkhash(sym);
     91 	if ((name = sym->name) != NULL && sym->ns != NS_CPP) {
     92 		if ((f & (SUSED|SGLOBAL|SDECLARED)) == SDECLARED)
     93 			warn("'%s' defined but not used", name);
     94 		if ((f & SDEFINED) == 0 && sym->ns == NS_LABEL)
     95 			errorp("label '%s' is not defined", name);
     96 	}
     97 	free(name);
     98 	free(sym);
     99 }
    100 
    101 void
    102 popctx(void)
    103 {
    104 	Symbol *next, *sym;
    105 
    106 	if (--curctx == GLOBALCTX) {
    107 		for (sym = labels; sym; sym = next) {
    108 			next = sym->next;
    109 			killsym(sym);
    110 		}
    111 		labels = NULL;
    112 		if (curfun) {
    113 			free(curfun->u.pars);
    114 			curfun->u.pars = NULL;
    115 		}
    116 	}
    117 
    118 	for (sym = head; sym && sym->ctx > curctx; sym = next) {
    119 		next = sym->next;
    120 		killsym(sym);
    121 	}
    122 	head = sym;
    123 }
    124 
    125 static unsigned short
    126 newid(void)
    127 {
    128 	unsigned short id;
    129 
    130 	id = ++counterid;
    131 	if (id == 0) {
    132 		die("Overflow in %s identifiers",
    133 		    (curctx) ? "internal" : "external");
    134 	}
    135 	return id;
    136 }
    137 
    138 Type *
    139 duptype(Type *base)
    140 {
    141 	Type *tp = xmalloc(sizeof(*tp));
    142 
    143 	*tp = *base;
    144 	tp->id = newid();
    145 	return tp;
    146 }
    147 
    148 static Symbol *
    149 allocsym(int ns, char *name)
    150 {
    151 	Symbol *sym;
    152 
    153 	sym = xmalloc(sizeof(*sym));
    154 	if (name)
    155 		name = xstrdup(name);
    156 	sym->name = name;
    157 	sym->id = 0;
    158 	sym->ns = ns;
    159 	sym->ctx = (ns == NS_CPP) ? UCHAR_MAX : curctx;
    160 	sym->token = IDEN;
    161 	sym->flags = 0;
    162 	sym->u.s = NULL;
    163 	sym->type = NULL;
    164 	sym->next = sym->hash = NULL;
    165 	return sym;
    166 }
    167 
    168 static Symbol *
    169 linksym(Symbol *sym)
    170 {
    171 	Symbol *p, *prev;
    172 
    173 	switch (sym->ns) {
    174 	case NS_CPP:
    175 		return sym;
    176 	case NS_LABEL:
    177 		sym->next = labels;
    178 		return labels = sym;
    179 	default:
    180 		for (prev = p = head; p; prev = p, p = p->next) {
    181 			if (p->ctx <= sym->ctx)
    182 				break;
    183 		}
    184 		if (p == prev) {
    185 			sym->next = head;
    186 			head = sym;
    187 		} else {
    188 			p = prev->next;
    189 			prev->next = sym;
    190 			sym->next = p;
    191 		}
    192 		return sym;
    193 	}
    194 }
    195 
    196 static Symbol *
    197 linkhash(Symbol *sym)
    198 {
    199 	Symbol **h, *p, *prev;
    200 
    201 	h = &htab[hash(sym->name)];
    202 	for (prev = p = *h; p; prev = p, p = p->hash) {
    203 		if (p->ctx <= sym->ctx)
    204 			break;
    205 	}
    206 	if (p == prev) {
    207 		sym->hash = *h;
    208 		*h = sym;
    209 	} else {
    210 		p = prev->hash;
    211 		prev->hash = sym;
    212 		sym->hash = p;
    213 	}
    214 
    215 	if (sym->ns != NS_CPP)
    216 		sym->id = newid();
    217 	sym->flags |= SDECLARED;
    218 	return linksym(sym);
    219 }
    220 
    221 Symbol *
    222 newsym(int ns)
    223 {
    224 	return linksym(allocsym(ns, NULL));
    225 }
    226 
    227 Symbol *
    228 newstring(char *s, size_t len)
    229 {
    230 	Symbol *sym = newsym(NS_IDEN);
    231 
    232 	sym->id = newid();
    233 	sym->flags |= SSTRING | SCONSTANT | SPRIVATE;
    234 	sym->u.s = xmalloc(len);
    235 	if (s)
    236 		memcpy(sym->u.s, s, len);
    237 	sym->type = mktype(chartype, ARY, len, NULL);
    238 	return sym;
    239 }
    240 
    241 Symbol *
    242 newlabel(void)
    243 {
    244 	Symbol *sym = newsym(NS_LABEL);
    245 	sym->id = newid();
    246 	return sym;
    247 }
    248 
    249 Symbol *
    250 lookup(int ns, char *name)
    251 {
    252 	Symbol *sym;
    253 	int sns;
    254 	char *t, c;
    255 
    256 	c = *name;
    257 	for (sym = htab[hash(name)]; sym; sym = sym->hash) {
    258 		t = sym->name;
    259 		if (*t != c || strcmp(t, name))
    260 			continue;
    261 		sns = sym->ns;
    262 		/*
    263 		 * CPP namespace has a total priority over the another
    264 		 * namespaces, because it is a previous pass,
    265 		 * If we are looking in the CPP namespace,
    266 		 * we don't want symbols related to keywords or types.
    267 		 * When a lookup is done in a namespace associated
    268 		 * to a struct we also want symbols of NS_IDEN which
    269 		 * are typedef, because in other case we cannot declare
    270 		 * fields of such types.
    271 		 */
    272 		if (sns == NS_CPP && !disexpand || sns == ns)
    273 			return sym;
    274 		if (ns == NS_CPP)
    275 			continue;
    276 		if (sns == NS_KEYWORD ||
    277 		    (sym->flags & STYPEDEF) && ns >= NS_STRUCTS) {
    278 			return sym;
    279 		}
    280 	}
    281 	return allocsym(ns, name);
    282 }
    283 
    284 Symbol *
    285 nextsym(Symbol *sym, int ns)
    286 {
    287 	char *s, *t, c;
    288 	Symbol *p;
    289 
    290 	/*
    291 	 * This function is only called when a macro with parameters
    292 	 * is called without them.
    293 	 *      #define x(y) ((y) + 1)
    294 	 *      int x = x(y);
    295 	 */
    296 	s = sym->name;
    297 	c = *s;
    298 	for (p = sym->hash; p; p = p->hash) {
    299 		t = p->name;
    300 		if (c == *t && !strcmp(s, t))
    301 			return p;
    302 	}
    303 	return allocsym(ns, s);
    304 }
    305 
    306 Symbol *
    307 install(int ns, Symbol *sym)
    308 {
    309 	if (sym->flags & SDECLARED) {
    310 		if (sym->ctx == curctx && ns == sym->ns)
    311 			return NULL;
    312 		sym = allocsym(ns, sym->name);
    313 	}
    314 	return linkhash(sym);
    315 }
    316 
    317 void
    318 keywords(struct keyword *key, int ns)
    319 {
    320 	Symbol *sym;
    321 
    322 	for ( ; key->str; ++key) {
    323 		sym = linkhash(allocsym(ns, key->str));
    324 		sym->token = key->token;
    325 		sym->u.token = key->value;
    326 	}
    327 	/*
    328 	 * Remove all the predefined symbols from * the symbol list. It
    329 	 * will make faster some operations. There is no problem of memory
    330 	 * leakeage because this memory is not ever freed
    331 	 */
    332 	counterid = 0;
    333 	head = NULL;
    334 }