+ char *text(alloc.Alloc(size));
+ int cursor(0);
+ for (vector<ScriptToken *>::const_iterator i(s.begin()), end(s.end()); i != end; ++i) {
+ if ((*i)->GetType() == ScriptToken::LABEL) {
+ continue;
+ }
+ if ((*i)->GetType() != ScriptToken::COMMAND) {
+ throw Error("unexpected script token");
+ }
+ const string &cmd((*i)->CommandName());
+ if (cmd == "move") {
+ Script::Code &code(CreateScriptCode(Script::COMMAND_MOVE, text + cursor));
+ cursor += sizeof(Script::Code);
+ code.numParams = 2;
+ ++i;
+ const string ®((*i)->RegisterName());
+ switch (reg[0]) {
+ case 'a':
+ code.type = Script::TYPE_ADDRESS;
+ break;
+ case 'i':
+ code.type = Script::TYPE_INTEGER;
+ break;
+ case 'v':
+ code.type = Script::TYPE_VECTOR;
+ break;
+ default:
+ throw Error("invalid register " + reg);
+ }
+ int regnum(reg[1] - '0');
+ if (regnum < 0 || regnum > 6) {
+ throw Error("invalid register " + reg);
+ }
+ code.reg1 = regnum;
+ ++i;
+
+ if ((*i)->GetType() == ScriptToken::REGISTER) {
+ string reg2((*i)->RegisterName());
+ if (reg[0] != reg2[0]) {
+ throw Error("mixed-type commands not allowed");
+ }
+ int reg2num(reg[1] - '0');
+ if (reg2num < 0 || reg2num > 6) {
+ throw Error("invalid register " + reg2);
+ }
+ code.reg2 = reg2num;
+ } else {
+ code.reg2 = 7;
+ switch (code.type) {
+ case Script::TYPE_ADDRESS:
+ ReadScriptAddress(**i, text + cursor);
+ cursor += sizeof(void *);
+ break;
+ case Script::TYPE_INTEGER:
+ ReadScriptInteger(**i, text + cursor);
+ cursor += sizeof(int);
+ break;
+ case Script::TYPE_VECTOR:
+ ReadScriptVector(**i, text + cursor);
+ cursor += sizeof(Vector<int>);
+ break;
+ }
+ }
+ } else if (cmd == "add") {
+ Script::Code &code(CreateScriptCode(Script::COMMAND_ADD, text + cursor));
+ cursor += sizeof(Script::Code);
+ code.numParams = 2;
+ ++i;
+ const string ®((*i)->RegisterName());
+ switch (reg[0]) {
+ case 'i':
+ code.type = Script::TYPE_INTEGER;
+ break;
+ case 'v':
+ code.type = Script::TYPE_VECTOR;
+ break;
+ default:
+ throw Error("invalid register " + reg);
+ }
+ int regnum(reg[1] - '0');
+ if (regnum < 0 || regnum > 6) {
+ throw Error("invalid register " + reg);
+ }
+ code.reg1 = regnum;
+ ++i;
+
+ if ((*i)->GetType() == ScriptToken::REGISTER) {
+ string reg2((*i)->RegisterName());
+ if (reg[0] != reg2[0]) {
+ throw Error("mixed-type commands not allowed");
+ }
+ int reg2num(reg[1] - '0');
+ if (reg2num < 0 || reg2num > 6) {
+ throw Error("invalid register name " + reg2);
+ }
+ code.reg2 = reg2num;
+ } else {
+ code.reg2 = 7;
+ switch (code.type) {
+ case Script::TYPE_INTEGER:
+ ReadScriptInteger(**i, text + cursor);
+ cursor += sizeof(int);
+ break;
+ case Script::TYPE_VECTOR:
+ ReadScriptVector(**i, text + cursor);
+ cursor += sizeof(Vector<int>);
+ break;
+ }
+ }
+ } else if (cmd == "mod") {
+ Script::Code &code(CreateScriptCode(Script::COMMAND_MOD, text + cursor));
+ cursor += sizeof(Script::Code);
+ code.numParams = 2;
+ ++i;
+ const string ®((*i)->RegisterName());
+ if (reg[0] != 'i') {
+ throw Error("invalid register " + reg);
+ }
+ code.type = Script::TYPE_INTEGER;
+ int regnum(reg[1] - '0');
+ if (regnum < 0 || regnum > 6) {
+ throw Error("invalid register " + reg);
+ }
+ code.reg1 = regnum;
+ ++i;
+
+ if ((*i)->GetType() == ScriptToken::REGISTER) {
+ string reg2((*i)->RegisterName());
+ if (reg[0] != reg2[0]) {
+ throw Error("mixed-type commands not allowed");
+ }
+ int reg2num(reg[1] - '0');
+ if (reg2num < 0 || reg2num > 6) {
+ throw Error("invalid register name " + reg2);
+ }
+ code.reg2 = reg2num;
+ } else {
+ code.reg2 = 7;
+ ReadScriptInteger(**i, text + cursor);
+ cursor += sizeof(int);
+ }
+ } else if (cmd == "rand") {
+ Script::Code &code(CreateScriptCode(Script::COMMAND_RAND, text + cursor));
+ cursor += sizeof(Script::Code);
+ code.numParams = 1;
+ ++i;
+ const string ®((*i)->RegisterName());
+ if (reg[0] != 'i') {
+ throw Error("invalid register " + reg);
+ }
+ code.type = Script::TYPE_INTEGER;
+ int regnum(reg[1] - '0');
+ if (regnum < 0 || regnum > 6) {
+ throw Error("invalid register " + reg);
+ }
+ code.reg1 = regnum;
+ } else if (cmd == "cmp") {
+ Script::Code &code(CreateScriptCode(Script::COMMAND_CMP, text + cursor));
+ cursor += sizeof(Script::Code);
+ code.numParams = 2;
+ ++i;
+ const string ®((*i)->RegisterName());
+ if (reg[0] != 'i') {
+ throw Error("invalid register " + reg);
+ }
+ code.type = Script::TYPE_INTEGER;
+ int regnum(reg[1] - '0');
+ if (regnum < 0 || regnum > 6) {
+ throw Error("invalid register " + reg);
+ }
+ code.reg1 = regnum;
+ ++i;
+
+ if ((*i)->GetType() == ScriptToken::REGISTER) {
+ string reg2((*i)->RegisterName());
+ if (reg[0] != reg2[0]) {
+ throw Error("mixed-type commands not allowed");
+ }
+ int reg2num(reg[1] - '0');
+ if (reg2num < 0 || reg2num > 6) {
+ throw Error("invalid register name " + reg2);
+ }
+ code.reg2 = reg2num;
+ } else {
+ code.reg2 = 7;
+ ReadScriptInteger(**i, text + cursor);
+ cursor += sizeof(int);
+ }
+ } else if (cmd == "jmp") {
+ Script::Code &code(CreateScriptCode(Script::COMMAND_JMP, text + cursor));
+ cursor += sizeof(Script::Code);
+ code.numParams = 1;
+ ++i;
+ if (!labels.count((*i)->Identifier())) {
+ throw Error("use of undefined label " + (*i)->Identifier());
+ }
+ *reinterpret_cast<int *>(text + cursor) = labels[(*i)->Identifier()];
+ cursor += sizeof(int);
+ } else if (cmd == "jeq") {
+ Script::Code &code(CreateScriptCode(Script::COMMAND_JEQ, text + cursor));
+ cursor += sizeof(Script::Code);
+ code.numParams = 1;
+ ++i;
+ if (!labels.count((*i)->Identifier())) {
+ throw Error("use of undefined label " + (*i)->Identifier());
+ }
+ *reinterpret_cast<int *>(text + cursor) = labels[(*i)->Identifier()];
+ cursor += sizeof(int);
+ } else if (cmd == "jne") {
+ Script::Code &code(CreateScriptCode(Script::COMMAND_JNE, text + cursor));
+ cursor += sizeof(Script::Code);
+ code.numParams = 1;
+ ++i;
+ if (!labels.count((*i)->Identifier())) {
+ throw Error("use of undefined label " + (*i)->Identifier());
+ }
+ *reinterpret_cast<int *>(text + cursor) = labels[(*i)->Identifier()];
+ cursor += sizeof(int);
+ } else if (cmd == "jl") {
+ Script::Code &code(CreateScriptCode(Script::COMMAND_JL, text + cursor));
+ cursor += sizeof(Script::Code);
+ code.numParams = 1;
+ ++i;
+ if (!labels.count((*i)->Identifier())) {
+ throw Error("use of undefined label " + (*i)->Identifier());
+ }
+ *reinterpret_cast<int *>(text + cursor) = labels[(*i)->Identifier()];
+ cursor += sizeof(int);
+ } else if (cmd == "jle") {
+ Script::Code &code(CreateScriptCode(Script::COMMAND_JLE, text + cursor));
+ cursor += sizeof(Script::Code);
+ code.numParams = 1;
+ ++i;
+ if (!labels.count((*i)->Identifier())) {
+ throw Error("use of undefined label " + (*i)->Identifier());
+ }
+ *reinterpret_cast<int *>(text + cursor) = labels[(*i)->Identifier()];
+ cursor += sizeof(int);
+ } else if (cmd == "jg") {
+ Script::Code &code(CreateScriptCode(Script::COMMAND_JG, text + cursor));
+ cursor += sizeof(Script::Code);
+ code.numParams = 1;
+ ++i;
+ if (!labels.count((*i)->Identifier())) {
+ throw Error("use of undefined label " + (*i)->Identifier());
+ }
+ *reinterpret_cast<int *>(text + cursor) = labels[(*i)->Identifier()];
+ cursor += sizeof(int);
+ } else if (cmd == "jge") {
+ Script::Code &code(CreateScriptCode(Script::COMMAND_JGE, text + cursor));
+ cursor += sizeof(Script::Code);
+ code.numParams = 1;
+ ++i;
+ if (!labels.count((*i)->Identifier())) {
+ throw Error("use of undefined label " + (*i)->Identifier());
+ }
+ *reinterpret_cast<int *>(text + cursor) = labels[(*i)->Identifier()];
+ cursor += sizeof(int);
+ } else if (cmd == "sysc") {
+ Script::Code &code(CreateScriptCode(Script::COMMAND_SYSC, text + cursor));
+ cursor += sizeof(Script::Code);
+ code.numParams = 0;
+ } else {
+ throw Error("unknown command " + cmd);
+ }