int vm(Pu *L) { int ret = 0; for (;;) { PuType tp = TOKEN.type; if (tp == FINISH) { ret = 0; break; } if (L->isyield) { ret = -2; break; } if (L->isquit) { ret = -1; break; } switch (tp) { case WHILE: whilet(L, &TOKEN); break; case IF: ift(L, &TOKEN); break; case OP: procop(L); break; case GOTO: gotot(L); break; case FUNCTION: regfunc(L); break; case RETURN:{ NEXT_TOKEN; L->isreturn = true; const __pu_value *expresult = exp(L); if (!expresult || expresult->type() == UNKNOWN) { QUIT_SCRIPT; break; } L->return_value = *expresult; ret = 1; goto END_VM;} case INCLUDE: NEXT_TOKEN; NEXT_TOKEN; break; case ELSE: case ELIF: case BREAK: case CONTINUE: case END: ret = 1; goto END_VM; default: exp(L); break; } } END_VM: DO_GC; return ret; }
/* process changes to resource file (or just list it) */ static opdef *rscproc(osfildef *fp, osfildef *fpout, opdef *oplist) { char buf[128]; ulong siz; char datebuf[27]; ulong endpos; uchar nambuf[40]; uint rsiz; opdef *op; int copyrsc; ulong startpos; uint endpos_ofs; ulong first_xfcn = 0; ulong extcnt_pos = 0; int found_user_rsc = FALSE; int showed_heading = FALSE; int found_htmlres = FALSE; char *file_type; /* * if we're reading an existing file, check it header; otherwise, * write out a brand new file header */ if (fp != 0) { /* * the input file exists -- check file and version headers, and * get flags and timestamp */ if (osfrb(fp, buf, (int)(sizeof(FIOFILHDR) + sizeof(FIOVSNHDR) + 2))) listexit(fp, "error reading file header"); /* check the file type */ if (memcmp(buf, FIOFILHDR, sizeof(FIOFILHDR)) == 0) file_type = "game"; else if (memcmp(buf, FIOFILHDRRSC, sizeof(FIOFILHDRRSC)) == 0) file_type = "resource"; else listexit(fp, "invalid resource file header"); /* check the version header */ if (memcmp(buf + sizeof(FIOFILHDR), FIOVSNHDR, sizeof(FIOVSNHDR)) && memcmp(buf + sizeof(FIOFILHDR), FIOVSNHDR2, sizeof(FIOVSNHDR2)) && memcmp(buf + sizeof(FIOFILHDR), FIOVSNHDR3, sizeof(FIOVSNHDR3))) listexit(fp, "incompatible resource file version"); /* get the timestamp */ if (osfrb(fp, datebuf, (size_t)26)) listexit(fp, "error reading file"); datebuf[26] = '\0'; } else { struct tm *tblock; time_t timer; /* construct a new file header */ memcpy(buf, FIOFILHDRRSC, sizeof(FIOFILHDRRSC)); memcpy(buf + sizeof(FIOFILHDR), FIOVSNHDR, sizeof(FIOVSNHDR)); /* clear the flags */ oswp2(buf + sizeof(FIOFILHDR) + sizeof(FIOVSNHDR), 0); /* construct the timestamp */ timer = time(0); tblock = localtime(&timer); strcpy(datebuf, asctime(tblock)); } if (fpout) { if (osfwb(fpout, buf, (int)(sizeof(FIOFILHDR) + sizeof(FIOVSNHDR) + 2)) || osfwb(fpout, datebuf, (size_t)26)) listexit(fp, "error writing header"); } /* if listing, show file creation timestamp */ if (fpout == 0) rscptf("\n" "File type: TADS %s file\n" "Date compiled: %s\n", file_type, datebuf); /* * Process the input file, if there is one */ for ( ; fp != 0 ; ) { /* assume this resource will be copied to the output */ copyrsc = TRUE; startpos = osfpos(fp); if (osfrb(fp, buf, 1) || osfrb(fp, buf + 1, (int)(buf[0] + 4))) listexit(fp, "error reading file"); memcpy(nambuf, buf + 1, (size_t)buf[0]); nambuf[buf[0]] = '\0'; endpos_ofs = 1 + buf[0]; endpos = osrp4(buf + endpos_ofs); siz = endpos - startpos; /* see what kind of resource we have, and do the right thing */ if (!strcmp((char *)nambuf, "$EOF")) { /* end of file marker - quit here */ break; } else if (!strcmp((char *)nambuf, "HTMLRES")) { /* if we've already found an HTMLRES list, it's an error */ if (found_htmlres) { rscptf("error: multiple HTMLRES maps found in file\n" " -- redundant entries have been deleted.\n"); copyrsc = FALSE; } else { /* go process it */ oplist = prochtmlres(fp, fpout, oplist, ©rsc, &showed_heading, TRUE); } /* note that we've found a resource */ found_user_rsc = TRUE; found_htmlres = TRUE; } else if (!strcmp((char *)nambuf, "EXTCNT")) { /* place to write start of XFCN's? */ if (siz >= 17 && fpout) extcnt_pos = osfpos(fpout); } else if (!strcmp((char *)nambuf, "XFCN")) { if (osfrb(fp, buf, 3) || osfrb(fp, buf + 3, (int)buf[2])) listexit(fp, "error reading file"); rsiz = osrp2(buf); buf[3 + buf[2]] = '\0'; if (fpout) { /* see if this resource is in the list */ for (op = oplist ; op ; op = op->opnxt) { if (!(op->opflag & OPFDONE) && op->oprestype == RESTYPE_XFCN && !stricmp((char *)buf + 3, op->opres)) { /* note that this resource has now been processed */ op->opflag |= OPFDONE; /* * if it's already here, and we're not deleting * it, warn that the old one will stay around */ if (!(op->opflag & OPFDEL)) { /* warn that we're going to ignore it */ rscptf("warning: XFCN resource \"%s\" already in " "file\n -- the old resource will be kept " "(use -replace to replace it)\n", op->opres); /* don't add it */ op->opflag &= ~OPFADD; } else { /* * we're deleting this resource; if adding * it back in (i.e., replacing it), process * the add operation now */ if (op->opflag & OPFADD) { /* show what we're doing */ show_op("replacing", op->opres, strlen(op->opres), op->oprestype); /* * add the external file, replacing the * one in the input file */ procop(fpout, op, &first_xfcn); } else { /* note that we're deleting it */ show_op("deleting", op->opres, strlen(op->opres), op->oprestype); } /* don't copy the one out of the file */ copyrsc = FALSE; } break; } } } else { /* no output file - just list the resource */ show_list_item(&showed_heading, "XFCN", (ulong)rsiz, buf + 3, (size_t)buf[2]); } /* note that we've found a user resource */ found_user_rsc = TRUE; } if (fpout != 0 && copyrsc) { osfseek(fp, startpos, OSFSK_SET); copyres(fp, fpout, siz, endpos_ofs); } /* skip to the next resource */ osfseek(fp, endpos, OSFSK_SET); } /* add the HTML resources if we haven't already */ if (!found_htmlres) oplist = prochtmlres(fp, fpout, oplist, ©rsc, &showed_heading, FALSE); /* now go through what's left, and add new non-HTML resources */ if (fpout != 0) { for (op = oplist ; op != 0 ; op = op->opnxt) { if (!(op->opflag & OPFDONE) && (op->opflag & OPFADD) && op->oprestype != RESTYPE_HTML) { /* show what we're doing */ show_op("adding", op->opres, strlen(op->opres), op->oprestype); /* add the file */ procop(fpout, op, &first_xfcn); /* mark the operation as completed */ op->opflag |= OPFDONE; } } } /* if just listing, and we didn't find anything, tell the user so */ if (fpout == 0 && !found_user_rsc) rscptf("No user resources found.\n"); /* done reading the file - finish it up */ if (fpout != 0) { /* write EOF resource */ if (osfwb(fpout, "\004$EOF\0\0\0\0", 9)) errexit("error writing resource", 1); /* write first_xfcn value to EXTCNT resource */ if (extcnt_pos) { osfseek(fpout, extcnt_pos + 13, OSFSK_SET); oswp4(buf, first_xfcn); osfwb(fpout, buf, 4); } } /* * return the final oplist (it may have been changed during * processing) */ return oplist; }