+/*
+ * ScriptRunner.cpp
+ *
+ * Created on: Oct 13, 2012
+ * Author: holy
+ */
+
+#include "ScriptRunner.h"
+
+#include "Script.h"
+#include "ScriptHost.h"
+
+#include <cstdlib>
+
+using geometry::Vector;
+
+namespace common {
+
+ScriptRunner::ScriptRunner()
+: host(0)
+, script(0)
+, cursor(0)
+, address0(0)
+, address1(0)
+, integer0(0)
+, integer1(0)
+, vector0(0, 0)
+, vector1(0, 0) {
+
+}
+
+ScriptRunner::~ScriptRunner() {
+
+}
+
+
+bool ScriptRunner::Running() const {
+ return script && cursor < script->textlen;
+}
+
+void ScriptRunner::Run(ScriptHost &h, const Script &s) {
+ host = &h;
+ script = &s;
+ Reset();
+ while (cursor < script->textlen) {
+ unsigned char code(script->text[cursor]);
+ ++cursor;
+ Exec(code);
+ }
+ host = 0;
+ script = 0;
+}
+
+void ScriptRunner::Reset() {
+ cursor = 0;
+ address0 = 0;
+ address1 = 0;
+ integer0 = 0;
+ integer1 = 0;
+ vector0 = Vector<int>(0, 0);
+ vector1 = Vector<int>(0, 0);
+}
+
+void ScriptRunner::Exec(unsigned char code) {
+ switch (code) {
+ case Script::CODE_MOVE_A0:
+ address0 = PopAddress();
+ break;
+ case Script::CODE_MOVE_A1:
+ address1 = PopAddress();
+ break;
+ case Script::CODE_MOVE_I0:
+ integer0 = PopInt();
+ break;
+ case Script::CODE_MOVE_I1:
+ integer1 = PopInt();
+ break;
+ case Script::CODE_MOVE_V0:
+ vector0 = PopVector();
+ break;
+ case Script::CODE_MOVE_V1:
+ vector1 = PopVector();
+ break;
+ case Script::CODE_ADD_I0:
+ integer0 += PopInt();
+ break;
+ case Script::CODE_ADD_I1:
+ integer1 += PopInt();
+ break;
+ case Script::CODE_ADD_V0:
+ vector0 += PopVector();
+ break;
+ case Script::CODE_ADD_V1:
+ vector1 += PopVector();
+ break;
+ case Script::CODE_RAND_I0:
+ integer0 = std::rand();
+ break;
+ case Script::CODE_RAND_I1:
+ integer1 = std::rand();
+ break;
+ case Script::CODE_SYSCALL:
+ host->HandleSyscall(*this);
+ break;
+ }
+}
+
+void *ScriptRunner::PopAddress() {
+ void *const *addr(reinterpret_cast<void *const *>(script->text + cursor));
+ cursor += sizeof(void *);
+ return *addr;
+}
+
+int ScriptRunner::PopInt() {
+ const int *i(reinterpret_cast<const int *>(script->text + cursor));
+ cursor += sizeof(int);
+ return *i;
+}
+
+const Vector<int> &ScriptRunner::PopVector() {
+ const Vector<int> *vec(reinterpret_cast<const Vector<int> *>(script->text + cursor));
+ cursor += sizeof(Vector<int>);
+ return *vec;
+}
+
+}