static void traitpickle(FILE *fd, Trait *tr) { size_t i; wrint(fd, tr->uid); wrbool(fd, tr->ishidden); pickle(fd, tr->name); typickle(fd, tr->param); wrint(fd, tr->nmemb); for (i = 0; i < tr->nmemb; i++) wrsym(fd, tr->memb[i]); wrint(fd, tr->nfuncs); for (i = 0; i < tr->nfuncs; i++) wrsym(fd, tr->funcs[i]); }
void rl(int fd) { Biobuf b; char *cp; struct ar_hdr a; long len; Binit(&b, fd, OWRITE); Bseek(&b,seek(fd,0,1), 0); len = symdefsize; if(len&01) len++; sprint(a.date, "%-12ld", time(0)); sprint(a.uid, "%-6d", 0); sprint(a.gid, "%-6d", 0); sprint(a.mode, "%-8o", 0644); sprint(a.size, "%-10ld", len); strncpy(a.fmag, ARFMAG, 2); strcpy(a.name, symdef); for (cp = strchr(a.name, 0); /* blank pad on right */ cp < a.name+sizeof(a.name); cp++) *cp = ' '; if(HEADER_IO(Bwrite, &b, a)) wrerr(); len += Boffset(&b); if (astart) { wrsym(&b, len, astart->sym); len += astart->size; } if(amiddle) { wrsym(&b, len, amiddle->sym); len += amiddle->size; } if(aend) wrsym(&b, len, aend->sym); if(symdefsize&0x01) Bputc(&b, 0); Bterm(&b); }
/* Outputs a symbol table to file in a way that can be * read back usefully. Only writes declarations, types * and sub-namespaces. Captured variables are ommitted. */ static void wrstab(FILE *fd, Stab *val) { size_t n, i; void **keys; wrstr(fd, val->name); /* write decls */ keys = htkeys(val->dcl, &n); wrint(fd, n); for (i = 0; i < n; i++) wrsym(fd, getdcl(val, keys[i])); free(keys); /* write types */ keys = htkeys(val->ty, &n); wrint(fd, n); for (i = 0; i < n; i++) { pickle(fd, keys[i]); /* name */ wrtype(fd, gettype(val, keys[i])); /* type */ } free(keys); }
/* Usefile format: * U<pkgname> * L<liblist> * I<initlist> * T<pickled-type> * D<picled-decl> * G<pickled-decl><pickled-initializer> * Z */ void writeuse(FILE *f, Node *file) { Stab *st; void **k; Node *s, *u; size_t i, n; assert(file->type == Nfile); st = file->file.globls; /* usefile name */ wrbyte(f, 'U'); wrint(f, Abiversion); /* use version */ if (st->name) wrstr(f, st->name); else wrstr(f, NULL); /* library deps */ for (i = 0; i < file->file.nuses; i++) { u = file->file.uses[i]; if (!u->use.islocal) { wrbyte(f, 'L'); wrstr(f, u->use.name); } } for (i = 0; i < file->file.nlibdeps; i++) { wrbyte(f, 'L'); wrstr(f, file->file.libdeps[i]); } for (i = 0; i < file->file.nextlibs; i++) { wrbyte(f, 'X'); wrstr(f, file->file.extlibs[i]); } /* source file name */ wrbyte(f, 'F'); wrstr(f, file->file.files[0]); for (i = 0; i < ntypes; i++) { if (types[i]->vis == Visexport || types[i]->vis == Vishidden) { wrbyte(f, 'T'); wrint(f, types[i]->tid); typickle(f, types[i]); } } for (i = 0; i < ntraittab; i++) { if (traittab[i]->vis == Visexport || traittab[i]->vis == Vishidden) { wrbyte(f, 'R'); traitpickle(f, traittab[i]); } } k = htkeys(st->impl, &n); for (i = 0; i < n; i++) { /* merging during inference should remove all protos */ s = getimpl(st, k[i]); assert(!s->impl.isproto); if (s->impl.vis == Visexport || s->impl.vis == Vishidden) { wrbyte(f, 'I'); pickle(f, s); } } free(k); k = htkeys(st->dcl, &n); for (i = 0; i < n; i++) { s = getdcl(st, k[i]); assert(s != NULL); if (s->decl.vis == Visintern || s->decl.vis == Visbuiltin) continue; /* trait functions get written out with their traits */ if (s->decl.trait || s->decl.isinit) continue; else if (s->decl.isgeneric) wrbyte(f, 'G'); else wrbyte(f, 'D'); wrsym(f, s); } for (i = 0; i < file->file.ninit; i++) { wrbyte(f, 'S'); pickle(f, file->file.init[i]); } if (file->file.localinit) { wrbyte(f, 'S'); pickle(f, file->file.localinit->decl.name); } free(k); }
/* Pickles a node to a file. The format * is more or less equivalen to to * simplest serialization of the * in-memory representation. Minimal * checking is done, so a bad type can * crash the compiler */ static void pickle(FILE *fd, Node *n) { size_t i; if (!n) { wrbyte(fd, Nnone); return; } wrbyte(fd, n->type); wrint(fd, n->loc.line); switch (n->type) { case Nfile: wrstr(fd, n->file.files[0]); wrint(fd, n->file.nuses); for (i = 0; i < n->file.nuses; i++) pickle(fd, n->file.uses[i]); wrint(fd, n->file.nstmts); for (i = 0; i < n->file.nstmts; i++) pickle(fd, n->file.stmts[i]); wrstab(fd, n->file.globls); break; case Nexpr: wrbyte(fd, n->expr.op); wrtype(fd, n->expr.type); wrbool(fd, n->expr.isconst); pickle(fd, n->expr.idx); wrint(fd, n->expr.nargs); for (i = 0; i < n->expr.nargs; i++) pickle(fd, n->expr.args[i]); break; case Nname: wrbool(fd, n->name.ns != NULL); if (n->name.ns) { wrstr(fd, n->name.ns); } wrstr(fd, n->name.name); break; case Nuse: wrbool(fd, n->use.islocal); wrstr(fd, n->use.name); break; case Nlit: wrbyte(fd, n->lit.littype); wrtype(fd, n->lit.type); wrint(fd, n->lit.nelt); switch (n->lit.littype) { case Lchr: wrint(fd, n->lit.chrval); break; case Lint: wrint(fd, n->lit.intval); break; case Lflt: wrflt(fd, n->lit.fltval); break; case Lstr: wrlenstr(fd, n->lit.strval); break; case Llbl: wrstr(fd, n->lit.lblval); break; case Lbool: wrbool(fd, n->lit.boolval); break; case Lfunc: pickle(fd, n->lit.fnval); break; } break; case Nloopstmt: pickle(fd, n->loopstmt.init); pickle(fd, n->loopstmt.cond); pickle(fd, n->loopstmt.step); pickle(fd, n->loopstmt.body); break; case Niterstmt: pickle(fd, n->iterstmt.elt); pickle(fd, n->iterstmt.seq); pickle(fd, n->iterstmt.body); break; case Nmatchstmt: pickle(fd, n->matchstmt.val); wrint(fd, n->matchstmt.nmatches); for (i = 0; i < n->matchstmt.nmatches; i++) pickle(fd, n->matchstmt.matches[i]); break; case Nmatch: pickle(fd, n->match.pat); pickle(fd, n->match.block); break; case Nifstmt: pickle(fd, n->ifstmt.cond); pickle(fd, n->ifstmt.iftrue); pickle(fd, n->ifstmt.iffalse); break; case Nblock: wrstab(fd, n->block.scope); wrint(fd, n->block.nstmts); for (i = 0; i < n->block.nstmts; i++) pickle(fd, n->block.stmts[i]); break; case Ndecl: /* sym */ pickle(fd, n->decl.name); wrtype(fd, n->decl.type); /* symflags */ wrbool(fd, n->decl.isconst); wrbool(fd, n->decl.isgeneric); wrbool(fd, n->decl.isextern); wrbool(fd, n->decl.isnoret); wrbool(fd, n->decl.ispkglocal); /* init */ pickle(fd, n->decl.init); break; case Nfunc: wrtype(fd, n->func.type); wrstab(fd, n->func.scope); wrint(fd, n->func.nargs); for (i = 0; i < n->func.nargs; i++) pickle(fd, n->func.args[i]); pickle(fd, n->func.body); break; case Nimpl: pickle(fd, n->impl.traitname); wrint(fd, n->impl.trait->uid); wrtype(fd, n->impl.type); wrint(fd, n->impl.ndecls); for (i = 0; i < n->impl.ndecls; i++) wrsym(fd, n->impl.decls[i]); break; case Nnone: die("Nnone should not be seen as node type!"); break; } }