00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "ScriptState.h"
00010
00011 #include "Log.h"
00012 #include "Path.h"
00013 #include "ScriptException.h"
00014
00015 extern "C" {
00016 #include "lualib.h"
00017 #include "lauxlib.h"
00018 }
00019
00020 #include "def-script.h"
00021
00022
00023 ScriptState::ScriptState()
00024 {
00025 m_state = lua_open();
00026 luaopen_base(m_state);
00027 luaopen_string(m_state);
00028 luaopen_math(m_state);
00029 luaopen_table(m_state);
00030
00031 prepareErrorHandler();
00032 }
00033
00034 ScriptState::~ScriptState()
00035 {
00036 lua_close(m_state);
00037 }
00038
00039
00040
00041
00042 void
00043 ScriptState::prepareErrorHandler()
00044 {
00045 lua_pushliteral(m_state, "_TRACEBACK");
00046 lua_pushcfunction(m_state, script_debugStack);
00047 lua_settable(m_state, LUA_GLOBALSINDEX);
00048 }
00049
00050
00051
00052
00053 void
00054 ScriptState::insertErrorHandler(int index)
00055 {
00056 lua_pushliteral(m_state, "_TRACEBACK");
00057 lua_rawget(m_state, LUA_GLOBALSINDEX);
00058 lua_insert(m_state, index);
00059 }
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 void
00070 ScriptState::callStack(int error, int params, int returns)
00071 {
00072 if (0 == error) {
00073 int base = lua_gettop(m_state) - params;
00074 insertErrorHandler(base);
00075 error = lua_pcall(m_state, params, returns, base);
00076 lua_remove(m_state, base);
00077 }
00078
00079 if (error) {
00080 const char *msg = lua_tostring(m_state, -1);
00081 if (NULL == msg) {
00082 msg = "(error with no message)";
00083 }
00084 lua_pop(m_state, 1);
00085 throw ScriptException(ExInfo("script failure")
00086 .addInfo("error", msg));
00087 }
00088 }
00089
00090
00091
00092
00093
00094 void
00095 ScriptState::doFile(const Path &file)
00096 {
00097 int error = luaL_loadfile(m_state, file.getNative().c_str());
00098 callStack(error);
00099 }
00100
00101
00102
00103
00104
00105 void
00106 ScriptState::doString(const std::string &input)
00107 {
00108 int error = luaL_loadbuffer(m_state, input.c_str(), input.size(),
00109 input.c_str());
00110 callStack(error);
00111 }
00112
00113 void
00114 ScriptState::registerFunc(const char *name, lua_CFunction func)
00115 {
00116 lua_register(m_state, name, func);
00117 }
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127 bool
00128 ScriptState::callCommand(int funcRef, int param)
00129 {
00130 int numResults = 1;
00131 lua_rawgeti(m_state, LUA_REGISTRYINDEX, funcRef);
00132 lua_pushnumber(m_state, param);
00133 callStack(0, 1, numResults);
00134
00135 if (0 == lua_isboolean(m_state, -1)) {
00136 const char *type = lua_typename(m_state, lua_type(m_state, -1));
00137 lua_pop(m_state, numResults);
00138 throw ScriptException(
00139 ExInfo("script command failure - boolean expected")
00140 .addInfo("got", type));
00141 }
00142 bool result = lua_toboolean(m_state, -1);
00143 lua_pop(m_state, numResults);
00144 return result;
00145 }
00146
00147
00148
00149
00150
00151 void
00152 ScriptState::unref(int funcRef)
00153 {
00154 luaL_unref(m_state, LUA_REGISTRYINDEX, funcRef);
00155 }
00156
00157
00158
00159
00160
00161 void
00162 ScriptState::registerLeader(Scripter *leader)
00163 {
00164 lua_pushstring(m_state, script_getLeaderName());
00165 lua_pushlightuserdata(m_state, leader);
00166 lua_rawset(m_state, LUA_REGISTRYINDEX);
00167 }
00168