int main(int argc, char *argv[]) { int i; Vec *includedirs; char *cfile; cfile = 0; includedirs = vec(); for(i = 1; i < argc; i++) { if(strcmp(argv[i], "-I") == 0) { i++; if(i >= argc) errorf("-I requires an include path\n"); vecappend(includedirs, argv[i]); } else if(strncmp(argv[i], "-I", 2) == 0) { vecappend(includedirs, argv[i]+2); } else { if(argv[i][0] == '-') errorf("unknown flag %s\n", argv[i]); if(cfile) errorf("please specify a single c file\n"); cfile = argv[i]; } } if(!cfile) usage(); cppinit(cfile, includedirs); emitinit(stdout); parse(); emitend(); return 0; }
static Val * randstruct(int depth) { Val *r, *p; int i, n; char buff[1024]; r = gcmalloc(sizeof(Val)); r->t = STRUCT; r->Cstruct.members = vec(); n = rand() % MAXSTRUCTM; for(i = 0; i < n; i++) vecappend(r->Cstruct.members, randval(depth + 1)); snprintf(buff, sizeof buff, "s%d", structcount++); r->Cstruct.name = gcstrdup(buff); printf("struct %s {\n", r->Cstruct.name); for(i = 0; i < r->Cstruct.members->len; i++) { p = vecget(r->Cstruct.members, i); printf("\t"); printvaltype(p); printf(" m%d;\n", i); } printf("};\n"); return r; }
static void fbody(void) { Node *gotofixup; int i; char *l; NameTy *nt; Sym *sym; pushscope(); labels = map(); gotos = vec(); for(i = 0; i < curfunc->type->Func.params->len; i++) { nt = vecget(curfunc->type->Func.params, i); if(nt->name) { sym = definesym(&curfunc->pos, SCAUTO, nt->name, nt->type, 0); vecappend(curfunc->Func.params, sym); } } curfunc->Func.body = block(); popscope(); for(i = 0 ; i < gotos->len ; i++) { gotofixup = vecget(gotos, i); l = mapget(labels, gotofixup->Goto.name); if(!l) errorposf(&gotofixup->pos, "goto target does not exist"); gotofixup->Goto.l = l; } }
static void params(CTy *fty) { int sclass; CTy *t; char *name; SrcPos *pos; fty->Func.isvararg = 0; if(tok->k == ')') return; for(;;) { pos = &tok->pos; t = declspecs(&sclass); t = declarator(t, &name, 0); if(sclass != SCNONE) errorposf(pos, "storage class not allowed in parameter decl"); vecappend(fty->Func.params, newnamety(name, t)); if(tok->k != ',') break; next(); } if(tok->k == TOKELLIPSIS) { fty->Func.isvararg = 1; next(); } }
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; }
void penddata(char *label, CTy *ty, Node *init, int isglobal) { Data *d; d = xmalloc(sizeof(Data)); d->label = label; d->type = ty; d->init = init; d->isglobal = isglobal; vecappend(pendingdata, d); }
static void addtentativesym(Sym *sym) { int i; Sym *s; for(i = 0; i < tentativesyms->len; i++) { s = vecget(tentativesyms, i); if(s == sym) return; } vecappend(tentativesyms, sym); }
static Testcase * randtestcase() { Testcase *t; int n, i; t = gcmalloc(sizeof(Testcase)); t->vals = vec(); t->ret = randval(0); n = rand() % MAXPARAMS; for(i = 0; i < n; i++) vecappend(t->vals, randval(0)); return t; }
/* TODO: proper efficient set for tentative syms */ static void removetentativesym(Sym *sym) { int i; Vec *newv; Sym *s; newv = vec(); for(i = 0; i < tentativesyms->len; i++) { s = vecget(tentativesyms, i); if(s == sym) continue; vecappend(newv, s); } tentativesyms = newv; }
void addstructmember(SrcPos *pos, CTy *t, char *name, CTy *membt) { StructMember *sm, *subsm; int i, align, sz; sm = gcmalloc(sizeof(StructMember)); sm->name = name; sm->type = membt; if(!isstruct(t)) panic("internal error"); if(sm->name == 0 && isstruct(sm->type)) { for(i = 0; i < sm->type->Struct.members->len; i++) { subsm = vecget(sm->type->Struct.members, i); addstructmember(pos, t, subsm->name, subsm->type); } return; } if(sm->name) { for(i = 0; i < t->Struct.members->len; i++) { subsm = vecget(t->Struct.members, i); if(subsm->name) if(strcmp(sm->name, subsm->name) == 0) errorposf(pos ,"struct already has a member named %s", sm->name); } } if(membt->align < t->align) t->align = membt->align; sz = t->size; align = membt->align; if(sz % align) sz = sz + align - (sz % align); sm->offset = sz; sz += sm->type->size; t->size = sz; vecappend(t->Struct.members, sm); }
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; }