summaryrefslogtreecommitdiff
path: root/library/LuaTools.cpp
diff options
context:
space:
mode:
authorAlexander Gavrilov2012-04-03 20:02:01 +0400
committerAlexander Gavrilov2012-04-03 20:02:01 +0400
commit2d4af4ac3e42ae1140fecc90b3beb02d0dd84f4a (patch)
tree6b33d8183b00ab462ce38b151cb2402f95e3f699 /library/LuaTools.cpp
parent42a9b0a59271f80d512dde78407d3a07681b3421 (diff)
downloaddfhack-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.cpp99
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 }