symbol.c (6803B)
1 static char sccsid[] = "@(#) ./cc1/symbol.c"; 2 #include <assert.h> 3 #include <limits.h> 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <string.h> 7 8 #include <cstd.h> 9 #include "../inc/scc.h" 10 #include "cc1.h" 11 12 #define NR_SYM_HASH 64 13 #define NR_CPP_HASH 32 14 #define NR_LBL_HASH 16 15 16 unsigned curctx; 17 static unsigned short counterid; 18 19 static Symbol *head, *labels; 20 static Symbol *htab[NR_SYM_HASH]; 21 static Symbol *htabcpp[NR_CPP_HASH]; 22 static Symbol *htablbl[NR_LBL_HASH]; 23 24 #ifndef NDEBUG 25 void 26 dumpstab(Symbol **tbl, char *msg) 27 { 28 Symbol **bp, *sym; 29 unsigned size; 30 31 fprintf(stderr, "Symbol Table dump at ctx=%u\n%s\n", curctx, msg); 32 if (tbl == htab) 33 size = NR_SYM_HASH; 34 else if (tbl == htabcpp) 35 size = NR_CPP_HASH; 36 else if (tbl == htablbl) 37 size = NR_LBL_HASH; 38 else 39 abort(); 40 41 for (bp = tbl; bp < &tbl[size]; ++bp) { 42 if (*bp == NULL) 43 continue; 44 fprintf(stderr, "%d", (int) (bp - htab)); 45 for (sym = *bp; sym; sym = sym->hash) 46 fprintf(stderr, "->[%d,%d:'%s'=%p]", 47 sym->ns, sym->ctx, sym->name, (void *) sym); 48 putc('\n', stderr); 49 } 50 fputs("head:", stderr); 51 for (sym = head; sym; sym = sym->next) { 52 fprintf(stderr, "->[%d,%d:'%s'=%p]", 53 sym->ns, sym->ctx, 54 (sym->name) ? sym->name : "", (void *) sym); 55 } 56 fputs("\nlabels:", stderr); 57 for (sym = labels; sym; sym = sym->next) { 58 fprintf(stderr, "->[%d,%d:'%s'=%p]", 59 sym->ns, sym->ctx, 60 (sym->name) ? sym->name : "", (void *) sym); 61 } 62 putc('\n', stderr); 63 } 64 #endif 65 66 static Symbol ** 67 hash(char *s, int ns) 68 { 69 unsigned c, h, size; 70 Symbol **tab; 71 72 for (h = 0; c = *s; ++s) 73 h = h*33 ^ c; 74 75 switch (ns) { 76 case NS_CPP: 77 tab = htabcpp; 78 size = NR_CPP_HASH-1; 79 break; 80 case NS_LABEL: 81 tab = htablbl; 82 size = NR_LBL_HASH-1; 83 break; 84 default: 85 tab = htab; 86 size = NR_SYM_HASH-1; 87 break; 88 } 89 return &tab[h & size]; 90 } 91 92 static void 93 unlinkhash(Symbol *sym) 94 { 95 Symbol **h; 96 97 if ((sym->flags & SDECLARED) == 0) 98 return; 99 h = hash(sym->name, sym->ns); 100 assert(sym->ns == NS_CPP || *h == sym); 101 while (*h != sym) 102 h = &(*h)->hash; 103 *h = sym->hash; 104 } 105 106 void 107 pushctx(void) 108 { 109 DBG("SYM: pushed context %d", curctx+1); 110 if (++curctx == NR_BLOCK+1) 111 error("too many nested blocks"); 112 } 113 114 void 115 killsym(Symbol *sym) 116 { 117 short f; 118 char *name; 119 120 if (!sym) 121 return; 122 f = sym->flags; 123 if (f & SSTRING) 124 free(sym->u.s); 125 if (sym->ns == NS_TAG) 126 sym->type->prop &= ~TDEFINED; 127 unlinkhash(sym); 128 if ((name = sym->name) != NULL) { 129 switch (sym->ns) { 130 case NS_LABEL: 131 if ((f & SDEFINED) == 0) 132 errorp("label '%s' is not defined", name); 133 case NS_IDEN: 134 if ((f & (SUSED|SGLOBAL|SDECLARED)) == SDECLARED) 135 warn("'%s' defined but not used", name); 136 break; 137 } 138 } 139 free(name); 140 free(sym); 141 } 142 143 void 144 popctx(void) 145 { 146 Symbol *next, *sym; 147 int ns, dangling = 0; 148 149 DBG("SYM: poped context %d", curctx); 150 /* 151 * we have to be careful before popping the current 152 * context, because since the parser is one token 153 * ahead it may already have read an identifier at 154 * this point, and yylval.sym is a pointer to 155 * the symbol associated to such token. If that 156 * symbol is from the context that we are popping 157 * then we are going to generate a dangling pointer. 158 * We can detect this situation and call again to 159 * lookup. 160 */ 161 if ((yytoken == IDEN || yytoken == TYPEIDEN) && 162 yylval.sym->ctx == curctx) { 163 ns = yylval.sym->ns; 164 dangling = 1; 165 } 166 167 for (sym = head; sym && sym->ctx == curctx; sym = next) { 168 /* 169 * Since we are unlinking them in the inverse order 170 * we do know that sym is always the head of the 171 * collision list 172 */ 173 next = sym->next; 174 killsym(sym); 175 } 176 head = sym; 177 178 if (--curctx == GLOBALCTX) { 179 for (sym = labels; sym; sym = next) { 180 next = sym->next; 181 killsym(sym); 182 } 183 labels = NULL; 184 } 185 186 if (dangling) { 187 yylval.sym = lookup(ns, yytext, ALLOC); 188 yytoken = yylval.sym->token; 189 } 190 } 191 192 unsigned 193 newid(void) 194 { 195 unsigned short id; 196 197 if (lexmode == CPPMODE) 198 return 0; 199 id = ++counterid; 200 if (id == 0) { 201 die("Overflow in %s identifiers", 202 (curctx) ? "internal" : "external"); 203 } 204 return id; 205 } 206 207 Symbol * 208 newsym(int ns, char *name) 209 { 210 Symbol *sym; 211 212 sym = xmalloc(sizeof(*sym)); 213 if (name) 214 name = xstrdup(name); 215 sym->name = name; 216 sym->id = 0; 217 sym->hide = 0; 218 sym->ns = ns; 219 sym->ctx = curctx; 220 sym->token = IDEN; 221 sym->flags = 0; 222 sym->u.s = NULL; 223 sym->type = NULL; 224 sym->hash = NULL; 225 226 if (ns == NS_LABEL) { 227 sym->next = labels; 228 labels = sym; 229 } else if (ns != NS_CPP) { 230 sym->next = head; 231 head = sym; 232 } 233 return sym; 234 } 235 236 static Symbol * 237 linkhash(Symbol *sym) 238 { 239 Symbol **h; 240 241 h = hash(sym->name, sym->ns); 242 sym->hash = *h; 243 *h = sym; 244 245 if (sym->ns != NS_CPP) 246 sym->id = newid(); 247 sym->flags |= SDECLARED; 248 return sym; 249 } 250 251 Symbol * 252 newstring(char *s, size_t len) 253 { 254 Symbol *sym = newsym(NS_IDEN, NULL); 255 256 if (lexmode != CPPMODE) 257 sym->type = mktype(chartype, ARY, len, NULL); 258 sym->id = newid(); 259 sym->flags |= SSTRING | SCONSTANT | SPRIVATE; 260 sym->u.s = xmalloc(len); 261 if (s) 262 memcpy(sym->u.s, s, len); 263 264 return sym; 265 } 266 267 Symbol * 268 newlabel(void) 269 { 270 Symbol *sym = newsym(NS_LABEL, NULL); 271 sym->id = newid(); 272 return sym; 273 } 274 275 Symbol * 276 lookup(int ns, char *name, int alloc) 277 { 278 Symbol *sym; 279 int sns, c; 280 char *t; 281 282 c = *name; 283 for (sym = *hash(name, ns); sym; sym = sym->hash) { 284 t = sym->name; 285 if (*t != c || strcmp(t, name)) 286 continue; 287 sns = sym->ns; 288 if (sns == ns) 289 return sym; 290 /* 291 * When a lookup is done in a namespace associated 292 * to a struct we also want symbols of NS_IDEN which 293 * are typedef, because in other case we cannot declare 294 * fields of such types. 295 * TODO: Remove this trick 296 */ 297 if (sns == NS_KEYWORD || 298 (sym->flags & STYPEDEF) && ns >= NS_STRUCTS) { 299 return sym; 300 } 301 } 302 return (alloc == ALLOC) ? newsym(ns, name) : NULL; 303 } 304 305 Symbol * 306 install(int ns, Symbol *sym) 307 { 308 if (sym->flags & SDECLARED || sym->ctx != curctx) { 309 if (sym->ctx == curctx && ns == sym->ns) 310 return NULL; 311 sym = newsym(ns, sym->name); 312 } 313 return linkhash(sym); 314 } 315 316 void 317 keywords(struct keyword *key, int ns) 318 { 319 Symbol *sym; 320 321 for ( ; key->str; ++key) { 322 sym = linkhash(newsym(ns, key->str)); 323 sym->token = key->token; 324 sym->u.token = key->value; 325 } 326 /* 327 * Remove all the predefined symbols from * the symbol list. It 328 * will make faster some operations. There is no problem of memory 329 * leakeage because this memory is not ever freed 330 */ 331 counterid = 0; 332 head = NULL; 333 } 334 335 void 336 builtins(struct builtin *built) 337 { 338 Symbol *sym; 339 struct builtin *bp; 340 341 for (bp = built; bp->str; ++bp) { 342 sym = linkhash(newsym(NS_KEYWORD, bp->str)); 343 sym->token = BUILTIN; 344 sym->u.fun = bp->fun; 345 } 346 /* 347 * Remove all the predefined symbols from * the symbol list. It 348 * will make faster some operations. There is no problem of memory 349 * leakeage because this memory is not ever freed 350 */ 351 counterid = 0; 352 head = NULL; 353 }