static Node * decl() { Node *n, *init; char *name; CTy *type, *basety; SrcPos *pos; Sym *sym; Vec *syms; int sclass; pos = &tok->pos; syms = vec(); basety = declspecs(&sclass); while(tok->k != ';' && tok->k != TOKEOF) { type = declarator(basety, &name, &init); switch(sclass){ case SCNONE: if(isglobal()) { sclass = SCGLOBAL; } else { sclass = SCAUTO; } break; case SCTYPEDEF: if(init) errorposf(pos, "typedef cannot have an initializer"); break; } if(!name) errorposf(pos, "decl needs to specify a name"); sym = definesym(pos, sclass, name, type, init); vecappend(syms, sym); if(isglobal() && tok->k == '{') { if(init) errorposf(pos, "function declaration has an initializer"); if(type->t != CFUNC) errorposf(pos, "expected a function"); curfunc = mknode(NFUNC, pos); curfunc->type = type; curfunc->Func.name = name; curfunc->Func.params = vec(); curfunc->Func.stkslots = vec(); fbody(); definesym(pos, sclass, name, type, curfunc); curfunc = 0; goto done; } if(tok->k == ',') next(); else break; } expect(';'); done: n = mknode(NDECL, pos); n->Decl.syms = syms; return n; }
static void r_symbol(SCTX_ unsigned mode, struct token *pos, struct symbol *sym) { char b[512]; if ((!sym->ctype.base_type || sym->ctype.base_type->type != SYM_FN) && !isglobal(sctx_ sym)) return; print_usage(sctx_ pos, sym, mode); if (!sym->ident) sym->ident = MK_IDENT("__asm__"); memcpy(b, sym->ident->name, sym->ident->len); b[sym->ident->len] = 0; if (isfunc(sctx_ sym)) strcat(b, "()"); printf("%s%-32.*s %s 0x%x 0x%p %s\n", sctxp reporter->indent ? "\t" : "", (int)strlen(b), b, show_typename(sctx_ sym->ctype.base_type), (unsigned int )sym->ctype.modifiers, sym, symbol_type_name(sym->type)); }
static Sym * definesym(SrcPos *p, int sclass, char *name, CTy *type, Node *n) { Sym *sym; if(sclass == SCAUTO || n != 0) if(type->incomplete) errorposf(p, "cannot use incomplete type in this context"); if(sclass == SCAUTO && isglobal()) errorposf(p, "defining local symbol in global scope"); sym = mapget(syms[nscopes - 1], name); if(sym) { switch(sym->k) { case SYMTYPE: if(sclass != SCTYPEDEF || !sametype(sym->type, type)) errorposf(p, "incompatible redefinition of typedef %s", name); break; case SYMGLOBAL: if(sym->Global.sclass != sclass) errorposf(p, "redefinition of %s with differing storage class", name); if(sym->init && n) errorposf(p, "%s already initialized", name); if(!sym->init && n) { sym->init = n; emitsym(sym); removetentativesym(sym); } break; default: errorposf(p, "redefinition of %s", name); } return sym; } sym = gcmalloc(sizeof(Sym)); sym->name = name; sym->type = type; sym->init = n; switch(sclass) { case SCAUTO: sym->k = SYMLOCAL; sym->Local.slot = gcmalloc(sizeof(StkSlot)); sym->Local.slot->size = sym->type->size; sym->Local.slot->align = sym->type->align; vecappend(curfunc->Func.stkslots, sym->Local.slot); break; case SCTYPEDEF: sym->k = SYMTYPE; break; case SCGLOBAL: sym->k = SYMGLOBAL; sym->Global.label = name; sym->Global.sclass = SCGLOBAL; break; case SCSTATIC: sym->k = SYMGLOBAL; sym->Global.label = newlabel(); sym->Global.sclass = SCSTATIC; break; } if(sym->k == SYMGLOBAL) { if(sym->init) emitsym(sym); else if(!isfunc(sym->type)) addtentativesym(sym); } if(!define(syms, name, sym)) panic("internal error"); return sym; }
/* * Search for variable, if not found create globally. */ struct tbl * global(const char *n) { return (isglobal(n, true)); }