From 371b39a09a0bf248d674fae718f5ff369e895b66 Mon Sep 17 00:00:00 2001 From: ShadowNinja Date: Tue, 5 Nov 2013 12:06:15 -0500 Subject: Pass a errfunc to lua_pcall to get a traceback --- src/script/common/c_content.cpp | 9 ++++--- src/script/common/c_internal.cpp | 56 ++++++++++++++++++++++++++-------------- src/script/common/c_internal.h | 9 ++++--- src/script/common/c_types.cpp | 5 ++-- 4 files changed, 49 insertions(+), 30 deletions(-) (limited to 'src/script/common') diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index a035b32a2..2ad4c9565 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -871,6 +871,8 @@ void read_groups(lua_State *L, int index, /******************************************************************************/ void push_items(lua_State *L, const std::vector &items) { + lua_pushcfunction(L, script_error_handler); + int errorhandler = lua_gettop(L); // Get the table insert function lua_getglobal(L, "table"); lua_getfield(L, -1, "insert"); @@ -883,11 +885,12 @@ void push_items(lua_State *L, const std::vector &items) lua_pushvalue(L, table_insert); lua_pushvalue(L, table); LuaItemStack::create(L, item); - if(lua_pcall(L, 2, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); + if(lua_pcall(L, 2, 0, errorhandler)) + script_error(L); } - lua_remove(L, -2); // Remove table lua_remove(L, -2); // Remove insert + lua_remove(L, -2); // Remove table + lua_remove(L, -2); // Remove error handler } /******************************************************************************/ diff --git a/src/script/common/c_internal.cpp b/src/script/common/c_internal.cpp index 5c16b88d9..7415aecb8 100644 --- a/src/script/common/c_internal.cpp +++ b/src/script/common/c_internal.cpp @@ -23,32 +23,41 @@ with this program; if not, write to the Free Software Foundation, Inc., std::string script_get_backtrace(lua_State *L) { std::string s; - lua_getfield(L, LUA_GLOBALSINDEX, "debug"); + lua_getglobal(L, "debug"); if(lua_istable(L, -1)){ lua_getfield(L, -1, "traceback"); - if(lua_isfunction(L, -1)){ + if(lua_isfunction(L, -1)) { lua_call(L, 0, 1); if(lua_isstring(L, -1)){ - s += lua_tostring(L, -1); + s = lua_tostring(L, -1); } - lua_pop(L, 1); - } - else{ - lua_pop(L, 1); } + lua_pop(L, 1); } lua_pop(L, 1); return s; } -void script_error(lua_State *L, const char *fmt, ...) +int script_error_handler(lua_State *L) { + lua_getglobal(L, "debug"); + if (!lua_istable(L, -1)) { + lua_pop(L, 1); + return 1; + } + lua_getfield(L, -1, "traceback"); + if (!lua_isfunction(L, -1)) { + lua_pop(L, 2); + return 1; + } + lua_pushvalue(L, 1); + lua_pushinteger(L, 2); + lua_call(L, 2, 1); + return 1; +} + +void script_error(lua_State *L) { - va_list argp; - va_start(argp, fmt); - char buf[10000]; - vsnprintf(buf, 10000, fmt, argp); - va_end(argp); - throw LuaError(L, buf); + throw LuaError(NULL, lua_tostring(L, -1)); } // Push the list of callbacks (a lua table). @@ -61,13 +70,20 @@ void script_run_callbacks(lua_State *L, int nargs, RunCallbacksMode mode) { // Insert the return value into the lua stack, below the table assert(lua_gettop(L) >= nargs + 1); + lua_pushnil(L); - lua_insert(L, -(nargs + 1) - 1); + int rv = lua_gettop(L) - nargs - 1; + lua_insert(L, rv); + + // Insert error handler after return value + lua_pushcfunction(L, script_error_handler); + int errorhandler = rv + 1; + lua_insert(L, errorhandler); + // Stack now looks like this: - // ... ... + // ...
... - int rv = lua_gettop(L) - nargs - 1; - int table = rv + 1; + int table = errorhandler + 1; int arg = table + 1; luaL_checktype(L, table, LUA_TTABLE); @@ -81,8 +97,8 @@ void script_run_callbacks(lua_State *L, int nargs, RunCallbacksMode mode) // Call function for(int i = 0; i < nargs; i++) lua_pushvalue(L, arg+i); - if(lua_pcall(L, nargs, 1, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); + if(lua_pcall(L, nargs, 1, errorhandler)) + script_error(L); // Move return value to designated space in stack // Or pop it diff --git a/src/script/common/c_internal.h b/src/script/common/c_internal.h index 9a50b8e96..eb6aa06e8 100644 --- a/src/script/common/c_internal.h +++ b/src/script/common/c_internal.h @@ -64,9 +64,10 @@ enum RunCallbacksMode // are converted by lua_toboolean to true or false, respectively. }; -std::string script_get_backtrace (lua_State *L); -void script_error (lua_State *L, const char *fmt, ...); -void script_run_callbacks (lua_State *L, int nargs, - RunCallbacksMode mode); +std::string script_get_backtrace(lua_State *L); +int script_error_handler(lua_State *L); +void script_error(lua_State *L); +void script_run_callbacks(lua_State *L, int nargs, + RunCallbacksMode mode); #endif /* C_INTERNAL_H_ */ diff --git a/src/script/common/c_types.cpp b/src/script/common/c_types.cpp index ac724c42c..a6faf9819 100644 --- a/src/script/common/c_types.cpp +++ b/src/script/common/c_types.cpp @@ -25,9 +25,8 @@ with this program; if not, write to the Free Software Foundation, Inc., LuaError::LuaError(lua_State *L, const std::string &s) { - m_s = "LuaError: "; - m_s += s + "\n"; - m_s += script_get_backtrace(L); + m_s = "LuaError: " + s; + if (L) m_s += '\n' + script_get_backtrace(L); } struct EnumString es_ItemType[] = -- cgit v1.2.3