diff options
| author | Alexander Gavrilov | 2012-04-03 20:02:01 +0400 |
|---|---|---|
| committer | Alexander Gavrilov | 2012-04-03 20:02:01 +0400 |
| commit | 2d4af4ac3e42ae1140fecc90b3beb02d0dd84f4a (patch) | |
| tree | 6b33d8183b00ab462ce38b151cb2402f95e3f699 /library/LuaTools.cpp | |
| parent | 42a9b0a59271f80d512dde78407d3a07681b3421 (diff) | |
| download | dfhack-2d4af4ac3e42ae1140fecc90b3beb02d0dd84f4a.tar.gz dfhack-2d4af4ac3e42ae1140fecc90b3beb02d0dd84f4a.tar.bz2 dfhack-2d4af4ac3e42ae1140fecc90b3beb02d0dd84f4a.tar.xz | |
A few more utility functions for lua.
Diffstat (limited to 'library/LuaTools.cpp')
| -rw-r--r-- | library/LuaTools.cpp | 99 |
1 files changed, 81 insertions, 18 deletions
diff --git a/library/LuaTools.cpp b/library/LuaTools.cpp index 1477b16d..caeed3a3 100644 --- a/library/LuaTools.cpp +++ b/library/LuaTools.cpp @@ -141,6 +141,49 @@ static int traceback (lua_State *L) { return 1; } +static int finish_dfhack_safecall (lua_State *L, bool success) +{ + if (!lua_checkstack(L, 1)) + { + lua_settop(L, 0); /* create space for return values */ + lua_pushboolean(L, 0); + lua_pushstring(L, "stack overflow in dfhack.safecall()"); + success = false; + } + else + { + lua_pushboolean(L, success); + lua_replace(L, 1); /* put first result in first slot */ + } + + if (!success) + { + const char *msg = lua_tostring(L, -1); + if (!msg) msg = "In dfhack.safecall: error message is not a string."; + if (color_ostream *out = Lua::GetOutput(L)) + out->printerr("%s\n", msg); + else + Core::printerr("%s\n", msg); + } + + return lua_gettop(L); +} + +static int safecall_cont (lua_State *L) +{ + int status = lua_getctx(L, NULL); + return finish_dfhack_safecall(L, (status == LUA_YIELD)); +} + +static int lua_dfhack_safecall (lua_State *L) +{ + luaL_checkany(L, 1); + lua_pushcfunction(L, traceback); + lua_insert(L, 1); + int status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 1, 0, safecall_cont); + return finish_dfhack_safecall(L, (status == LUA_OK)); +} + static void report_error(color_ostream &out, lua_State *L) { const char *msg = lua_tostring(L, -1); @@ -189,24 +232,48 @@ bool DFHack::Lua::Require(color_ostream &out, lua_State *state, return true; } -static bool load_with_env(color_ostream &out, lua_State *state, const std::string &code, int eidx) +bool DFHack::Lua::AssignDFObject(color_ostream &out, lua_State *state, + type_identity *type, void *target, int val_index, bool perr) { - if (luaL_loadbuffer(state, code.data(), code.size(), "=(interactive)") != LUA_OK) + val_index = lua_absindex(state, val_index); + lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_ASSIGN_NAME); + PushDFObject(state, type, target); + lua_pushvalue(state, val_index); + return Lua::SafeCall(out, state, 2, 0, perr); +} + +bool DFHack::Lua::SafeCallString(color_ostream &out, lua_State *state, const std::string &code, + int nargs, int nres, bool perr, + const char *debug_tag, int env_idx) +{ + if (!debug_tag) + debug_tag = code.c_str(); + if (env_idx) + env_idx = lua_absindex(state, env_idx); + + int base = lua_gettop(state); + + // Parse the code + if (luaL_loadbuffer(state, code.data(), code.size(), debug_tag) != LUA_OK) { - report_error(out, state); + if (perr) + report_error(out, state); + return false; } // Replace _ENV - lua_pushvalue(state, eidx); - - if (!lua_setupvalue(state, -2, 1)) + if (env_idx) { - out.printerr("No _ENV upvalue.\n"); - return false; + lua_pushvalue(state, env_idx); + lua_setupvalue(state, -2, 1); + assert(lua_gettop(state) == base+1); } - return true; + if (nargs > 0) + lua_insert(state, -1-nargs); + + return Lua::SafeCall(out, state, nargs, nres, perr); } bool DFHack::Lua::InterpreterLoop(color_ostream &out, lua_State *state, @@ -273,9 +340,7 @@ bool DFHack::Lua::InterpreterLoop(color_ostream &out, lua_State *state, { curline = "return " + curline.substr(1); - if (!load_with_env(out, state, curline, base)) - continue; - if (!SafeCall(out, state, 0, LUA_MULTRET)) + if (!Lua::SafeCallString(out, state, curline, 0, LUA_MULTRET, true, "=(interactive)", base)) continue; int numret = lua_gettop(state) - base; @@ -309,9 +374,7 @@ bool DFHack::Lua::InterpreterLoop(color_ostream &out, lua_State *state, } else { - if (!load_with_env(out, state, curline, base)) - continue; - if (!SafeCall(out, state, 0, 0)) + if (!Lua::SafeCallString(out, state, curline, 0, LUA_MULTRET, true, "=(interactive)", base)) continue; } } @@ -352,8 +415,7 @@ static int lua_dfhack_interpreter(lua_State *state) static int lua_dfhack_with_suspend(lua_State *L) { - int ctx; - int rv = lua_getctx(L, &ctx); + int rv = lua_getctx(L, NULL); // Non-resume entry point: if (rv == LUA_OK) @@ -385,7 +447,8 @@ static const luaL_Reg dfhack_funcs[] = { { "print", lua_dfhack_print }, { "println", lua_dfhack_println }, { "printerr", lua_dfhack_printerr }, - { "traceback", traceback }, + { "safecall", lua_dfhack_safecall }, + { "onerror", traceback }, { "interpreter", lua_dfhack_interpreter }, { "with_suspend", lua_dfhack_with_suspend }, { NULL, NULL } |
