dsk_err_t w32serial_call(DSK_PDRIVER pDriver, unsigned char *input, int inp_len, unsigned char *output, int *out_len) { word16 wire_len; word16 crc; byte var; byte wvar[2]; int n; dsk_err_t err; unsigned char *tmpbuf; W32SERIAL_REMOTE_DATA *self = (W32SERIAL_REMOTE_DATA *)pDriver->dr_remote; if (!self || self->super.rd_class != &rpc_w32serial) return DSK_ERR_BADPTR; /* CRC tbe input... */ wire_len = inp_len; CRC_Clear(); for (n = 0; n < inp_len; n++) CRC_Update(input[n]); crc = CRC_Done(); /* printf("rpc_w32serial: Input packet: "); for (n = 0; n < inp_len; n++) printf("%02x ", input[n]); printf("\n"); */ while (1) { /* Write SOH (start of request) */ err = wrbyte(self, SOH); if (err) return err; /* Write packet length (network byte order) */ wvar[0] = wire_len >> 8; wvar[1] = wire_len & 0xFF; err = write_bytes(self, 2, wvar); if (err) return err; err = write_bytes(self, inp_len, input); if (err) return err; wvar[0] = crc >> 8; wvar[1] = crc & 0xFF; err = write_bytes(self, 2, wvar); if (err) return err; /* err = read_bytes(self, 1, &var); if (err) return err; */ /* Wait 'til we get an ACK or a NAK. */ do { err = read_bytes(self, 1, &var); if (err) return err; } while(var != ACK && var != NAK); if (var == ACK) break; if (var == NAK) continue; } /* Outgoing packet sent. Await response */ while (1) { /* First byte of response must be STX. */ err = read_bytes(self, 1, &var); if (err) return err; if (var != STX) continue; err = read_bytes(self, 2, wvar); if (err) return err; wire_len = wvar[0]; wire_len = (wire_len << 8) | wvar[1]; tmpbuf = dsk_malloc(wire_len + 2); if (!tmpbuf) return DSK_ERR_NOMEM; CRC_Clear(); err = read_bytes(self, wire_len + 2, tmpbuf); if (err) { dsk_free(tmpbuf); return err; } for (n = 0; n < wire_len; n++) { CRC_Update(tmpbuf[n]); } crc = tmpbuf[wire_len]; crc = (crc << 8) | tmpbuf[wire_len + 1]; /* If CRC matches, send ACK and return. Else send NAK. */ if (crc == CRC_Done()) { /* printf("rpc_w32serial: Result packet: "); for (n = 0; n < wire_len; n++) printf("%02x ", tmpbuf[n]); printf("\n"); */ err = wrbyte(self, ACK); if (err) { dsk_free(tmpbuf); return err; } /* Copy packet to waiting output buffer */ if (wire_len < *out_len) *out_len = wire_len; memcpy(output, tmpbuf, *out_len); dsk_free(tmpbuf); return DSK_ERR_OK; } /* Packet was garbled. NAK it and try again. */ dsk_free(tmpbuf); err = wrbyte(self, NAK); if (err) return err; } /* Should never happen */ return DSK_ERR_NOTIMPL; }
/* 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); }
/* Writes types to a file. Errors on * internal only types like Tyvar that * will not be meaningful in another file*/ static void typickle(FILE *fd, Type *ty) { size_t i; if (!ty) { die("trying to pickle null type\n"); return; } wrbyte(fd, ty->type); wrbyte(fd, ty->vis); /* tid is generated; don't write */ /* FIXME: since we only support hardcoded traits, we just write * out the set of them. we should write out the trait list as * well */ if (!ty->traits) { wrint(fd, 0); } else { wrint(fd, bscount(ty->traits)); for (i = 0; bsiter(ty->traits, &i); i++) { if (i < Ntraits) wrint(fd, i | Builtinmask); else wrint(fd, i); } } wrint(fd, ty->nsub); switch (ty->type) { case Tyunres: pickle(fd, ty->name); break; case Typaram: wrstr(fd, ty->pname); break; case Tystruct: wrint(fd, ty->nmemb); for (i = 0; i < ty->nmemb; i++) pickle(fd, ty->sdecls[i]); break; case Tyunion: wrint(fd, ty->nmemb); for (i = 0; i < ty->nmemb; i++) wrucon(fd, ty->udecls[i]); break; case Tyarray: wrtype(fd, ty->sub[0]); pickle(fd, ty->asize); break; case Tyslice: wrtype(fd, ty->sub[0]); break; case Tyvar: die("Attempting to pickle %s. This will not work.\n", tystr(ty)); break; case Tyname: pickle(fd, ty->name); wrbool(fd, ty->issynth); wrint(fd, ty->narg); for (i = 0; i < ty->narg; i++) wrtype(fd, ty->arg[i]); wrtype(fd, ty->sub[0]); break; case Tygeneric: pickle(fd, ty->name); wrbool(fd, ty->issynth); wrint(fd, ty->ngparam); for (i = 0; i < ty->ngparam; i++) wrtype(fd, ty->gparam[i]); wrtype(fd, ty->sub[0]); break; default: for (i = 0; i < ty->nsub; i++) wrtype(fd, ty->sub[i]); break; } }
/* 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; } }
static dsk_err_t unsqueeze(SQ_COMPRESS_DATA *self) { dsk_err_t err; unsigned short magic, checksum; unsigned char c; unsigned short dictlen; unsigned short nd; unsigned short node; signed short code; self->ck_sum = 0; err = readu(self, &magic); if (err) return err; if (magic != MAGIC) return DSK_ERR_COMPRESS; err = readu(self, &checksum); /* Filename (skip) */ do { err = readc(self, &c); if (err) return err; } while (c); /* Dictionary length */ err = readu(self, &dictlen); if (err) return err; if (dictlen > MAXNODE) return DSK_ERR_COMPRESS; /* Dictionary */ for (nd = 0; nd < dictlen; nd++) { err = reads(self, &self->huf_node[nd].left); if (err) return err; err = reads(self, &self->huf_node[nd].right); if (err) return err; } /* Now start decoding data */ self->huf_out = 0; self->huf_nout = 8; node = 0; rle_reset(self); /* if dictlen == 0, the file is empty */ if (dictlen) while (1) { if (self->huf_nout == 8) { self->huf_nout = 0; err = readc(self, &self->huf_out); if (err) return err; } code = self->huf_out & st_masks[self->huf_nout]; ++self->huf_nout; if (code) code = self->huf_node[node].right; else code = self->huf_node[node].left; if (code < 0) { if (-1 - code == SQ_EOF) break; /* Reached EOF */ err = wrbyte(self, (unsigned char)(-1 - code)); if (err) return err; node = 0; } else node = code; } if (self->rle_char != -1) { err = ckputc(self, (unsigned char)(self->rle_char)); if (err) return err; } if (checksum != self->ck_sum) return DSK_ERR_COMPRESS; return DSK_ERR_OK; }