From 371b39a09a0bf248d674fae718f5ff369e895b66 Mon Sep 17 00:00:00 2001 From: ShadowNinja Date: Tue, 5 Nov 2013 12:06:15 -0500 Subject: [PATCH] Pass a errfunc to lua_pcall to get a traceback --- src/script/common/c_content.cpp | 9 +- src/script/common/c_internal.cpp | 58 +++++++---- src/script/common/c_internal.h | 9 +- src/script/common/c_types.cpp | 5 +- src/script/cpp_api/s_base.cpp | 33 +----- src/script/cpp_api/s_base.h | 3 +- src/script/cpp_api/s_entity.cpp | 60 +++++++---- src/script/cpp_api/s_inventory.cpp | 147 +++++++++++++------------- src/script/cpp_api/s_item.cpp | 70 +++++++------ src/script/cpp_api/s_mainmenu.cpp | 28 +++-- src/script/cpp_api/s_node.cpp | 92 ++++++++++------ src/script/cpp_api/s_nodemeta.cpp | 162 ++++++++++++++--------------- src/script/cpp_api/s_server.cpp | 31 ++++-- src/script/lua_api/l_base.h | 1 + src/script/lua_api/l_craft.cpp | 2 +- src/script/lua_api/l_env.cpp | 28 +++-- src/script/lua_api/l_noise.cpp | 5 +- src/script/lua_api/l_rollback.cpp | 2 +- src/script/lua_api/l_server.cpp | 3 +- 19 files changed, 424 insertions(+), 324 deletions(-) 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); - // Stack now looks like this: - // ... ... + lua_pushnil(L); int rv = lua_gettop(L) - nargs - 1; - int table = rv + 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 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[] = diff --git a/src/script/cpp_api/s_base.cpp b/src/script/cpp_api/s_base.cpp index e26d54ba7..b1272b64e 100644 --- a/src/script/cpp_api/s_base.cpp +++ b/src/script/cpp_api/s_base.cpp @@ -55,23 +55,6 @@ public: } }; -static int loadScript_ErrorHandler(lua_State *L) { - lua_getfield(L, LUA_GLOBALSINDEX, "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; -} - /* ScriptApiBase @@ -133,7 +116,7 @@ bool ScriptApiBase::loadScript(const std::string &scriptpath) lua_State *L = getStack(); - lua_pushcfunction(L, loadScript_ErrorHandler); + lua_pushcfunction(L, script_error_handler); int errorhandler = lua_gettop(L); int ret = luaL_loadfile(L, scriptpath.c_str()) || lua_pcall(L, 0, 0, errorhandler); @@ -144,7 +127,7 @@ bool ScriptApiBase::loadScript(const std::string &scriptpath) errorstream<= 30){ dstream<<"Stack is over 30:"< items; for(u32 i=0; igetSize(); i++) @@ -130,10 +149,11 @@ bool ScriptApiItem::item_CraftPredict(ItemStack &item, ServerActiveObject *user, push_items(L, items); InvRef::create(L, craft_inv); - if(lua_pcall(L, 4, 1, 0)) - scriptError("error: %s", lua_tostring(L, -1)); + if(lua_pcall(L, 4, 1, errorhandler)) + scriptError(); if(!lua_isnil(L, -1)) item = read_item(L,-1, getServer()); + lua_pop(L, 2); // Pop item and error handler return true; } @@ -149,15 +169,15 @@ bool ScriptApiItem::getItemCallback(const char *name, const char *callbackname) lua_getglobal(L, "minetest"); lua_getfield(L, -1, "registered_items"); - lua_remove(L, -2); + lua_remove(L, -2); // Remove minetest luaL_checktype(L, -1, LUA_TTABLE); lua_getfield(L, -1, name); - lua_remove(L, -2); + lua_remove(L, -2); // Remove registered_items // Should be a table if(lua_type(L, -1) != LUA_TTABLE) { // Report error and clean up - errorstream<<"Item \""< fields) { SCRIPTAPI_PRECHECKHEADER + lua_pushcfunction(L, script_error_handler); + int errorhandler = lua_gettop(L); + // Get handler function lua_getglobal(L, "engine"); lua_getfield(L, -1, "button_handler"); - if(lua_isnil(L, -1)) + lua_remove(L, -2); // Remove engine + if(lua_isnil(L, -1)) { + lua_pop(L, 1); // Pop button handler return; + } luaL_checktype(L, -1, LUA_TFUNCTION); // Convert fields to lua table @@ -74,7 +86,7 @@ void ScriptApiMainMenu::handleMainMenuButtons(std::map } // Call it - if(lua_pcall(L, 1, 0, 0)) - scriptError("error running function engine.button_handler: %s\n", - lua_tostring(L, -1)); + if(lua_pcall(L, 1, 0, errorhandler)) + scriptError(); + lua_pop(L, 1); // Pop error handler } diff --git a/src/script/cpp_api/s_node.cpp b/src/script/cpp_api/s_node.cpp index 92fd00a74..cd8451cf0 100644 --- a/src/script/cpp_api/s_node.cpp +++ b/src/script/cpp_api/s_node.cpp @@ -91,6 +91,9 @@ bool ScriptApiNode::node_on_punch(v3s16 p, MapNode node, { SCRIPTAPI_PRECHECKHEADER + lua_pushcfunction(L, script_error_handler); + int errorhandler = lua_gettop(L); + INodeDefManager *ndef = getServer()->ndef(); // Push callback function on stack @@ -101,8 +104,9 @@ bool ScriptApiNode::node_on_punch(v3s16 p, MapNode node, push_v3s16(L, p); pushnode(L, node, ndef); objectrefGetOrCreate(puncher); - if(lua_pcall(L, 3, 0, 0)) - scriptError("error: %s", lua_tostring(L, -1)); + if(lua_pcall(L, 3, 0, errorhandler)) + scriptError(); + lua_pop(L, 1); // Pop error handler return true; } @@ -111,6 +115,9 @@ bool ScriptApiNode::node_on_dig(v3s16 p, MapNode node, { SCRIPTAPI_PRECHECKHEADER + lua_pushcfunction(L, script_error_handler); + int errorhandler = lua_gettop(L); + INodeDefManager *ndef = getServer()->ndef(); // Push callback function on stack @@ -121,8 +128,9 @@ bool ScriptApiNode::node_on_dig(v3s16 p, MapNode node, push_v3s16(L, p); pushnode(L, node, ndef); objectrefGetOrCreate(digger); - if(lua_pcall(L, 3, 0, 0)) - scriptError("error: %s", lua_tostring(L, -1)); + if(lua_pcall(L, 3, 0, errorhandler)) + scriptError(); + lua_pop(L, 1); // Pop error handler return true; } @@ -130,6 +138,9 @@ void ScriptApiNode::node_on_construct(v3s16 p, MapNode node) { SCRIPTAPI_PRECHECKHEADER + lua_pushcfunction(L, script_error_handler); + int errorhandler = lua_gettop(L); + INodeDefManager *ndef = getServer()->ndef(); // Push callback function on stack @@ -138,14 +149,18 @@ void ScriptApiNode::node_on_construct(v3s16 p, MapNode node) // Call function push_v3s16(L, p); - if(lua_pcall(L, 1, 0, 0)) - scriptError("error: %s", lua_tostring(L, -1)); + if(lua_pcall(L, 1, 0, errorhandler)) + scriptError(); + lua_pop(L, 1); // Pop error handler } void ScriptApiNode::node_on_destruct(v3s16 p, MapNode node) { SCRIPTAPI_PRECHECKHEADER + lua_pushcfunction(L, script_error_handler); + int errorhandler = lua_gettop(L); + INodeDefManager *ndef = getServer()->ndef(); // Push callback function on stack @@ -154,14 +169,18 @@ void ScriptApiNode::node_on_destruct(v3s16 p, MapNode node) // Call function push_v3s16(L, p); - if(lua_pcall(L, 1, 0, 0)) - scriptError("error: %s", lua_tostring(L, -1)); + if(lua_pcall(L, 1, 0, errorhandler)) + scriptError(); + lua_pop(L, 1); // Pop error handler } void ScriptApiNode::node_after_destruct(v3s16 p, MapNode node) { SCRIPTAPI_PRECHECKHEADER + lua_pushcfunction(L, script_error_handler); + int errorhandler = lua_gettop(L); + INodeDefManager *ndef = getServer()->ndef(); // Push callback function on stack @@ -171,14 +190,18 @@ void ScriptApiNode::node_after_destruct(v3s16 p, MapNode node) // Call function push_v3s16(L, p); pushnode(L, node, ndef); - if(lua_pcall(L, 2, 0, 0)) - scriptError("error: %s", lua_tostring(L, -1)); + if(lua_pcall(L, 2, 0, errorhandler)) + scriptError(); + lua_pop(L, 1); // Pop error handler } bool ScriptApiNode::node_on_timer(v3s16 p, MapNode node, f32 dtime) { SCRIPTAPI_PRECHECKHEADER + lua_pushcfunction(L, script_error_handler); + int errorhandler = lua_gettop(L); + INodeDefManager *ndef = getServer()->ndef(); // Push callback function on stack @@ -188,12 +211,10 @@ bool ScriptApiNode::node_on_timer(v3s16 p, MapNode node, f32 dtime) // Call function push_v3s16(L, p); lua_pushnumber(L,dtime); - if(lua_pcall(L, 2, 1, 0)) - scriptError("error: %s", lua_tostring(L, -1)); - if((bool)lua_isboolean(L,-1) && (bool)lua_toboolean(L,-1) == true) - return true; - - return false; + if(lua_pcall(L, 2, 1, errorhandler)) + scriptError(); + lua_remove(L, errorhandler); // Remove error handler + return (bool) lua_isboolean(L, -1) && (bool) lua_toboolean(L, -1) == true; } void ScriptApiNode::node_on_receive_fields(v3s16 p, @@ -203,6 +224,9 @@ void ScriptApiNode::node_on_receive_fields(v3s16 p, { SCRIPTAPI_PRECHECKHEADER + lua_pushcfunction(L, script_error_handler); + int errorhandler = lua_gettop(L); + INodeDefManager *ndef = getServer()->ndef(); // If node doesn't exist, we don't know what callback to call @@ -215,12 +239,9 @@ void ScriptApiNode::node_on_receive_fields(v3s16 p, return; // Call function - // param 1 - push_v3s16(L, p); - // param 2 - lua_pushstring(L, formname.c_str()); - // param 3 - lua_newtable(L); + push_v3s16(L, p); // pos + lua_pushstring(L, formname.c_str()); // formname + lua_newtable(L); // fields for(std::map::const_iterator i = fields.begin(); i != fields.end(); i++){ const std::string &name = i->first; @@ -229,26 +250,37 @@ void ScriptApiNode::node_on_receive_fields(v3s16 p, lua_pushlstring(L, value.c_str(), value.size()); lua_settable(L, -3); } - // param 4 - objectrefGetOrCreate(sender); - if(lua_pcall(L, 4, 0, 0)) - scriptError("error: %s", lua_tostring(L, -1)); + objectrefGetOrCreate(sender); // player + if(lua_pcall(L, 4, 0, errorhandler)) + scriptError(); + lua_pop(L, 1); // Pop error handler } void ScriptApiNode::node_falling_update(v3s16 p) { SCRIPTAPI_PRECHECKHEADER + + lua_pushcfunction(L, script_error_handler); + int errorhandler = lua_gettop(L); + lua_getglobal(L, "nodeupdate"); push_v3s16(L, p); - if(lua_pcall(L, 1, 0, 0)) - scriptError("error: %s", lua_tostring(L, -1)); + if(lua_pcall(L, 1, 0, errorhandler)) + scriptError(); + lua_pop(L, 1); // Pop error handler } void ScriptApiNode::node_falling_update_single(v3s16 p) { SCRIPTAPI_PRECHECKHEADER + + lua_pushcfunction(L, script_error_handler); + int errorhandler = lua_gettop(L); + lua_getglobal(L, "nodeupdate_single"); push_v3s16(L, p); - if(lua_pcall(L, 1, 0, 0)) - scriptError("error: %s", lua_tostring(L, -1)); + if(lua_pcall(L, 1, 0, errorhandler)) + scriptError(); + lua_pop(L, 1); // Pop error handler } + diff --git a/src/script/cpp_api/s_nodemeta.cpp b/src/script/cpp_api/s_nodemeta.cpp index e87464c61..1f04383f1 100644 --- a/src/script/cpp_api/s_nodemeta.cpp +++ b/src/script/cpp_api/s_nodemeta.cpp @@ -34,6 +34,9 @@ int ScriptApiNodemeta::nodemeta_inventory_AllowMove(v3s16 p, { SCRIPTAPI_PRECHECKHEADER + lua_pushcfunction(L, script_error_handler); + int errorhandler = lua_gettop(L); + INodeDefManager *ndef = getServer()->ndef(); // If node doesn't exist, we don't know what callback to call @@ -47,25 +50,21 @@ int ScriptApiNodemeta::nodemeta_inventory_AllowMove(v3s16 p, return count; // function(pos, from_list, from_index, to_list, to_index, count, player) - // pos - push_v3s16(L, p); - // from_list - lua_pushstring(L, from_list.c_str()); - // from_index - lua_pushinteger(L, from_index + 1); - // to_list - lua_pushstring(L, to_list.c_str()); - // to_index - lua_pushinteger(L, to_index + 1); - // count - lua_pushinteger(L, count); - // player - objectrefGetOrCreate(player); - if(lua_pcall(L, 7, 1, 0)) - scriptError("error: %s", lua_tostring(L, -1)); + push_v3s16(L, p); // pos + lua_pushstring(L, from_list.c_str()); // from_list + lua_pushinteger(L, from_index + 1); // from_index + lua_pushstring(L, to_list.c_str()); // to_list + lua_pushinteger(L, to_index + 1); // to_index + lua_pushinteger(L, count); // count + objectrefGetOrCreate(player); // player + if(lua_pcall(L, 7, 1, errorhandler)) + scriptError(); + lua_remove(L, errorhandler); // Remove error handler if(!lua_isnumber(L, -1)) throw LuaError(L, "allow_metadata_inventory_move should return a number"); - return luaL_checkinteger(L, -1); + int num = luaL_checkinteger(L, -1); + lua_pop(L, 1); // Pop integer + return num; } // Return number of accepted items to be put @@ -75,6 +74,9 @@ int ScriptApiNodemeta::nodemeta_inventory_AllowPut(v3s16 p, { SCRIPTAPI_PRECHECKHEADER + lua_pushcfunction(L, script_error_handler); + int errorhandler = lua_gettop(L); + INodeDefManager *ndef = getServer()->ndef(); // If node doesn't exist, we don't know what callback to call @@ -88,21 +90,19 @@ int ScriptApiNodemeta::nodemeta_inventory_AllowPut(v3s16 p, return stack.count; // Call function(pos, listname, index, stack, player) - // pos - push_v3s16(L, p); - // listname - lua_pushstring(L, listname.c_str()); - // index - lua_pushinteger(L, index + 1); - // stack - LuaItemStack::create(L, stack); - // player - objectrefGetOrCreate(player); - if(lua_pcall(L, 5, 1, 0)) - scriptError("error: %s", lua_tostring(L, -1)); + push_v3s16(L, p); // pos + lua_pushstring(L, listname.c_str()); // listname + lua_pushinteger(L, index + 1); // index + LuaItemStack::create(L, stack); // stack + objectrefGetOrCreate(player); // player + if(lua_pcall(L, 5, 1, errorhandler)) + scriptError(); + lua_remove(L, errorhandler); // Remove error handler if(!lua_isnumber(L, -1)) throw LuaError(L, "allow_metadata_inventory_put should return a number"); - return luaL_checkinteger(L, -1); + int num = luaL_checkinteger(L, -1); + lua_pop(L, 1); // Pop integer + return num; } // Return number of accepted items to be taken @@ -112,6 +112,9 @@ int ScriptApiNodemeta::nodemeta_inventory_AllowTake(v3s16 p, { SCRIPTAPI_PRECHECKHEADER + lua_pushcfunction(L, script_error_handler); + int errorhandler = lua_gettop(L); + INodeDefManager *ndef = getServer()->ndef(); // If node doesn't exist, we don't know what callback to call @@ -125,21 +128,19 @@ int ScriptApiNodemeta::nodemeta_inventory_AllowTake(v3s16 p, return stack.count; // Call function(pos, listname, index, count, player) - // pos - push_v3s16(L, p); - // listname - lua_pushstring(L, listname.c_str()); - // index - lua_pushinteger(L, index + 1); - // stack - LuaItemStack::create(L, stack); - // player - objectrefGetOrCreate(player); - if(lua_pcall(L, 5, 1, 0)) - scriptError("error: %s", lua_tostring(L, -1)); + push_v3s16(L, p); // pos + lua_pushstring(L, listname.c_str()); // listname + lua_pushinteger(L, index + 1); // index + LuaItemStack::create(L, stack); // stack + objectrefGetOrCreate(player); // player + if(lua_pcall(L, 5, 1, errorhandler)) + scriptError(); + lua_remove(L, errorhandler); // Remove error handler if(!lua_isnumber(L, -1)) throw LuaError(L, "allow_metadata_inventory_take should return a number"); - return luaL_checkinteger(L, -1); + int num = luaL_checkinteger(L, -1); + lua_pop(L, 1); // Pop integer + return num; } // Report moved items @@ -150,6 +151,9 @@ void ScriptApiNodemeta::nodemeta_inventory_OnMove(v3s16 p, { SCRIPTAPI_PRECHECKHEADER + lua_pushcfunction(L, script_error_handler); + int errorhandler = lua_gettop(L); + INodeDefManager *ndef = getServer()->ndef(); // If node doesn't exist, we don't know what callback to call @@ -163,22 +167,16 @@ void ScriptApiNodemeta::nodemeta_inventory_OnMove(v3s16 p, return; // function(pos, from_list, from_index, to_list, to_index, count, player) - // pos - push_v3s16(L, p); - // from_list - lua_pushstring(L, from_list.c_str()); - // from_index - lua_pushinteger(L, from_index + 1); - // to_list - lua_pushstring(L, to_list.c_str()); - // to_index - lua_pushinteger(L, to_index + 1); - // count - lua_pushinteger(L, count); - // player - objectrefGetOrCreate(player); - if(lua_pcall(L, 7, 0, 0)) - scriptError("error: %s", lua_tostring(L, -1)); + push_v3s16(L, p); // pos + lua_pushstring(L, from_list.c_str()); // from_list + lua_pushinteger(L, from_index + 1); // from_index + lua_pushstring(L, to_list.c_str()); // to_list + lua_pushinteger(L, to_index + 1); // to_index + lua_pushinteger(L, count); // count + objectrefGetOrCreate(player); // player + if(lua_pcall(L, 7, 0, errorhandler)) + scriptError(); + lua_pop(L, 1); // Pop error handler } // Report put items @@ -188,6 +186,9 @@ void ScriptApiNodemeta::nodemeta_inventory_OnPut(v3s16 p, { SCRIPTAPI_PRECHECKHEADER + lua_pushcfunction(L, script_error_handler); + int errorhandler = lua_gettop(L); + INodeDefManager *ndef = getServer()->ndef(); // If node doesn't exist, we don't know what callback to call @@ -201,18 +202,14 @@ void ScriptApiNodemeta::nodemeta_inventory_OnPut(v3s16 p, return; // Call function(pos, listname, index, stack, player) - // pos - push_v3s16(L, p); - // listname - lua_pushstring(L, listname.c_str()); - // index - lua_pushinteger(L, index + 1); - // stack - LuaItemStack::create(L, stack); - // player - objectrefGetOrCreate(player); - if(lua_pcall(L, 5, 0, 0)) - scriptError("error: %s", lua_tostring(L, -1)); + push_v3s16(L, p); // pos + lua_pushstring(L, listname.c_str()); // listname + lua_pushinteger(L, index + 1); // index + LuaItemStack::create(L, stack); // stack + objectrefGetOrCreate(player); // player + if(lua_pcall(L, 5, 0, errorhandler)) + scriptError(); + lua_pop(L, 1); // Pop error handler } // Report taken items @@ -222,6 +219,9 @@ void ScriptApiNodemeta::nodemeta_inventory_OnTake(v3s16 p, { SCRIPTAPI_PRECHECKHEADER + lua_pushcfunction(L, script_error_handler); + int errorhandler = lua_gettop(L); + INodeDefManager *ndef = getServer()->ndef(); // If node doesn't exist, we don't know what callback to call @@ -235,18 +235,14 @@ void ScriptApiNodemeta::nodemeta_inventory_OnTake(v3s16 p, return; // Call function(pos, listname, index, stack, player) - // pos - push_v3s16(L, p); - // listname - lua_pushstring(L, listname.c_str()); - // index - lua_pushinteger(L, index + 1); - // stack - LuaItemStack::create(L, stack); - // player - objectrefGetOrCreate(player); - if(lua_pcall(L, 5, 0, 0)) - scriptError("error: %s", lua_tostring(L, -1)); + push_v3s16(L, p); // pos + lua_pushstring(L, listname.c_str()); // listname + lua_pushinteger(L, index + 1); // index + LuaItemStack::create(L, stack); // stack + objectrefGetOrCreate(player); // player + if(lua_pcall(L, 5, 0, errorhandler)) + scriptError(); + lua_pop(L, 1); // Pop error handler } ScriptApiNodemeta::ScriptApiNodemeta() { diff --git a/src/script/cpp_api/s_server.cpp b/src/script/cpp_api/s_server.cpp index d41805b7b..4baf90636 100644 --- a/src/script/cpp_api/s_server.cpp +++ b/src/script/cpp_api/s_server.cpp @@ -27,13 +27,18 @@ bool ScriptApiServer::getAuth(const std::string &playername, { SCRIPTAPI_PRECHECKHEADER + lua_pushcfunction(L, script_error_handler); + int errorhandler = lua_gettop(L); + getAuthHandler(); lua_getfield(L, -1, "get_auth"); if(lua_type(L, -1) != LUA_TFUNCTION) throw LuaError(L, "Authentication handler missing get_auth"); lua_pushstring(L, playername.c_str()); - if(lua_pcall(L, 1, 1, 0)) - scriptError("error: %s", lua_tostring(L, -1)); + if(lua_pcall(L, 1, 1, errorhandler)) + scriptError(); + lua_remove(L, -2); // Remove auth handler + lua_remove(L, errorhandler); // Remove error handler // nil = login not allowed if(lua_isnil(L, -1)) @@ -49,8 +54,7 @@ bool ScriptApiServer::getAuth(const std::string &playername, lua_getfield(L, -1, "privileges"); if(!lua_istable(L, -1)) - throw LuaError(L, - "Authentication handler didn't return privilege table"); + throw LuaError(L, "Authentication handler didn't return privilege table"); if(dst_privs) readPrivileges(-1, *dst_privs); lua_pop(L, 1); @@ -68,6 +72,7 @@ void ScriptApiServer::getAuthHandler() lua_pop(L, 1); lua_getfield(L, -1, "builtin_auth_handler"); } + lua_remove(L, -2); // Remove minetest if(lua_type(L, -1) != LUA_TTABLE) throw LuaError(L, "Authentication handler table not valid"); } @@ -96,14 +101,19 @@ void ScriptApiServer::createAuth(const std::string &playername, { SCRIPTAPI_PRECHECKHEADER + lua_pushcfunction(L, script_error_handler); + int errorhandler = lua_gettop(L); + getAuthHandler(); lua_getfield(L, -1, "create_auth"); + lua_remove(L, -2); // Remove auth handler if(lua_type(L, -1) != LUA_TFUNCTION) throw LuaError(L, "Authentication handler missing create_auth"); lua_pushstring(L, playername.c_str()); lua_pushstring(L, password.c_str()); - if(lua_pcall(L, 2, 0, 0)) - scriptError("error: %s", lua_tostring(L, -1)); + if(lua_pcall(L, 2, 0, errorhandler)) + scriptError(); + lua_pop(L, 1); // Pop error handler } bool ScriptApiServer::setPassword(const std::string &playername, @@ -111,14 +121,19 @@ bool ScriptApiServer::setPassword(const std::string &playername, { SCRIPTAPI_PRECHECKHEADER + lua_pushcfunction(L, script_error_handler); + int errorhandler = lua_gettop(L); + getAuthHandler(); lua_getfield(L, -1, "set_password"); + lua_remove(L, -2); // Remove auth handler if(lua_type(L, -1) != LUA_TFUNCTION) throw LuaError(L, "Authentication handler missing set_password"); lua_pushstring(L, playername.c_str()); lua_pushstring(L, password.c_str()); - if(lua_pcall(L, 2, 1, 0)) - scriptError("error: %s", lua_tostring(L, -1)); + if(lua_pcall(L, 2, 1, errorhandler)) + scriptError(); + lua_remove(L, -2); // Remove error handler return lua_toboolean(L, -1); } diff --git a/src/script/lua_api/l_base.h b/src/script/lua_api/l_base.h index 71ebd215c..808043bd4 100644 --- a/src/script/lua_api/l_base.h +++ b/src/script/lua_api/l_base.h @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #define L_BASE_H_ #include "common/c_types.h" +#include "common/c_internal.h" extern "C" { #include diff --git a/src/script/lua_api/l_craft.cpp b/src/script/lua_api/l_craft.cpp index b0a47bfc1..c5732bad2 100644 --- a/src/script/lua_api/l_craft.cpp +++ b/src/script/lua_api/l_craft.cpp @@ -449,7 +449,7 @@ int ModApiCraft::l_get_all_craft_recipes(lua_State *L) lua_pushstring(L, &tmpout.item[0]); lua_setfield(L, -2, "output"); if (lua_pcall(L, 2, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); + script_error(L); } } return 1; diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp index 436eb014d..9bed23d47 100644 --- a/src/script/lua_api/l_env.cpp +++ b/src/script/lua_api/l_env.cpp @@ -53,28 +53,34 @@ void LuaABM::trigger(ServerEnvironment *env, v3s16 p, MapNode n, assert(lua_checkstack(L, 20)); StackUnroller stack_unroller(L); + lua_pushcfunction(L, script_error_handler); + int errorhandler = lua_gettop(L); + // Get minetest.registered_abms lua_getglobal(L, "minetest"); lua_getfield(L, -1, "registered_abms"); luaL_checktype(L, -1, LUA_TTABLE); - int registered_abms = lua_gettop(L); + lua_remove(L, -2); // Remove "minetest" // Get minetest.registered_abms[m_id] lua_pushnumber(L, m_id); - lua_gettable(L, registered_abms); + lua_gettable(L, -2); if(lua_isnil(L, -1)) assert(0); + lua_remove(L, -2); // Remove "registered_abms" // Call action luaL_checktype(L, -1, LUA_TTABLE); lua_getfield(L, -1, "action"); luaL_checktype(L, -1, LUA_TFUNCTION); + lua_remove(L, -2); // Remove "registered_abms[m_id]" push_v3s16(L, p); pushnode(L, n, env->getGameDef()->ndef()); lua_pushnumber(L, active_object_count); lua_pushnumber(L, active_object_count_wider); - if(lua_pcall(L, 4, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); + if(lua_pcall(L, 4, 0, errorhandler)) + script_error(L); + lua_pop(L, 1); // Pop error handler } // Exported functions @@ -370,15 +376,21 @@ int ModApiEnvMod::l_add_item(lua_State *L) ItemStack item = read_item(L, 2,getServer(L)); if(item.empty() || !item.isKnown(getServer(L)->idef())) return 0; + + lua_pushcfunction(L, script_error_handler); + int errorhandler = lua_gettop(L); + // Use minetest.spawn_item to spawn a __builtin:item lua_getglobal(L, "minetest"); lua_getfield(L, -1, "spawn_item"); + lua_remove(L, -2); // Remove minetest if(lua_isnil(L, -1)) return 0; lua_pushvalue(L, 1); lua_pushstring(L, item.getItemString().c_str()); - if(lua_pcall(L, 2, 1, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); + if(lua_pcall(L, 2, 1, errorhandler)) + script_error(L); + lua_remove(L, errorhandler); // Remove error handler return 1; /*lua_pushvalue(L, 1); lua_pushstring(L, "__builtin:item"); @@ -441,7 +453,7 @@ int ModApiEnvMod::l_get_objects_inside_radius(lua_State *L) lua_pushvalue(L, table); getScriptApiBase(L)->objectrefGetOrCreate(obj); if(lua_pcall(L, 2, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); + script_error(L); } return 1; } @@ -569,7 +581,7 @@ int ModApiEnvMod::l_find_nodes_in_area(lua_State *L) lua_pushvalue(L, table); push_v3s16(L, p); if(lua_pcall(L, 2, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); + script_error(L); } } return 1; diff --git a/src/script/lua_api/l_noise.cpp b/src/script/lua_api/l_noise.cpp index ecbda9fad..4b0c7932d 100644 --- a/src/script/lua_api/l_noise.cpp +++ b/src/script/lua_api/l_noise.cpp @@ -333,7 +333,10 @@ int LuaPseudoRandom::l_next(lua_State *L) throw LuaError(L, "PseudoRandom.next(): max < min"); } if(max - min != 32767 && max - min > 32767/5) - throw LuaError(L, "PseudoRandom.next() max-min is not 32767 and is > 32768/5. This is disallowed due to the bad random distribution the implementation would otherwise make."); + throw LuaError(L, "PseudoRandom.next() max-min is not 32767" + " and is > 32768/5. This is disallowed due to" + " the bad random distribution the" + " implementation would otherwise make."); PseudoRandom &pseudo = o->m_pseudo; int val = pseudo.next(); val = (val % (max-min+1)) + min; diff --git a/src/script/lua_api/l_rollback.cpp b/src/script/lua_api/l_rollback.cpp index 6076399ae..d5abe176e 100644 --- a/src/script/lua_api/l_rollback.cpp +++ b/src/script/lua_api/l_rollback.cpp @@ -66,7 +66,7 @@ int ModApiRollback::l_rollback_revert_actions_by(lua_State *L) lua_pushvalue(L, table); lua_pushstring(L, i->c_str()); if(lua_pcall(L, 2, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); + script_error(L); } lua_remove(L, -2); // Remove table lua_remove(L, -2); // Remove insert diff --git a/src/script/lua_api/l_server.cpp b/src/script/lua_api/l_server.cpp index 8e809c36a..19e2f1bcb 100644 --- a/src/script/lua_api/l_server.cpp +++ b/src/script/lua_api/l_server.cpp @@ -220,6 +220,7 @@ int ModApiServer::l_get_modpath(lua_State *L) int ModApiServer::l_get_modnames(lua_State *L) { NO_MAP_LOCK_REQUIRED; + // Get a list of mods std::list mods_unsorted, mods_sorted; getServer(L)->getModNames(mods_unsorted); @@ -263,7 +264,7 @@ int ModApiServer::l_get_modnames(lua_State *L) lua_pushstring(L, (*i).c_str()); if(lua_pcall(L, 2, 0, 0) != 0) { - script_error(L, "error: %s", lua_tostring(L, -1)); + script_error(L); } ++i; }